diff --git a/.buildkite/ftr_configs.yml b/.buildkite/ftr_configs.yml index 7abd52a1ea153..26e8d3855bf7b 100644 --- a/.buildkite/ftr_configs.yml +++ b/.buildkite/ftr_configs.yml @@ -15,7 +15,7 @@ disabled: - x-pack/test/fleet_api_integration/config.base.ts - x-pack/test/security_solution_api_integration/config/ess/config.base.ts - x-pack/test/security_solution_api_integration/config/serverless/config.base.ts - + - x-pack/test/security_solution_endpoint/config.base.ts # QA suites that are run out-of-band - x-pack/test/stack_functional_integration/configs/config.stack_functional_integration_base.js @@ -387,7 +387,9 @@ enabled: - x-pack/test/security_functional/expired_session.config.ts - x-pack/test/security_solution_endpoint_api_int/config.ts - x-pack/test/security_solution_endpoint/endpoint.config.ts + - x-pack/test/security_solution_endpoint/serverless.endpoint.config.ts - x-pack/test/security_solution_endpoint/integrations.config.ts + - x-pack/test/security_solution_endpoint/serverless.integrations.config.ts - x-pack/test/session_view/basic/config.ts - x-pack/test/spaces_api_integration/security_and_spaces/config_basic.ts - x-pack/test/spaces_api_integration/security_and_spaces/copy_to_space_config_basic.ts diff --git a/.buildkite/pipelines/pull_request/deploy_project.yml b/.buildkite/pipelines/pull_request/deploy_project.yml new file mode 100644 index 0000000000000..5d6e442542304 --- /dev/null +++ b/.buildkite/pipelines/pull_request/deploy_project.yml @@ -0,0 +1,11 @@ +steps: + - command: .buildkite/scripts/steps/serverless/build_and_deploy.sh + label: 'Build and Deploy Project' + agents: + queue: n2-16-spot + timeout_in_minutes: 60 + soft_fail: true + retry: + automatic: + - exit_status: '-1' + limit: 3 diff --git a/.buildkite/scripts/lifecycle/post_command.sh b/.buildkite/scripts/lifecycle/post_command.sh index eeb7fa0ef410f..d0a5837ed5a67 100755 --- a/.buildkite/scripts/lifecycle/post_command.sh +++ b/.buildkite/scripts/lifecycle/post_command.sh @@ -15,6 +15,7 @@ if [[ "$IS_TEST_EXECUTION_STEP" == "true" ]]; then buildkite-agent artifact upload 'target/kibana-*' buildkite-agent artifact upload 'target/kibana-security-solution/**/*.png' buildkite-agent artifact upload 'target/kibana-osquery/**/*.png' + buildkite-agent artifact upload 'target/kibana-osquery/**/*.mp4' buildkite-agent artifact upload 'target/kibana-fleet/**/*.png' buildkite-agent artifact upload 'target/test-metrics/*' buildkite-agent artifact upload 'target/test-suites-ci-plan.json' diff --git a/.buildkite/scripts/lifecycle/pre_command.sh b/.buildkite/scripts/lifecycle/pre_command.sh index b945f08d1dfd9..9cfa973b28024 100755 --- a/.buildkite/scripts/lifecycle/pre_command.sh +++ b/.buildkite/scripts/lifecycle/pre_command.sh @@ -115,6 +115,12 @@ export KIBANA_DOCKER_PASSWORD EC_API_KEY="$(retry 5 5 vault read -field=pr_deploy_api_key secret/kibana-issues/dev/kibana-ci-cloud-deploy)" export EC_API_KEY +PROJECT_API_KEY="$(retry 5 5 vault read -field=pr_deploy_api_key secret/kibana-issues/dev/kibana-ci-project-deploy)" +export PROJECT_API_KEY + +PROJECT_API_DOMAIN="$(retry 5 5 vault read -field=pr_deploy_domain secret/kibana-issues/dev/kibana-ci-project-deploy)" +export PROJECT_API_DOMAIN + SYNTHETICS_SERVICE_USERNAME="$(retry 5 5 vault read -field=username secret/kibana-issues/dev/kibana-ci-synthetics-credentials)" export SYNTHETICS_SERVICE_USERNAME diff --git a/.buildkite/scripts/pipelines/pull_request/pipeline.ts b/.buildkite/scripts/pipelines/pull_request/pipeline.ts index 3eb5fd250e2b7..fa320a6853cc8 100644 --- a/.buildkite/scripts/pipelines/pull_request/pipeline.ts +++ b/.buildkite/scripts/pipelines/pull_request/pipeline.ts @@ -136,6 +136,14 @@ const uploadPipeline = (pipelineContent: string | object) => { pipeline.push(getPipeline('.buildkite/pipelines/pull_request/deploy_cloud.yml')); } + if ( + GITHUB_PR_LABELS.includes('ci:project-deploy-es') || + GITHUB_PR_LABELS.includes('ci:project-deploy-oblt') || + GITHUB_PR_LABELS.includes('ci:project-deploy-security') + ) { + pipeline.push(getPipeline('.buildkite/pipelines/pull_request/deploy_project.yml')); + } + if (GITHUB_PR_LABELS.includes('ci:build-serverless-image')) { pipeline.push(getPipeline('.buildkite/pipelines/artifacts_container_image.yml')); } diff --git a/.buildkite/scripts/steps/artifacts/docker_image.sh b/.buildkite/scripts/steps/artifacts/docker_image.sh index d57770cdaddf9..9b4edc16024f0 100755 --- a/.buildkite/scripts/steps/artifacts/docker_image.sh +++ b/.buildkite/scripts/steps/artifacts/docker_image.sh @@ -14,7 +14,7 @@ else fi KIBANA_BASE_IMAGE="docker.elastic.co/kibana-ci/kibana-serverless" -KIBANA_IMAGE="$KIBANA_BASE_IMAGE:$KIBANA_IMAGE_TAG" +export KIBANA_IMAGE="$KIBANA_BASE_IMAGE:$KIBANA_IMAGE_TAG" echo "--- Verify manifest does not already exist" echo "$KIBANA_DOCKER_PASSWORD" | docker login -u "$KIBANA_DOCKER_USERNAME" --password-stdin docker.elastic.co diff --git a/.buildkite/scripts/steps/checks.sh b/.buildkite/scripts/steps/checks.sh index 639e3f02ef1df..4d9461a6a2bff 100755 --- a/.buildkite/scripts/steps/checks.sh +++ b/.buildkite/scripts/steps/checks.sh @@ -24,4 +24,5 @@ export DISABLE_BOOTSTRAP_VALIDATION=false .buildkite/scripts/steps/checks/saved_objects_compat_changes.sh .buildkite/scripts/steps/checks/saved_objects_definition_change.sh .buildkite/scripts/steps/code_generation/security_solution_codegen.sh +.buildkite/scripts/steps/code_generation/osquery_codegen.sh .buildkite/scripts/steps/checks/yarn_deduplicate.sh diff --git a/.buildkite/scripts/steps/code_generation/osquery_codegen.sh b/.buildkite/scripts/steps/code_generation/osquery_codegen.sh new file mode 100755 index 0000000000000..7c04f4aecd442 --- /dev/null +++ b/.buildkite/scripts/steps/code_generation/osquery_codegen.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env bash + +set -euo pipefail + +source .buildkite/scripts/common/util.sh + +echo --- Osquery OpenAPI Code Generation + +(cd x-pack/plugins/osquery && yarn openapi:generate) +check_for_changed_files "yarn openapi:generate" true diff --git a/.buildkite/scripts/steps/serverless/build_and_deploy.sh b/.buildkite/scripts/steps/serverless/build_and_deploy.sh new file mode 100644 index 0000000000000..837757a587786 --- /dev/null +++ b/.buildkite/scripts/steps/serverless/build_and_deploy.sh @@ -0,0 +1,96 @@ +#!/bin/bash + +set -euo pipefail + + +source .buildkite/scripts/common/util.sh +source .buildkite/scripts/steps/artifacts/docker_image.sh + +PROJECT_TYPE="" +is_pr_with_label "ci:project-deploy-es" && PROJECT_TYPE="elasticsearch" +is_pr_with_label "ci:project-deploy-oblt" && PROJECT_TYPE="observability" +is_pr_with_label "ci:project-deploy-security" && PROJECT_TYPE="security" +if [ -z "${PROJECT_TYPE}" ]; then + echo "Mising project type" + exit 10 +fi + +PROJECT_NAME="kibana-pr-$BUILDKITE_PULL_REQUEST-$PROJECT_TYPE" +PROJECT_CREATE_CONFIGURATION='{ + "name": "'"$PROJECT_NAME"'", + "region_id": "aws-eu-west-1", + "overrides": { + "kibana": { + "docker_image": "'"$KIBANA_IMAGE"'" + } + } +}' +PROJECT_UPDATE_CONFIGURATION='{ + "name": "'"$PROJECT_NAME"'", + "overrides": { + "kibana": { + "docker_image": "'"$KIBANA_IMAGE"'" + } + } +}' + +echo "--- Create project" +DEPLOY_LOGS=$(mktemp --suffix ".json") + +echo "Checking if project already exists..." +curl -s \ + -H "Authorization: ApiKey $PROJECT_API_KEY" \ + "${PROJECT_API_DOMAIN}/api/v1/serverless/projects/${PROJECT_TYPE}" \ + -XGET &>> $DEPLOY_LOGS + +PROJECT_ID=$(jq -r --slurp '[.[0].items[] | select(.name == "'$PROJECT_NAME'")] | .[0].id' $DEPLOY_LOGS) +if [ -z "${PROJECT_ID}" ] || [ "$PROJECT_ID" = 'null' ]; then + echo "Creating project..." + curl -s \ + -H "Authorization: ApiKey $PROJECT_API_KEY" \ + -H "Content-Type: application/json" \ + "${PROJECT_API_DOMAIN}/api/v1/serverless/projects/${PROJECT_TYPE}" \ + -XPOST -d "$PROJECT_CREATE_CONFIGURATION" &>> $DEPLOY_LOGS + + PROJECT_ID=$(jq -r --slurp '.[1].id' $DEPLOY_LOGS) + + echo "Get credentials..." + curl -s -XPOST -H "Authorization: ApiKey $PROJECT_API_KEY" \ + "${PROJECT_API_DOMAIN}/api/v1/serverless/projects/${PROJECT_TYPE}/${PROJECT_ID}/_reset-credentials" &>> $DEPLOY_LOGS + + PROJECT_USERNAME=$(jq -r --slurp '.[2].username' $DEPLOY_LOGS) + PROJECT_PASSWORD=$(jq -r --slurp '.[2].password' $DEPLOY_LOGS) + + echo "Write to vault..." + VAULT_ROLE_ID="$(retry 5 15 gcloud secrets versions access latest --secret=kibana-buildkite-vault-role-id)" + VAULT_SECRET_ID="$(retry 5 15 gcloud secrets versions access latest --secret=kibana-buildkite-vault-secret-id)" + VAULT_TOKEN=$(retry 5 30 vault write -field=token auth/approle/login role_id="$VAULT_ROLE_ID" secret_id="$VAULT_SECRET_ID") + retry 5 30 vault login -no-print "$VAULT_TOKEN" + retry 5 5 vault write "secret/kibana-issues/dev/cloud-deploy/$PROJECT_NAME" username="$PROJECT_USERNAME" password="$PROJECT_PASSWORD" id="$PROJECT_ID" +else + echo "Updating project..." + curl -s \ + -H "Authorization: ApiKey $PROJECT_API_KEY" \ + -H "Content-Type: application/json" \ + "${PROJECT_API_DOMAIN}/api/v1/serverless/projects/${PROJECT_TYPE}/${PROJECT_ID}" \ + -XPUT -d "$PROJECT_UPDATE_CONFIGURATION" &>> $DEPLOY_LOGS +fi + +PROJECT_KIBANA_URL=$(jq -r --slurp '.[1].endpoints.kibana' $DEPLOY_LOGS) +PROJECT_KIBANA_LOGIN_URL="${PROJECT_KIBANA_URL}/login" +PROJECT_ELASTICSEARCH_URL=$(jq -r --slurp '.[1].endpoints.elasticsearch' $DEPLOY_LOGS) + +cat << EOF | buildkite-agent annotate --style "info" --context project + ### Project Deployment + + Kibana: $PROJECT_KIBANA_LOGIN_URL + + Elasticsearch: $PROJECT_ELASTICSEARCH_URL + + Credentials: \`vault read secret/kibana-issues/dev/cloud-deploy/$PROJECT_NAME\` + + Kibana image: \`$KIBANA_IMAGE\` +EOF + +buildkite-agent meta-data set pr_comment:deploy_project:head "* [Project Deployment](${PROJECT_KIBANA_LOGIN_URL})" +buildkite-agent meta-data set pr_comment:early_comment_job_id "$BUILDKITE_JOB_ID" diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index fb41f6d904b10..d029e3952dfec 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -676,9 +676,7 @@ examples/share_examples @elastic/appex-sharedux src/plugins/share @elastic/appex-sharedux packages/kbn-shared-svg @elastic/apm-ui packages/shared-ux/avatar/solution @elastic/appex-sharedux -packages/shared-ux/button/exit_full_screen/impl @elastic/appex-sharedux -packages/shared-ux/button/exit_full_screen/mocks @elastic/appex-sharedux -packages/shared-ux/button/exit_full_screen/types @elastic/appex-sharedux +packages/shared-ux/button/exit_full_screen @elastic/appex-sharedux packages/shared-ux/button_toolbar @elastic/appex-sharedux packages/shared-ux/card/no_data/impl @elastic/appex-sharedux packages/shared-ux/card/no_data/mocks @elastic/appex-sharedux diff --git a/api_docs/actions.mdx b/api_docs/actions.mdx index 37ee56c38eef2..a53b97775e023 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'actions'] --- import actionsObj from './actions.devdocs.json'; diff --git a/api_docs/advanced_settings.mdx b/api_docs/advanced_settings.mdx index 040132929a034..8131715185e7a 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'advancedSettings'] --- import advancedSettingsObj from './advanced_settings.devdocs.json'; diff --git a/api_docs/aiops.mdx b/api_docs/aiops.mdx index 4cc88f5760194..21ab35960689f 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'aiops'] --- import aiopsObj from './aiops.devdocs.json'; diff --git a/api_docs/alerting.devdocs.json b/api_docs/alerting.devdocs.json index a8c688261c4f7..e91a46ecfb7fb 100644 --- a/api_docs/alerting.devdocs.json +++ b/api_docs/alerting.devdocs.json @@ -109,8 +109,8 @@ "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", @@ -125,8 +125,8 @@ "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": [ @@ -2949,7 +2949,7 @@ "label": "snoozeSchedule", "description": [], "signature": [ - "Readonly<{ id?: string | undefined; skipRecurrences?: string[] | undefined; } & { duration: number; rRule: Readonly<{ count?: number | undefined; interval?: number | undefined; freq?: 0 | 2 | 6 | 5 | 4 | 3 | 1 | undefined; until?: string | undefined; byweekday?: (string | number)[] | undefined; bymonth?: number[] | undefined; wkst?: \"MO\" | \"TU\" | \"WE\" | \"TH\" | \"FR\" | \"SA\" | \"SU\" | undefined; bysetpos?: number[] | undefined; } & { dtstart: string; tzid: string; bymonthday: number[]; byyearday: number[]; byweekno: number[]; byhour: number[]; byminute: number[]; bysecond: number[]; }>; }>[] | undefined" + "Readonly<{ id?: string | undefined; skipRecurrences?: string[] | undefined; } & { duration: number; rRule: Readonly<{ count?: number | undefined; interval?: number | undefined; freq?: 0 | 2 | 6 | 5 | 4 | 3 | 1 | undefined; until?: string | undefined; byweekday?: (string | number)[] | undefined; bymonthday?: number[] | undefined; bymonth?: number[] | undefined; wkst?: \"MO\" | \"TU\" | \"WE\" | \"TH\" | \"FR\" | \"SA\" | \"SU\" | undefined; bysetpos?: number[] | undefined; byyearday?: number[] | undefined; byweekno?: number[] | undefined; byhour?: number[] | undefined; byminute?: number[] | undefined; bysecond?: number[] | undefined; } & { dtstart: string; tzid: string; }>; }>[] | undefined" ], "path": "x-pack/plugins/alerting/server/application/rule/types/rule.ts", "deprecated": false, @@ -4492,7 +4492,7 @@ "label": "AlertingRulesConfig", "description": [], "signature": [ - "Pick; maxScheduledPerMinute: number; run: Readonly<{ timeout?: string | undefined; ruleTypeOverrides?: Readonly<{ timeout?: string | undefined; } & { id: string; }>[] | undefined; } & { actions: Readonly<{ connectorTypeOverrides?: Readonly<{ max?: number | undefined; } & { id: string; }>[] | undefined; } & { max: number; }>; alerts: Readonly<{} & { max: number; }>; }>; }>, \"minimumScheduleInterval\" | \"maxScheduledPerMinute\"> & { isUsingSecurity: boolean; }" + "Pick; maxScheduledPerMinute: number; run: Readonly<{ timeout?: string | undefined; ruleTypeOverrides?: Readonly<{ timeout?: string | undefined; } & { id: string; }>[] | undefined; } & { actions: Readonly<{ connectorTypeOverrides?: Readonly<{ max?: number | undefined; } & { id: string; }>[] | undefined; } & { max: number; }>; alerts: Readonly<{} & { max: number; }>; }>; }>, \"minimumScheduleInterval\" | \"maxScheduledPerMinute\"> & { isUsingSecurity: boolean; }" ], "path": "x-pack/plugins/alerting/server/config.ts", "deprecated": false, @@ -4950,7 +4950,7 @@ ")[]; total: number; taskIdsFailedToBeEnabled: string[]; }>; bulkDisableRules: (options: Readonly<{ filter?: string | undefined; ids?: string[] | undefined; } & {}>) => Promise<", "BulkDisableRulesResult", ">>; updateApiKey: (options: { id: string; }) => Promise; enable: (options: { id: string; }) => Promise; disable: (options: { id: string; }) => Promise; snooze: (options: ", - "SnoozeParams", + "SnoozeRuleOptions", ") => Promise; unsnooze: (options: ", "UnsnoozeParams", ") => Promise; clearExpiredSnoozes: (options: { rule: Pick<", @@ -10491,7 +10491,7 @@ "section": "def-common.SavedObjectsResolveResponse", "text": "SavedObjectsResolveResponse" }, - ", \"saved_object\">" + ", \"saved_object\"> & { outcome: string; alias_target_id?: string | undefined; }" ], "path": "x-pack/plugins/alerting/common/rule.ts", "deprecated": false, diff --git a/api_docs/alerting.mdx b/api_docs/alerting.mdx index 1fb373c54caf7..e68260d8912b2 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'alerting'] --- import alertingObj from './alerting.devdocs.json'; diff --git a/api_docs/apm.devdocs.json b/api_docs/apm.devdocs.json index 6277fef104482..2878d3c994d49 100644 --- a/api_docs/apm.devdocs.json +++ b/api_docs/apm.devdocs.json @@ -902,18 +902,24 @@ "; \"GET /internal/apm/assistant/get_error_document\": { endpoint: \"GET /internal/apm/assistant/get_error_document\"; params?: ", "TypeC", "<{ query: ", + "IntersectionC", + "<[", "TypeC", "<{ start: ", "StringC", "; end: ", "StringC", - "; 'error.grouping_name': ", + "; }>, ", + "PartialC", + "<{ 'error.grouping_name': ", + "StringC", + "; 'service.name': ", "StringC", - "; }>; }> | undefined; handler: ({}: ", + "; }>]>; }> | undefined; handler: ({}: ", "APMRouteHandlerResources", - " & { params: { query: { start: string; end: string; 'error.grouping_name': string; }; }; }) => Promise<{ content: Partial<", + " & { params: { query: { start: string; end: string; } & { 'error.grouping_name'?: string | undefined; 'service.name'?: string | undefined; }; }; }) => Promise<{ content: Partial<", "APMError", - "> | undefined; }>; } & ", + ">[]; }>; } & ", "APMRouteCreateOptions", "; \"GET /internal/apm/assistant/get_service_summary\": { endpoint: \"GET /internal/apm/assistant/get_service_summary\"; params?: ", "TypeC", diff --git a/api_docs/apm.mdx b/api_docs/apm.mdx index 4ee6b99f2566e..9c7afd791f5e8 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'apm'] --- import apmObj from './apm.devdocs.json'; diff --git a/api_docs/apm_data_access.mdx b/api_docs/apm_data_access.mdx index 848c796ef9e71..8b52b62737dd9 100644 --- a/api_docs/apm_data_access.mdx +++ b/api_docs/apm_data_access.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/apmDataAccess title: "apmDataAccess" image: https://source.unsplash.com/400x175/?github description: API docs for the apmDataAccess plugin -date: 2023-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'apmDataAccess'] --- import apmDataAccessObj from './apm_data_access.devdocs.json'; diff --git a/api_docs/asset_manager.mdx b/api_docs/asset_manager.mdx index 5db8bf04ddfda..2584cef535fa0 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-10-31 +date: 2023-11-03 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 f9f91e6acea10..b6651aea49ac0 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-10-31 +date: 2023-11-03 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 be5a77fb303e8..54682bd838f0d 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-10-31 +date: 2023-11-03 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 7c16afc403e20..589188eb06e60 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'canvas'] --- import canvasObj from './canvas.devdocs.json'; diff --git a/api_docs/cases.mdx b/api_docs/cases.mdx index a8e28efbb3bf1..632797a8ef81d 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cases'] --- import casesObj from './cases.devdocs.json'; diff --git a/api_docs/charts.mdx b/api_docs/charts.mdx index 0c33f30644e2d..32c6bf823d25d 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'charts'] --- import chartsObj from './charts.devdocs.json'; diff --git a/api_docs/cloud.mdx b/api_docs/cloud.mdx index 1dee7bb622860..0466d52e99fdd 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloud'] --- import cloudObj from './cloud.devdocs.json'; diff --git a/api_docs/cloud_data_migration.mdx b/api_docs/cloud_data_migration.mdx index c2172ef715a34..26cdab11b3b3c 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloudDataMigration'] --- import cloudDataMigrationObj from './cloud_data_migration.devdocs.json'; diff --git a/api_docs/cloud_defend.mdx b/api_docs/cloud_defend.mdx index f4fc1abfe1023..9e1e7f8191a21 100644 --- a/api_docs/cloud_defend.mdx +++ b/api_docs/cloud_defend.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cloudDefend title: "cloudDefend" image: https://source.unsplash.com/400x175/?github description: API docs for the cloudDefend plugin -date: 2023-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloudDefend'] --- import cloudDefendObj from './cloud_defend.devdocs.json'; diff --git a/api_docs/cloud_experiments.mdx b/api_docs/cloud_experiments.mdx index bc65bcb7f9c54..e081cf473dc11 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-10-31 +date: 2023-11-03 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 d8915acf6e1f1..17261600100ed 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-10-31 +date: 2023-11-03 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 0a24b4d15cf4c..377cde5b1e221 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-10-31 +date: 2023-11-03 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 0cf7bf4f96427..291e3926ad678 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'contentManagement'] --- import contentManagementObj from './content_management.devdocs.json'; diff --git a/api_docs/controls.mdx b/api_docs/controls.mdx index febc589d44517..3c8a1f75e28cf 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-10-31 +date: 2023-11-03 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 831585890d6f0..f1a522cff93fe 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'customIntegrations'] --- import customIntegrationsObj from './custom_integrations.devdocs.json'; diff --git a/api_docs/dashboard.mdx b/api_docs/dashboard.mdx index 9ac9f2eada99b..0ab9f3902b5b9 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dashboard'] --- import dashboardObj from './dashboard.devdocs.json'; diff --git a/api_docs/dashboard_enhanced.mdx b/api_docs/dashboard_enhanced.mdx index 65ef6d7d54aea..cd806297d4363 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-10-31 +date: 2023-11-03 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 893f44d9b139a..a45dcac495005 100644 --- a/api_docs/data.devdocs.json +++ b/api_docs/data.devdocs.json @@ -12531,14 +12531,14 @@ "plugin": "stackAlerts", "path": "x-pack/plugins/stack_alerts/public/rule_types/geo_containment/rule_form/entity_form.tsx" }, - { - "plugin": "infra", - "path": "x-pack/plugins/infra/public/hooks/use_kibana_index_patterns.ts" - }, { "plugin": "graph", "path": "x-pack/plugins/graph/public/plugin.ts" }, + { + "plugin": "infra", + "path": "x-pack/plugins/infra/public/hooks/use_kibana_index_patterns.ts" + }, { "plugin": "inputControlVis", "path": "src/plugins/input_control_vis/public/control/list_control_factory.ts" @@ -12627,10 +12627,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" @@ -12647,6 +12643,10 @@ "plugin": "dataVisualizer", "path": "x-pack/plugins/data_visualizer/public/application/data_drift/charts/default_value_formatter.ts" }, + { + "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" @@ -13359,14 +13359,14 @@ "deprecated": true, "trackAdoption": false, "references": [ - { - "plugin": "graph", - "path": "x-pack/plugins/graph/public/services/persistence/deserialize.ts" - }, { "plugin": "visTypeTimeseries", "path": "src/plugins/vis_types/timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.ts" }, + { + "plugin": "graph", + "path": "x-pack/plugins/graph/public/services/persistence/deserialize.ts" + }, { "plugin": "graph", "path": "x-pack/plugins/graph/public/state_management/datasource.test.ts" @@ -19506,14 +19506,14 @@ "deprecated": true, "trackAdoption": false, "references": [ - { - "plugin": "graph", - "path": "x-pack/plugins/graph/public/services/persistence/deserialize.ts" - }, { "plugin": "visTypeTimeseries", "path": "src/plugins/vis_types/timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.ts" }, + { + "plugin": "graph", + "path": "x-pack/plugins/graph/public/services/persistence/deserialize.ts" + }, { "plugin": "graph", "path": "x-pack/plugins/graph/public/state_management/datasource.test.ts" diff --git a/api_docs/data.mdx b/api_docs/data.mdx index 3052d550a8359..5c5f7693a8456 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'data'] --- import dataObj from './data.devdocs.json'; diff --git a/api_docs/data_query.mdx b/api_docs/data_query.mdx index d9394e19a3558..cb2053bbb1ae1 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'data.query'] --- import dataQueryObj from './data_query.devdocs.json'; diff --git a/api_docs/data_search.mdx b/api_docs/data_search.mdx index a8fd254793f73..4fe6f4d00e64a 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'data.search'] --- import dataSearchObj from './data_search.devdocs.json'; diff --git a/api_docs/data_view_editor.mdx b/api_docs/data_view_editor.mdx index 88b55492aeb22..f4f758ea3388a 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataViewEditor'] --- import dataViewEditorObj from './data_view_editor.devdocs.json'; diff --git a/api_docs/data_view_field_editor.mdx b/api_docs/data_view_field_editor.mdx index 3c9861aeab09d..f1128b3d7a96e 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-10-31 +date: 2023-11-03 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 2441039294578..ebeaf20cbdd29 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-10-31 +date: 2023-11-03 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 f94efb6ef7d6c..c4efdd100341f 100644 --- a/api_docs/data_views.devdocs.json +++ b/api_docs/data_views.devdocs.json @@ -323,14 +323,14 @@ "deprecated": true, "trackAdoption": false, "references": [ - { - "plugin": "graph", - "path": "x-pack/plugins/graph/public/services/persistence/deserialize.ts" - }, { "plugin": "visTypeTimeseries", "path": "src/plugins/vis_types/timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.ts" }, + { + "plugin": "graph", + "path": "x-pack/plugins/graph/public/services/persistence/deserialize.ts" + }, { "plugin": "graph", "path": "x-pack/plugins/graph/public/state_management/datasource.test.ts" @@ -6712,14 +6712,14 @@ "deprecated": true, "trackAdoption": false, "references": [ - { - "plugin": "graph", - "path": "x-pack/plugins/graph/public/services/persistence/deserialize.ts" - }, { "plugin": "visTypeTimeseries", "path": "src/plugins/vis_types/timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.ts" }, + { + "plugin": "graph", + "path": "x-pack/plugins/graph/public/services/persistence/deserialize.ts" + }, { "plugin": "graph", "path": "x-pack/plugins/graph/public/state_management/datasource.test.ts" @@ -12140,14 +12140,14 @@ "deprecated": true, "trackAdoption": false, "references": [ - { - "plugin": "graph", - "path": "x-pack/plugins/graph/public/services/persistence/deserialize.ts" - }, { "plugin": "visTypeTimeseries", "path": "src/plugins/vis_types/timeseries/server/lib/search_strategies/strategies/abstract_search_strategy.ts" }, + { + "plugin": "graph", + "path": "x-pack/plugins/graph/public/services/persistence/deserialize.ts" + }, { "plugin": "graph", "path": "x-pack/plugins/graph/public/state_management/datasource.test.ts" diff --git a/api_docs/data_views.mdx b/api_docs/data_views.mdx index 5a3e59b32df7c..22ada9638a4bb 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataViews'] --- import dataViewsObj from './data_views.devdocs.json'; diff --git a/api_docs/data_visualizer.mdx b/api_docs/data_visualizer.mdx index 44cfbbe28ad11..277e4ad5f5742 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-10-31 +date: 2023-11-03 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 774ddaaa0cb3a..8350ade5cac36 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- @@ -16,18 +16,18 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | Deprecated API | Referencing plugin(s) | Remove By | | ---------------|-----------|-----------| -| | stackAlerts, ml | - | +| | ml, stackAlerts | - | | | ruleRegistry, observability, ml, infra, monitoring, securitySolution, stackAlerts, synthetics, transform, uptime | - | -| | stackAlerts, alerting, securitySolution, inputControlVis | - | -| | stackAlerts, infra, graph, inputControlVis, securitySolution, savedObjects | - | -| | dashboard, stackAlerts, dataVisualizer, expressionPartitionVis | - | -| | stackAlerts, alerting, securitySolution, inputControlVis | - | | | home, data, esUiShared, savedObjectsManagement, exploratoryView, fleet, ml, apm, indexLifecycleManagement, observabilityOnboarding, synthetics, upgradeAssistant, uptime, ux, kibanaOverview | - | -| | share, uiActions, guidedOnboarding, home, serverless, management, spaces, savedObjects, indexManagement, visualizations, controls, dashboard, savedObjectsTagging, expressionXY, lens, expressionMetricVis, expressionGauge, security, alerting, triggersActionsUi, cases, aiops, advancedSettings, exploratoryView, fleet, licenseManagement, maps, dataVisualizer, ml, 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 | - | +| | share, uiActions, guidedOnboarding, home, serverless, management, spaces, savedObjects, indexManagement, visualizations, controls, dashboard, savedObjectsTagging, expressionXY, lens, expressionMetricVis, expressionGauge, security, alerting, triggersActionsUi, cases, aiops, advancedSettings, exploratoryView, fleet, metricsDataAccess, licenseManagement, maps, dataVisualizer, ml, profiling, apm, expressionImage, expressionMetric, expressionError, expressionRevealImage, expressionRepeatImage, expressionShape, crossClusterReplication, enterpriseSearch, globalSearchBar, graph, grokdebugger, indexLifecycleManagement, infra, 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, logstash, securitySolution, cloudChat | - | | | actions, ml, savedObjectsTagging, enterpriseSearch | - | | | @kbn/core-saved-objects-browser-internal, @kbn/core, savedObjects, 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 | - | +| | stackAlerts, alerting, securitySolution, inputControlVis | - | +| | stackAlerts, graph, infra, inputControlVis, securitySolution, savedObjects | - | +| | dashboard, dataVisualizer, stackAlerts, expressionPartitionVis | - | +| | stackAlerts, alerting, securitySolution, inputControlVis | - | | | observability, @kbn/securitysolution-data-table, securitySolution | - | | | monitoring | - | | | inspector, data, savedObjects, runtimeFields, indexManagement, dataViewEditor, unifiedSearch, embeddable, visualizations, controls, dashboard, licensing, savedObjectsTagging, dataViewFieldEditor, lens, security, triggersActionsUi, cases, observabilityShared, advancedSettings, exploratoryView, fleet, telemetry, maps, banners, reporting, timelines, cloudSecurityPosture, dashboardEnhanced, imageEmbeddable, graph, monitoring, securitySolution, synthetics, uptime, cloudLinks, console, dataViewManagement, eventAnnotationListing, filesManagement, uiActions, visTypeVislib | - | @@ -43,7 +43,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | 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, savedSearch, canvas, graph, visualizations, lists, maps, securitySolution, dashboard, @kbn/core-test-helpers-so-type-serializer | - | +| | @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 | - | | | lists, securitySolution, @kbn/securitysolution-io-ts-list-types | - | | | lists, securitySolution, @kbn/securitysolution-io-ts-list-types | - | | | lists, securitySolution, @kbn/securitysolution-io-ts-list-types | - | @@ -93,9 +93,9 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | @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 | - | -| | graph, visTypeTimeseries, dataViewManagement, dataViews | - | -| | graph, visTypeTimeseries, dataViewManagement, dataViews | - | -| | graph, visTypeTimeseries, dataViewManagement | - | +| | visTypeTimeseries, graph, dataViewManagement, dataViews | - | +| | visTypeTimeseries, graph, dataViewManagement, dataViews | - | +| | visTypeTimeseries, graph, dataViewManagement | - | | | visualizations, graph | - | | | @kbn/core, lens, savedObjects | - | | | dataViews, maps | - | diff --git a/api_docs/deprecations_by_plugin.mdx b/api_docs/deprecations_by_plugin.mdx index c079fa70cc42b..0249cc67b4f57 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- @@ -1096,6 +1096,14 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] +## metricsDataAccess + +| Deprecated API | Reference location(s) | Remove By | +| ---------------|-----------|-----------| +| | [common_providers.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/metrics_data_access/public/apps/common_providers.tsx#:~:text=KibanaThemeProvider), [common_providers.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/metrics_data_access/public/apps/common_providers.tsx#:~:text=KibanaThemeProvider), [common_providers.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/metrics_data_access/public/apps/common_providers.tsx#:~:text=KibanaThemeProvider) | - | + + + ## ml | Deprecated API | Reference location(s) | Remove By | diff --git a/api_docs/deprecations_by_team.mdx b/api_docs/deprecations_by_team.mdx index 70360a7d7b8d8..b381753ec7c55 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- diff --git a/api_docs/dev_tools.mdx b/api_docs/dev_tools.mdx index 23f238c032a9d..c5a7107ab3e4e 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'devTools'] --- import devToolsObj from './dev_tools.devdocs.json'; diff --git a/api_docs/discover.mdx b/api_docs/discover.mdx index f640433dadb64..e7e1e8f58d9f7 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'discover'] --- import discoverObj from './discover.devdocs.json'; diff --git a/api_docs/discover_enhanced.mdx b/api_docs/discover_enhanced.mdx index bc917ed304cc5..3930137991d63 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-10-31 +date: 2023-11-03 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 9b5709b6fb1a7..b66aaa51c0797 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'ecsDataQualityDashboard'] --- import ecsDataQualityDashboardObj from './ecs_data_quality_dashboard.devdocs.json'; diff --git a/api_docs/elastic_assistant.mdx b/api_docs/elastic_assistant.mdx index d48b3e19a765d..a40d450645483 100644 --- a/api_docs/elastic_assistant.mdx +++ b/api_docs/elastic_assistant.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/elasticAssistant title: "elasticAssistant" image: https://source.unsplash.com/400x175/?github description: API docs for the elasticAssistant plugin -date: 2023-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'elasticAssistant'] --- import elasticAssistantObj from './elastic_assistant.devdocs.json'; diff --git a/api_docs/embeddable.mdx b/api_docs/embeddable.mdx index 845ec6cefb595..d78884af725b2 100644 --- a/api_docs/embeddable.mdx +++ b/api_docs/embeddable.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/embeddable title: "embeddable" image: https://source.unsplash.com/400x175/?github description: API docs for the embeddable plugin -date: 2023-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'embeddable'] --- import embeddableObj from './embeddable.devdocs.json'; diff --git a/api_docs/embeddable_enhanced.mdx b/api_docs/embeddable_enhanced.mdx index c44f7ce480200..08855c4e87dd2 100644 --- a/api_docs/embeddable_enhanced.mdx +++ b/api_docs/embeddable_enhanced.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/embeddableEnhanced title: "embeddableEnhanced" image: https://source.unsplash.com/400x175/?github description: API docs for the embeddableEnhanced plugin -date: 2023-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'embeddableEnhanced'] --- import embeddableEnhancedObj from './embeddable_enhanced.devdocs.json'; diff --git a/api_docs/encrypted_saved_objects.mdx b/api_docs/encrypted_saved_objects.mdx index b3e25949e5f40..9202a4fb59585 100644 --- a/api_docs/encrypted_saved_objects.mdx +++ b/api_docs/encrypted_saved_objects.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/encryptedSavedObjects title: "encryptedSavedObjects" image: https://source.unsplash.com/400x175/?github description: API docs for the encryptedSavedObjects plugin -date: 2023-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'encryptedSavedObjects'] --- import encryptedSavedObjectsObj from './encrypted_saved_objects.devdocs.json'; diff --git a/api_docs/enterprise_search.mdx b/api_docs/enterprise_search.mdx index 389c292fdd009..195527461651e 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'enterpriseSearch'] --- import enterpriseSearchObj from './enterprise_search.devdocs.json'; diff --git a/api_docs/es_ui_shared.mdx b/api_docs/es_ui_shared.mdx index 6a4447799b4d0..a23db776de25d 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-10-31 +date: 2023-11-03 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 f107d3ee6c768..c4f90f98b9a1a 100644 --- a/api_docs/event_annotation.devdocs.json +++ b/api_docs/event_annotation.devdocs.json @@ -1209,7 +1209,7 @@ "signature": [ "{ item: ", "EventAnnotationGroupSavedObject", - "; meta: { outcome: \"conflict\" | \"exactMatch\" | \"aliasMatch\"; aliasTargetId?: string | undefined; aliasPurpose?: \"savedObjectConversion\" | \"savedObjectImport\" | undefined; }; }" + "; meta: { outcome: \"exactMatch\" | \"aliasMatch\" | \"conflict\"; aliasTargetId?: string | undefined; aliasPurpose?: \"savedObjectConversion\" | \"savedObjectImport\" | undefined; }; }" ], "path": "src/plugins/event_annotation/common/content_management/v1/types.ts", "deprecated": false, diff --git a/api_docs/event_annotation.mdx b/api_docs/event_annotation.mdx index bdf936b345c46..e9cb8bc9bbdd7 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'eventAnnotation'] --- import eventAnnotationObj from './event_annotation.devdocs.json'; diff --git a/api_docs/event_annotation_listing.mdx b/api_docs/event_annotation_listing.mdx index 0d60add60483d..a2a4942a6061b 100644 --- a/api_docs/event_annotation_listing.mdx +++ b/api_docs/event_annotation_listing.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/eventAnnotationListing title: "eventAnnotationListing" image: https://source.unsplash.com/400x175/?github description: API docs for the eventAnnotationListing plugin -date: 2023-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'eventAnnotationListing'] --- import eventAnnotationListingObj from './event_annotation_listing.devdocs.json'; diff --git a/api_docs/event_log.mdx b/api_docs/event_log.mdx index 9d129d9bf20d6..42bb1a5ae197a 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-10-31 +date: 2023-11-03 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 d4bea3a72827c..370ffc125955a 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-10-31 +date: 2023-11-03 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 cd1eea889bd08..7202be7c2b6f6 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionError'] --- import expressionErrorObj from './expression_error.devdocs.json'; diff --git a/api_docs/expression_gauge.mdx b/api_docs/expression_gauge.mdx index 8fbced0087aa1..53c120c75632f 100644 --- a/api_docs/expression_gauge.mdx +++ b/api_docs/expression_gauge.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionGauge title: "expressionGauge" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionGauge plugin -date: 2023-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionGauge'] --- import expressionGaugeObj from './expression_gauge.devdocs.json'; diff --git a/api_docs/expression_heatmap.mdx b/api_docs/expression_heatmap.mdx index 87e10069dc0da..5beb4f62eeee6 100644 --- a/api_docs/expression_heatmap.mdx +++ b/api_docs/expression_heatmap.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionHeatmap title: "expressionHeatmap" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionHeatmap plugin -date: 2023-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionHeatmap'] --- import expressionHeatmapObj from './expression_heatmap.devdocs.json'; diff --git a/api_docs/expression_image.mdx b/api_docs/expression_image.mdx index 26e9ccac22f46..ee9beaa552ca1 100644 --- a/api_docs/expression_image.mdx +++ b/api_docs/expression_image.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionImage title: "expressionImage" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionImage plugin -date: 2023-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionImage'] --- import expressionImageObj from './expression_image.devdocs.json'; diff --git a/api_docs/expression_legacy_metric_vis.mdx b/api_docs/expression_legacy_metric_vis.mdx index 604f510c0b790..1f95f62dbb972 100644 --- a/api_docs/expression_legacy_metric_vis.mdx +++ b/api_docs/expression_legacy_metric_vis.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionLegacyMetricVis title: "expressionLegacyMetricVis" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionLegacyMetricVis plugin -date: 2023-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionLegacyMetricVis'] --- import expressionLegacyMetricVisObj from './expression_legacy_metric_vis.devdocs.json'; diff --git a/api_docs/expression_metric.mdx b/api_docs/expression_metric.mdx index ccf9b5f759436..085d6db88f20b 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionMetric'] --- import expressionMetricObj from './expression_metric.devdocs.json'; diff --git a/api_docs/expression_metric_vis.mdx b/api_docs/expression_metric_vis.mdx index cf7718dd7c6a4..ecd9d59399285 100644 --- a/api_docs/expression_metric_vis.mdx +++ b/api_docs/expression_metric_vis.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionMetricVis title: "expressionMetricVis" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionMetricVis plugin -date: 2023-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionMetricVis'] --- import expressionMetricVisObj from './expression_metric_vis.devdocs.json'; diff --git a/api_docs/expression_partition_vis.mdx b/api_docs/expression_partition_vis.mdx index 69304b55b8de3..819c992ca0451 100644 --- a/api_docs/expression_partition_vis.mdx +++ b/api_docs/expression_partition_vis.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionPartitionVis title: "expressionPartitionVis" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionPartitionVis plugin -date: 2023-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionPartitionVis'] --- import expressionPartitionVisObj from './expression_partition_vis.devdocs.json'; diff --git a/api_docs/expression_repeat_image.mdx b/api_docs/expression_repeat_image.mdx index 1e791ee2c4c67..5f1a1df4d66a8 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionRepeatImage'] --- import expressionRepeatImageObj from './expression_repeat_image.devdocs.json'; diff --git a/api_docs/expression_reveal_image.mdx b/api_docs/expression_reveal_image.mdx index 2ca7a27968180..89cc26e71356c 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-10-31 +date: 2023-11-03 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 0f62a9771e76a..33214ad4c1f2b 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-10-31 +date: 2023-11-03 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 571e6a0f46623..4a3d87ef6e8c4 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionTagcloud'] --- import expressionTagcloudObj from './expression_tagcloud.devdocs.json'; diff --git a/api_docs/expression_x_y.mdx b/api_docs/expression_x_y.mdx index afe45539d1ac8..5c5f705587c5e 100644 --- a/api_docs/expression_x_y.mdx +++ b/api_docs/expression_x_y.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionXY title: "expressionXY" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionXY plugin -date: 2023-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionXY'] --- import expressionXYObj from './expression_x_y.devdocs.json'; diff --git a/api_docs/expressions.devdocs.json b/api_docs/expressions.devdocs.json index 9a55c35439d2e..b22b81fce29c4 100644 --- a/api_docs/expressions.devdocs.json +++ b/api_docs/expressions.devdocs.json @@ -3802,7 +3802,7 @@ "id": "def-public.ExpressionRenderHandler.Unnamed.$2", "type": "Object", "tags": [], - "label": "{\n onRenderError,\n renderMode,\n syncColors,\n syncTooltips,\n syncCursor,\n interactive,\n hasCompatibleActions = async () => false,\n getCompatibleCellValueActions = async () => [],\n executionContext,\n }", + "label": "{\n onRenderError,\n renderMode,\n syncColors,\n syncTooltips,\n syncCursor,\n interactive,\n hasCompatibleActions = async () => false,\n getCompatibleCellValueActions = async () => [],\n executionContext,\n shouldShowLegendAction,\n }", "description": [], "signature": [ "ExpressionRenderHandlerParams" @@ -7350,6 +7350,38 @@ } ], "returnComment": [] + }, + { + "parentPluginId": "expressions", + "id": "def-public.ExecutionContext.shouldShowLegendAction", + "type": "Function", + "tags": [], + "label": "shouldShowLegendAction", + "description": [], + "signature": [ + "((actionId: string) => boolean) | undefined" + ], + "path": "src/plugins/expressions/common/execution/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "expressions", + "id": "def-public.ExecutionContext.shouldShowLegendAction.$1", + "type": "string", + "tags": [], + "label": "actionId", + "description": [], + "signature": [ + "string" + ], + "path": "src/plugins/expressions/common/execution/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] } ], "initialIsOpen": false @@ -10980,6 +11012,38 @@ "path": "src/plugins/expressions/public/types/index.ts", "deprecated": false, "trackAdoption": false + }, + { + "parentPluginId": "expressions", + "id": "def-public.IExpressionLoaderParams.shouldShowLegendAction", + "type": "Function", + "tags": [], + "label": "shouldShowLegendAction", + "description": [], + "signature": [ + "((actionId: string) => boolean) | undefined" + ], + "path": "src/plugins/expressions/public/types/index.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "expressions", + "id": "def-public.IExpressionLoaderParams.shouldShowLegendAction.$1", + "type": "string", + "tags": [], + "label": "actionId", + "description": [], + "signature": [ + "string" + ], + "path": "src/plugins/expressions/public/types/index.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] } ], "initialIsOpen": false @@ -11362,6 +11426,38 @@ "trackAdoption": false, "children": [], "returnComment": [] + }, + { + "parentPluginId": "expressions", + "id": "def-public.IInterpreterRenderHandlers.shouldShowLegendAction", + "type": "Function", + "tags": [], + "label": "shouldShowLegendAction", + "description": [], + "signature": [ + "((actionId: string) => boolean) | undefined" + ], + "path": "src/plugins/expressions/common/expression_renderers/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "expressions", + "id": "def-public.IInterpreterRenderHandlers.shouldShowLegendAction.$1", + "type": "string", + "tags": [], + "label": "actionId", + "description": [], + "signature": [ + "string" + ], + "path": "src/plugins/expressions/common/expression_renderers/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] } ], "initialIsOpen": false @@ -11705,6 +11801,38 @@ "path": "src/plugins/expressions/public/react_expression_renderer/react_expression_renderer.tsx", "deprecated": false, "trackAdoption": false + }, + { + "parentPluginId": "expressions", + "id": "def-public.ReactExpressionRendererProps.shouldShowLegendAction", + "type": "Function", + "tags": [], + "label": "shouldShowLegendAction", + "description": [], + "signature": [ + "((actionId: string) => boolean) | undefined" + ], + "path": "src/plugins/expressions/public/react_expression_renderer/react_expression_renderer.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "expressions", + "id": "def-public.ReactExpressionRendererProps.shouldShowLegendAction.$1", + "type": "string", + "tags": [], + "label": "actionId", + "description": [], + "signature": [ + "string" + ], + "path": "src/plugins/expressions/public/react_expression_renderer/react_expression_renderer.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] } ], "initialIsOpen": false @@ -11925,7 +12053,7 @@ "\nThis type represents the `type` of any `DatatableColumn` in a `Datatable`.\nits duplicated from KBN_FIELD_TYPES" ], "signature": [ - "\"string\" | \"number\" | \"boolean\" | \"object\" | \"nested\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"date\" | \"murmur3\" | \"histogram\" | \"unknown\" | \"_source\" | \"attachment\" | \"conflict\" | \"null\"" + "\"string\" | \"number\" | \"boolean\" | \"object\" | \"nested\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"date\" | \"murmur3\" | \"histogram\" | \"conflict\" | \"unknown\" | \"_source\" | \"attachment\" | \"null\"" ], "path": "src/plugins/expressions/common/expression_types/specs/datatable.ts", "deprecated": false, @@ -18757,6 +18885,38 @@ } ], "returnComment": [] + }, + { + "parentPluginId": "expressions", + "id": "def-server.ExecutionContext.shouldShowLegendAction", + "type": "Function", + "tags": [], + "label": "shouldShowLegendAction", + "description": [], + "signature": [ + "((actionId: string) => boolean) | undefined" + ], + "path": "src/plugins/expressions/common/execution/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "expressions", + "id": "def-server.ExecutionContext.shouldShowLegendAction.$1", + "type": "string", + "tags": [], + "label": "actionId", + "description": [], + "signature": [ + "string" + ], + "path": "src/plugins/expressions/common/execution/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] } ], "initialIsOpen": false @@ -21406,6 +21566,38 @@ "trackAdoption": false, "children": [], "returnComment": [] + }, + { + "parentPluginId": "expressions", + "id": "def-server.IInterpreterRenderHandlers.shouldShowLegendAction", + "type": "Function", + "tags": [], + "label": "shouldShowLegendAction", + "description": [], + "signature": [ + "((actionId: string) => boolean) | undefined" + ], + "path": "src/plugins/expressions/common/expression_renderers/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "expressions", + "id": "def-server.IInterpreterRenderHandlers.shouldShowLegendAction.$1", + "type": "string", + "tags": [], + "label": "actionId", + "description": [], + "signature": [ + "string" + ], + "path": "src/plugins/expressions/common/expression_renderers/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] } ], "initialIsOpen": false @@ -21833,7 +22025,7 @@ "\nThis type represents the `type` of any `DatatableColumn` in a `Datatable`.\nits duplicated from KBN_FIELD_TYPES" ], "signature": [ - "\"string\" | \"number\" | \"boolean\" | \"object\" | \"nested\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"date\" | \"murmur3\" | \"histogram\" | \"unknown\" | \"_source\" | \"attachment\" | \"conflict\" | \"null\"" + "\"string\" | \"number\" | \"boolean\" | \"object\" | \"nested\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"date\" | \"murmur3\" | \"histogram\" | \"conflict\" | \"unknown\" | \"_source\" | \"attachment\" | \"null\"" ], "path": "src/plugins/expressions/common/expression_types/specs/datatable.ts", "deprecated": false, @@ -30258,7 +30450,7 @@ "label": "type", "description": [], "signature": [ - "\"string\" | \"number\" | \"boolean\" | \"object\" | \"nested\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"date\" | \"murmur3\" | \"histogram\" | \"unknown\" | \"_source\" | \"attachment\" | \"conflict\" | \"null\"" + "\"string\" | \"number\" | \"boolean\" | \"object\" | \"nested\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"date\" | \"murmur3\" | \"histogram\" | \"conflict\" | \"unknown\" | \"_source\" | \"attachment\" | \"null\"" ], "path": "src/plugins/expressions/common/expression_types/specs/datatable.ts", "deprecated": false, @@ -30824,6 +31016,38 @@ } ], "returnComment": [] + }, + { + "parentPluginId": "expressions", + "id": "def-common.ExecutionContext.shouldShowLegendAction", + "type": "Function", + "tags": [], + "label": "shouldShowLegendAction", + "description": [], + "signature": [ + "((actionId: string) => boolean) | undefined" + ], + "path": "src/plugins/expressions/common/execution/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "expressions", + "id": "def-common.ExecutionContext.shouldShowLegendAction.$1", + "type": "string", + "tags": [], + "label": "actionId", + "description": [], + "signature": [ + "string" + ], + "path": "src/plugins/expressions/common/execution/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] } ], "initialIsOpen": false @@ -35698,6 +35922,38 @@ "trackAdoption": false, "children": [], "returnComment": [] + }, + { + "parentPluginId": "expressions", + "id": "def-common.IInterpreterRenderHandlers.shouldShowLegendAction", + "type": "Function", + "tags": [], + "label": "shouldShowLegendAction", + "description": [], + "signature": [ + "((actionId: string) => boolean) | undefined" + ], + "path": "src/plugins/expressions/common/expression_renderers/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "expressions", + "id": "def-common.IInterpreterRenderHandlers.shouldShowLegendAction.$1", + "type": "string", + "tags": [], + "label": "actionId", + "description": [], + "signature": [ + "string" + ], + "path": "src/plugins/expressions/common/expression_renderers/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] } ], "initialIsOpen": false @@ -36540,7 +36796,7 @@ "\nThis type represents the `type` of any `DatatableColumn` in a `Datatable`.\nits duplicated from KBN_FIELD_TYPES" ], "signature": [ - "\"string\" | \"number\" | \"boolean\" | \"object\" | \"nested\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"date\" | \"murmur3\" | \"histogram\" | \"unknown\" | \"_source\" | \"attachment\" | \"conflict\" | \"null\"" + "\"string\" | \"number\" | \"boolean\" | \"object\" | \"nested\" | \"geo_point\" | \"geo_shape\" | \"ip\" | \"date\" | \"murmur3\" | \"histogram\" | \"conflict\" | \"unknown\" | \"_source\" | \"attachment\" | \"null\"" ], "path": "src/plugins/expressions/common/expression_types/specs/datatable.ts", "deprecated": false, diff --git a/api_docs/expressions.mdx b/api_docs/expressions.mdx index 74c001d57617a..b4d3fc33685f8 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-10-31 +date: 2023-11-03 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 | |-------------------|-----------|------------------------|-----------------| -| 2208 | 17 | 1749 | 5 | +| 2224 | 17 | 1765 | 5 | ## Client diff --git a/api_docs/features.mdx b/api_docs/features.mdx index 968076de21d1b..f1091bcc1556e 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'features'] --- import featuresObj from './features.devdocs.json'; diff --git a/api_docs/field_formats.mdx b/api_docs/field_formats.mdx index 1e26987df88a8..900b70f0231b9 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'fieldFormats'] --- import fieldFormatsObj from './field_formats.devdocs.json'; diff --git a/api_docs/file_upload.mdx b/api_docs/file_upload.mdx index ec4908885a663..1a1f84599d941 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-10-31 +date: 2023-11-03 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 8fdbb54e8c322..390d99c6d5dd1 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'files'] --- import filesObj from './files.devdocs.json'; diff --git a/api_docs/files_management.mdx b/api_docs/files_management.mdx index 092e6a2ca3017..eddfc20b3bd6d 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'filesManagement'] --- import filesManagementObj from './files_management.devdocs.json'; diff --git a/api_docs/fleet.devdocs.json b/api_docs/fleet.devdocs.json index fd706a0787873..69c6344cdae38 100644 --- a/api_docs/fleet.devdocs.json +++ b/api_docs/fleet.devdocs.json @@ -24999,6 +24999,8 @@ "signature": [ "NewElasticsearchOutput", " | ", + "NewRemoteElasticsearchOutput", + " | ", "NewLogstashOutput", " | ", "KafkaOutput" diff --git a/api_docs/fleet.mdx b/api_docs/fleet.mdx index df0f11879f2ce..6b6af5f069d17 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-10-31 +date: 2023-11-03 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 | |-------------------|-----------|------------------------|-----------------| -| 1209 | 3 | 1091 | 44 | +| 1209 | 3 | 1091 | 45 | ## Client diff --git a/api_docs/global_search.mdx b/api_docs/global_search.mdx index 8546741cd7725..34efa1523cb39 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-10-31 +date: 2023-11-03 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 49dbc40923eb1..e22e29dd7a832 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'guidedOnboarding'] --- import guidedOnboardingObj from './guided_onboarding.devdocs.json'; diff --git a/api_docs/home.mdx b/api_docs/home.mdx index 56dabf7163bf1..c6941dcd3bcd7 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'home'] --- import homeObj from './home.devdocs.json'; diff --git a/api_docs/image_embeddable.mdx b/api_docs/image_embeddable.mdx index 89d92bda100e5..b568366d51de9 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-10-31 +date: 2023-11-03 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 352bd33348770..58c6a144cd596 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-10-31 +date: 2023-11-03 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 4eca4cc05eb09..ea196f7b96479 100644 --- a/api_docs/index_management.devdocs.json +++ b/api_docs/index_management.devdocs.json @@ -1523,6 +1523,17 @@ "deprecated": false, "trackAdoption": false }, + { + "parentPluginId": "indexManagement", + "id": "def-common.DataStream.nextGenerationManagedBy", + "type": "string", + "tags": [], + "label": "nextGenerationManagedBy", + "description": [], + "path": "x-pack/plugins/index_management/common/types/data_streams.ts", + "deprecated": false, + "trackAdoption": false + }, { "parentPluginId": "indexManagement", "id": "def-common.DataStream.lifecycle", @@ -1574,6 +1585,28 @@ "path": "x-pack/plugins/index_management/common/types/data_streams.ts", "deprecated": false, "trackAdoption": false + }, + { + "parentPluginId": "indexManagement", + "id": "def-common.DataStreamIndex.preferILM", + "type": "boolean", + "tags": [], + "label": "preferILM", + "description": [], + "path": "x-pack/plugins/index_management/common/types/data_streams.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "indexManagement", + "id": "def-common.DataStreamIndex.managedBy", + "type": "string", + "tags": [], + "label": "managedBy", + "description": [], + "path": "x-pack/plugins/index_management/common/types/data_streams.ts", + "deprecated": false, + "trackAdoption": false } ], "initialIsOpen": false @@ -1643,6 +1676,32 @@ "deprecated": false, "trackAdoption": false }, + { + "parentPluginId": "indexManagement", + "id": "def-common.EnhancedDataStreamFromEs.indices", + "type": "Array", + "tags": [], + "label": "indices", + "description": [], + "signature": [ + "DataStreamIndexFromEs", + "[]" + ], + "path": "x-pack/plugins/index_management/common/types/data_streams.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "indexManagement", + "id": "def-common.EnhancedDataStreamFromEs.next_generation_managed_by", + "type": "string", + "tags": [], + "label": "next_generation_managed_by", + "description": [], + "path": "x-pack/plugins/index_management/common/types/data_streams.ts", + "deprecated": false, + "trackAdoption": false + }, { "parentPluginId": "indexManagement", "id": "def-common.EnhancedDataStreamFromEs.privileges", diff --git a/api_docs/index_management.mdx b/api_docs/index_management.mdx index 56c47ade511ce..6b120ed90e050 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-10-31 +date: 2023-11-03 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 | |-------------------|-----------|------------------------|-----------------| -| 199 | 0 | 194 | 3 | +| 204 | 0 | 199 | 4 | ## Client diff --git a/api_docs/infra.devdocs.json b/api_docs/infra.devdocs.json index 3c6703fd87f83..7bd53f61bf8b7 100644 --- a/api_docs/infra.devdocs.json +++ b/api_docs/infra.devdocs.json @@ -18,23 +18,7 @@ "initialIsOpen": false } ], - "misc": [ - { - "parentPluginId": "infra", - "id": "def-public.InfraAppId", - "type": "Type", - "tags": [], - "label": "InfraAppId", - "description": [], - "signature": [ - "\"metrics\" | \"logs\"" - ], - "path": "x-pack/plugins/infra/public/index.ts", - "deprecated": false, - "trackAdoption": false, - "initialIsOpen": false - } - ], + "misc": [], "objects": [ { "parentPluginId": "infra", @@ -292,123 +276,6 @@ "path": "x-pack/plugins/infra/public/types.ts", "deprecated": false, "trackAdoption": false - }, - { - "parentPluginId": "infra", - "id": "def-public.InfraClientStartExports.ContainerMetricsTable", - "type": "Function", - "tags": [], - "label": "ContainerMetricsTable", - "description": [], - "signature": [ - "(props: ", - "UseNodeMetricsTableOptions", - " & Partial<", - "SourceProviderProps", - ">) => JSX.Element" - ], - "path": "x-pack/plugins/infra/public/types.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "infra", - "id": "def-public.InfraClientStartExports.ContainerMetricsTable.$1", - "type": "CompoundType", - "tags": [], - "label": "props", - "description": [], - "signature": [ - "UseNodeMetricsTableOptions", - " & Partial<", - "SourceProviderProps", - ">" - ], - "path": "x-pack/plugins/infra/public/types.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [] - }, - { - "parentPluginId": "infra", - "id": "def-public.InfraClientStartExports.HostMetricsTable", - "type": "Function", - "tags": [], - "label": "HostMetricsTable", - "description": [], - "signature": [ - "(props: ", - "UseNodeMetricsTableOptions", - " & Partial<", - "SourceProviderProps", - ">) => JSX.Element" - ], - "path": "x-pack/plugins/infra/public/types.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "infra", - "id": "def-public.InfraClientStartExports.HostMetricsTable.$1", - "type": "CompoundType", - "tags": [], - "label": "props", - "description": [], - "signature": [ - "UseNodeMetricsTableOptions", - " & Partial<", - "SourceProviderProps", - ">" - ], - "path": "x-pack/plugins/infra/public/types.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [] - }, - { - "parentPluginId": "infra", - "id": "def-public.InfraClientStartExports.PodMetricsTable", - "type": "Function", - "tags": [], - "label": "PodMetricsTable", - "description": [], - "signature": [ - "(props: ", - "UseNodeMetricsTableOptions", - " & Partial<", - "SourceProviderProps", - ">) => JSX.Element" - ], - "path": "x-pack/plugins/infra/public/types.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "infra", - "id": "def-public.InfraClientStartExports.PodMetricsTable.$1", - "type": "CompoundType", - "tags": [], - "label": "props", - "description": [], - "signature": [ - "UseNodeMetricsTableOptions", - " & Partial<", - "SourceProviderProps", - ">" - ], - "path": "x-pack/plugins/infra/public/types.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [] } ], "lifecycle": "start", diff --git a/api_docs/infra.mdx b/api_docs/infra.mdx index b0da80dc4b939..3948b9be0eec6 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'infra'] --- import infraObj from './infra.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/infra-monitoring-ui](https://github.com/orgs/elastic/teams/inf | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 42 | 0 | 39 | 11 | +| 35 | 0 | 32 | 9 | ## Client @@ -34,9 +34,6 @@ Contact [@elastic/infra-monitoring-ui](https://github.com/orgs/elastic/teams/inf ### Enums -### Consts, variables and types - - ## Server ### Setup diff --git a/api_docs/inspector.mdx b/api_docs/inspector.mdx index 459ea5a59cb7d..744238d9c44d8 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-10-31 +date: 2023-11-03 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 fb707221b657f..34c241bcc6e7a 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-10-31 +date: 2023-11-03 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 9e22160e70d5d..1f9ad7b50acc9 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-10-31 +date: 2023-11-03 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 f515ca8b3fd4e..29ccd72374d57 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-10-31 +date: 2023-11-03 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 ccce27c8a71ac..32869448cefb8 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/aiops-utils'] --- import kbnAiopsUtilsObj from './kbn_aiops_utils.devdocs.json'; diff --git a/api_docs/kbn_alerting_api_integration_helpers.mdx b/api_docs/kbn_alerting_api_integration_helpers.mdx index 4898d695a2416..7ea15023c28b0 100644 --- a/api_docs/kbn_alerting_api_integration_helpers.mdx +++ b/api_docs/kbn_alerting_api_integration_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-alerting-api-integration-helpers title: "@kbn/alerting-api-integration-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/alerting-api-integration-helpers plugin -date: 2023-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/alerting-api-integration-helpers'] --- import kbnAlertingApiIntegrationHelpersObj from './kbn_alerting_api_integration_helpers.devdocs.json'; diff --git a/api_docs/kbn_alerting_state_types.mdx b/api_docs/kbn_alerting_state_types.mdx index 654231a415d89..c953edcb2ad7f 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/alerting-state-types'] --- import kbnAlertingStateTypesObj from './kbn_alerting_state_types.devdocs.json'; diff --git a/api_docs/kbn_alerts_as_data_utils.mdx b/api_docs/kbn_alerts_as_data_utils.mdx index 6077db9871ff1..dbdb98e5c827c 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/alerts-as-data-utils'] --- import kbnAlertsAsDataUtilsObj from './kbn_alerts_as_data_utils.devdocs.json'; diff --git a/api_docs/kbn_alerts_ui_shared.mdx b/api_docs/kbn_alerts_ui_shared.mdx index ed95f6fb69e6e..22766a994fc23 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/alerts-ui-shared'] --- import kbnAlertsUiSharedObj from './kbn_alerts_ui_shared.devdocs.json'; diff --git a/api_docs/kbn_analytics.mdx b/api_docs/kbn_analytics.mdx index 6a496f313e8cb..8ee84c30384a7 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-10-31 +date: 2023-11-03 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 f6397f0d7d0e8..ed52c252cbe81 100644 --- a/api_docs/kbn_analytics_client.devdocs.json +++ b/api_docs/kbn_analytics_client.devdocs.json @@ -739,16 +739,16 @@ "path": "x-pack/plugins/fleet/server/services/telemetry/fleet_usage_sender.ts" }, { - "plugin": "infra", - "path": "x-pack/plugins/infra/public/services/telemetry/telemetry_client.ts" + "plugin": "apm", + "path": "x-pack/plugins/apm/public/services/telemetry/telemetry_client.ts" }, { - "plugin": "infra", - "path": "x-pack/plugins/infra/public/services/telemetry/telemetry_client.ts" + "plugin": "globalSearchBar", + "path": "x-pack/plugins/global_search_bar/public/telemetry/event_reporter.ts" }, { - "plugin": "infra", - "path": "x-pack/plugins/infra/public/services/telemetry/telemetry_client.ts" + "plugin": "globalSearchBar", + "path": "x-pack/plugins/global_search_bar/public/telemetry/event_reporter.ts" }, { "plugin": "infra", @@ -767,16 +767,16 @@ "path": "x-pack/plugins/infra/public/services/telemetry/telemetry_client.ts" }, { - "plugin": "apm", - "path": "x-pack/plugins/apm/public/services/telemetry/telemetry_client.ts" + "plugin": "infra", + "path": "x-pack/plugins/infra/public/services/telemetry/telemetry_client.ts" }, { - "plugin": "globalSearchBar", - "path": "x-pack/plugins/global_search_bar/public/telemetry/event_reporter.ts" + "plugin": "infra", + "path": "x-pack/plugins/infra/public/services/telemetry/telemetry_client.ts" }, { - "plugin": "globalSearchBar", - "path": "x-pack/plugins/global_search_bar/public/telemetry/event_reporter.ts" + "plugin": "infra", + "path": "x-pack/plugins/infra/public/services/telemetry/telemetry_client.ts" }, { "plugin": "osquery", diff --git a/api_docs/kbn_analytics_client.mdx b/api_docs/kbn_analytics_client.mdx index a9815dee8cee7..4b4ca98d3f533 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-10-31 +date: 2023-11-03 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 867eb03196404..fc5174b8ae79f 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-10-31 +date: 2023-11-03 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 e7b98e3230dc7..15f9a39899fa3 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-10-31 +date: 2023-11-03 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 74126e5a76385..fc3e19ad9d1fa 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-10-31 +date: 2023-11-03 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 4843f1990437f..7f3cba8657e0a 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-10-31 +date: 2023-11-03 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 9629272d81c92..ad378bfc5685e 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-10-31 +date: 2023-11-03 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 372540b9ab1fa..b0d20890fb0fd 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-10-31 +date: 2023-11-03 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 eba9ffa82464b..91885e42c3c65 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-10-31 +date: 2023-11-03 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 70989630de90d..70b89dd473547 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-10-31 +date: 2023-11-03 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 bd8e929936bd0..66cac47d2ef17 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-10-31 +date: 2023-11-03 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 f61b50b1b0062..1ccddccab44c6 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/axe-config'] --- import kbnAxeConfigObj from './kbn_axe_config.devdocs.json'; diff --git a/api_docs/kbn_cases_components.mdx b/api_docs/kbn_cases_components.mdx index 881dee7f0522d..340d22ced32a3 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-10-31 +date: 2023-11-03 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 af23e034ff9f3..6dc9ab1273bb9 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-10-31 +date: 2023-11-03 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 6e790dd98401e..3a12ac5c8ebb3 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-10-31 +date: 2023-11-03 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 47d6be4bab32a..65b2d2fd8df6a 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-10-31 +date: 2023-11-03 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 a8c7287abeaf9..e0d04cf23e237 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-10-31 +date: 2023-11-03 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 d0a26287091a3..398a4c14d8928 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-10-31 +date: 2023-11-03 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 e19e3096f3443..fe60349ce7a15 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-10-31 +date: 2023-11-03 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 c58bb498a823e..b5f714b5fe2ad 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/cli-dev-mode'] --- import kbnCliDevModeObj from './kbn_cli_dev_mode.devdocs.json'; diff --git a/api_docs/kbn_code_editor.mdx b/api_docs/kbn_code_editor.mdx index ab78306f49d42..6d65788df97cc 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-10-31 +date: 2023-11-03 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 7f6ada9f2ee0e..fb798bb6c5508 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/code-editor-mocks'] --- import kbnCodeEditorMocksObj from './kbn_code_editor_mocks.devdocs.json'; diff --git a/api_docs/kbn_coloring.mdx b/api_docs/kbn_coloring.mdx index 746c8d9e84006..18215efc38b8f 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-10-31 +date: 2023-11-03 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 52bbb901de594..5a91eb877d1e6 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/config'] --- import kbnConfigObj from './kbn_config.devdocs.json'; diff --git a/api_docs/kbn_config_mocks.mdx b/api_docs/kbn_config_mocks.mdx index 93123f08b0871..c74a47b20d657 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/config-mocks'] --- import kbnConfigMocksObj from './kbn_config_mocks.devdocs.json'; diff --git a/api_docs/kbn_config_schema.mdx b/api_docs/kbn_config_schema.mdx index 66814ac74c4b5..9249e0ec1b64d 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/config-schema'] --- import kbnConfigSchemaObj from './kbn_config_schema.devdocs.json'; diff --git a/api_docs/kbn_content_management_content_editor.mdx b/api_docs/kbn_content_management_content_editor.mdx index e012dc5ebec39..afe344de1a9e3 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-10-31 +date: 2023-11-03 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 e74ff48474b63..7a53f63e77095 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-10-31 +date: 2023-11-03 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 8d310139c5347..d762dda8ce696 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-10-31 +date: 2023-11-03 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 09ed0b34bfab4..cc22f22083766 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-10-31 +date: 2023-11-03 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.devdocs.json b/api_docs/kbn_content_management_utils.devdocs.json index 4225db663ec83..f1747bda3db86 100644 --- a/api_docs/kbn_content_management_utils.devdocs.json +++ b/api_docs/kbn_content_management_utils.devdocs.json @@ -763,7 +763,7 @@ "section": "def-common.Type", "text": "Type" }, - "<\"conflict\" | \"exactMatch\" | \"aliasMatch\">; aliasTargetId: ", + "<\"exactMatch\" | \"aliasMatch\" | \"conflict\">; aliasTargetId: ", { "pluginId": "@kbn/config-schema", "scope": "common", @@ -1282,7 +1282,7 @@ "section": "def-common.SOWithMetadata", "text": "SOWithMetadata" }, - "; meta: { outcome: \"conflict\" | \"exactMatch\" | \"aliasMatch\"; aliasTargetId?: string | undefined; aliasPurpose?: \"savedObjectConversion\" | \"savedObjectImport\" | undefined; }; }" + "; meta: { outcome: \"exactMatch\" | \"aliasMatch\" | \"conflict\"; aliasTargetId?: string | undefined; aliasPurpose?: \"savedObjectConversion\" | \"savedObjectImport\" | undefined; }; }" ], "path": "packages/kbn-content-management-utils/src/types.ts", "deprecated": false, @@ -1709,7 +1709,7 @@ "section": "def-common.SOWithMetadata", "text": "SOWithMetadata" }, - "; meta: { outcome: \"conflict\" | \"exactMatch\" | \"aliasMatch\"; aliasTargetId?: string | undefined; aliasPurpose?: \"savedObjectConversion\" | \"savedObjectImport\" | undefined; }; }" + "; meta: { outcome: \"exactMatch\" | \"aliasMatch\" | \"conflict\"; aliasTargetId?: string | undefined; aliasPurpose?: \"savedObjectConversion\" | \"savedObjectImport\" | undefined; }; }" ], "path": "packages/kbn-content-management-utils/src/types.ts", "deprecated": false, @@ -3149,7 +3149,7 @@ "Return value for Saved Object get, T is item returned" ], "signature": [ - "{ item: T; meta: { outcome: \"conflict\" | \"exactMatch\" | \"aliasMatch\"; aliasTargetId?: string | undefined; aliasPurpose?: \"savedObjectConversion\" | \"savedObjectImport\" | undefined; }; }" + "{ item: T; meta: { outcome: \"exactMatch\" | \"aliasMatch\" | \"conflict\"; aliasTargetId?: string | undefined; aliasPurpose?: \"savedObjectConversion\" | \"savedObjectImport\" | undefined; }; }" ], "path": "packages/kbn-content-management-utils/src/types.ts", "deprecated": false, diff --git a/api_docs/kbn_content_management_utils.mdx b/api_docs/kbn_content_management_utils.mdx index 6838dd24b7293..1f1a495926941 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-10-31 +date: 2023-11-03 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 87f77388dec62..70db1baeafbad 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-10-31 +date: 2023-11-03 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 50f786eda89f0..8b1c6fbd838df 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-10-31 +date: 2023-11-03 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 8fe98a53a82a4..d37afe37207a7 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-10-31 +date: 2023-11-03 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 2debb1ab3aef5..1040835acc091 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-10-31 +date: 2023-11-03 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 7c9ad67516599..20026de657c7e 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-10-31 +date: 2023-11-03 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 37fe77f541fa5..1c3a70a1ed1f8 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-server-mocks'] --- import kbnCoreAnalyticsServerMocksObj from './kbn_core_analytics_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_application_browser.mdx b/api_docs/kbn_core_application_browser.mdx index 3a83f40f3b256..f61cd23a9d5ea 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-10-31 +date: 2023-11-03 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 1480cb1a26f29..d92994b0cca13 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-10-31 +date: 2023-11-03 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 c43d5fb3aa32f..95c2bbe264e89 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-10-31 +date: 2023-11-03 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 4a9e69014bef3..ab8b2a7d2eb9e 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-10-31 +date: 2023-11-03 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 70b37a69aa333..899cff7069e2f 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-10-31 +date: 2023-11-03 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 bdc5727df9896..1989ef4b2b280 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-apps-browser-mocks'] --- import kbnCoreAppsBrowserMocksObj from './kbn_core_apps_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_apps_server_internal.mdx b/api_docs/kbn_core_apps_server_internal.mdx index 0a7507b566e62..ce3280e97e383 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-apps-server-internal'] --- import kbnCoreAppsServerInternalObj from './kbn_core_apps_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_base_browser_mocks.mdx b/api_docs/kbn_core_base_browser_mocks.mdx index fcc626eb2cab4..bdd952aa30e9f 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-10-31 +date: 2023-11-03 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 60fbaf0c08471..1a6589df1f8bf 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-10-31 +date: 2023-11-03 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 40dfee6c74c2b..90ccd63a52593 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-10-31 +date: 2023-11-03 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 15d1485db8392..f46cf460e4cca 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-10-31 +date: 2023-11-03 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 b419244ccc6fd..f66e48bd294ea 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-10-31 +date: 2023-11-03 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 6a29925c5eee0..87dd0b1001c95 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-10-31 +date: 2023-11-03 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 85663a88afdf5..5dd645e46bf61 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-10-31 +date: 2023-11-03 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 8865c6570e578..6abfd20d9e372 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-10-31 +date: 2023-11-03 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 b914612cdbced..31b5872cefaa6 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-10-31 +date: 2023-11-03 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 032015504aebd..7f55c3c8e7fa1 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-10-31 +date: 2023-11-03 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 05a0a32ef42d8..9407cc6c00bfc 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-10-31 +date: 2023-11-03 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 c0b58ade4aa69..bda5368f2e985 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-10-31 +date: 2023-11-03 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 54be88097c6ac..aa1b4e5359019 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-10-31 +date: 2023-11-03 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 cdd56d84699a6..4ec3d8097c314 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-10-31 +date: 2023-11-03 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 dd1fbbf2b26f7..16fc77ae7c914 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-10-31 +date: 2023-11-03 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 4ff33b37e3301..ff1cca260026d 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-10-31 +date: 2023-11-03 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 3f5578d5e6f84..2e2b25ec14951 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-10-31 +date: 2023-11-03 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 5ab691a6622bb..93647d27fed44 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-10-31 +date: 2023-11-03 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 8b156dcbef7dd..8ed262903c450 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-10-31 +date: 2023-11-03 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 d77156ad5105b..85de523833227 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-10-31 +date: 2023-11-03 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 a36d900762aaa..db32fd60a9cff 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-10-31 +date: 2023-11-03 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 5ca6ad437e582..29e7b793315fe 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-10-31 +date: 2023-11-03 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 0d38de265ef85..d8d4096579de6 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-10-31 +date: 2023-11-03 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 898864ce5b69b..02b0d26574ae7 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-10-31 +date: 2023-11-03 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 d558d596cea4d..426adcc514514 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-10-31 +date: 2023-11-03 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 346abab3fdf73..1fbbfda815342 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-10-31 +date: 2023-11-03 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 0ebac00b7a999..8114dcada6984 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-10-31 +date: 2023-11-03 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 2204806511104..282f0c001a821 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-10-31 +date: 2023-11-03 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 a5022bd317689..c257178043509 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-10-31 +date: 2023-11-03 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 e26e8c084a065..612f6c234af06 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-10-31 +date: 2023-11-03 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 4c04bd8209b20..b82a069e40a25 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-elasticsearch-client-server-mocks'] --- import kbnCoreElasticsearchClientServerMocksObj from './kbn_core_elasticsearch_client_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_elasticsearch_server.mdx b/api_docs/kbn_core_elasticsearch_server.mdx index 0ed3883108733..4f4000d6597d6 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-elasticsearch-server'] --- import kbnCoreElasticsearchServerObj from './kbn_core_elasticsearch_server.devdocs.json'; diff --git a/api_docs/kbn_core_elasticsearch_server_internal.devdocs.json b/api_docs/kbn_core_elasticsearch_server_internal.devdocs.json index 7344fb27e6659..ddc738b65660a 100644 --- a/api_docs/kbn_core_elasticsearch_server_internal.devdocs.json +++ b/api_docs/kbn_core_elasticsearch_server_internal.devdocs.json @@ -27,7 +27,7 @@ "label": "isInlineScriptingEnabled", "description": [], "signature": [ - "({ client, }: { client: ", + "({ client, maxRetries, maxRetryDelay, }: { client: ", { "pluginId": "@kbn/core-elasticsearch-server", "scope": "common", @@ -35,7 +35,7 @@ "section": "def-common.ElasticsearchClient", "text": "ElasticsearchClient" }, - "; }) => Promise" + "; maxRetries?: number | undefined; maxRetryDelay?: number | undefined; }) => Promise" ], "path": "packages/core/elasticsearch/core-elasticsearch-server-internal/src/is_scripting_enabled.ts", "deprecated": false, @@ -46,7 +46,7 @@ "id": "def-common.isInlineScriptingEnabled.$1", "type": "Object", "tags": [], - "label": "{\n client,\n}", + "label": "{\n client,\n maxRetries = 20,\n maxRetryDelay = 64,\n}", "description": [], "path": "packages/core/elasticsearch/core-elasticsearch-server-internal/src/is_scripting_enabled.ts", "deprecated": false, @@ -1281,6 +1281,34 @@ "path": "packages/core/elasticsearch/core-elasticsearch-server-internal/src/is_scripting_enabled.ts", "deprecated": false, "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-elasticsearch-server-internal", + "id": "def-common.isInlineScriptingEnabled.$1.maxRetries", + "type": "number", + "tags": [], + "label": "maxRetries", + "description": [], + "signature": [ + "number | undefined" + ], + "path": "packages/core/elasticsearch/core-elasticsearch-server-internal/src/is_scripting_enabled.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/core-elasticsearch-server-internal", + "id": "def-common.isInlineScriptingEnabled.$1.maxRetryDelay", + "type": "number", + "tags": [], + "label": "maxRetryDelay", + "description": [], + "signature": [ + "number | undefined" + ], + "path": "packages/core/elasticsearch/core-elasticsearch-server-internal/src/is_scripting_enabled.ts", + "deprecated": false, + "trackAdoption": false } ] } @@ -1351,6 +1379,43 @@ ], "initialIsOpen": false }, + { + "parentPluginId": "@kbn/core-elasticsearch-server-internal", + "id": "def-common.isRetryableEsClientError", + "type": "Function", + "tags": [], + "label": "isRetryableEsClientError", + "description": [ + "\nReturns true if the given elasticsearch error should be retried\nby retry-based resiliency systems such as the SO migration, false otherwise." + ], + "signature": [ + "(e: ", + "ElasticsearchClientError", + ") => boolean" + ], + "path": "packages/core/elasticsearch/core-elasticsearch-server-internal/src/retryable_es_client_errors.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/core-elasticsearch-server-internal", + "id": "def-common.isRetryableEsClientError.$1", + "type": "Object", + "tags": [], + "label": "e", + "description": [], + "signature": [ + "ElasticsearchClientError" + ], + "path": "packages/core/elasticsearch/core-elasticsearch-server-internal/src/retryable_es_client_errors.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, { "parentPluginId": "@kbn/core-elasticsearch-server-internal", "id": "def-common.isSupportedEsServer", diff --git a/api_docs/kbn_core_elasticsearch_server_internal.mdx b/api_docs/kbn_core_elasticsearch_server_internal.mdx index ffb559548d4d5..ce2a29f655bb2 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-10-31 +date: 2023-11-03 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 | |-------------------|-----------|------------------------|-----------------| -| 38 | 0 | 34 | 3 | +| 42 | 0 | 37 | 3 | ## Common diff --git a/api_docs/kbn_core_elasticsearch_server_mocks.mdx b/api_docs/kbn_core_elasticsearch_server_mocks.mdx index 6dfc62aa863b3..0d7f6f20bb278 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-elasticsearch-server-mocks'] --- import kbnCoreElasticsearchServerMocksObj from './kbn_core_elasticsearch_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_environment_server_internal.mdx b/api_docs/kbn_core_environment_server_internal.mdx index 29635d1827df3..209abe8c67c32 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-10-31 +date: 2023-11-03 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 11d298d2ad3df..11759657aa571 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-10-31 +date: 2023-11-03 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 aa1fcee1a61b4..47afd8f872586 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-10-31 +date: 2023-11-03 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 804718e0ab821..b3fe2a358be89 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-10-31 +date: 2023-11-03 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 2b422bdc34280..77830f77742ed 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-10-31 +date: 2023-11-03 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 259ef73855298..16ee4041da916 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-10-31 +date: 2023-11-03 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 797e4a51805e4..76b43e2148a4e 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-10-31 +date: 2023-11-03 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 525df9822d412..354f3f5cf45b3 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-10-31 +date: 2023-11-03 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 1c80dd761af52..eb0cd73d79870 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-10-31 +date: 2023-11-03 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 78890364f746e..3c17df9ef11ee 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-10-31 +date: 2023-11-03 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 50dd3bc969723..76d903e49e379 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-10-31 +date: 2023-11-03 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 06626ebb76055..0850a9fb1befb 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-10-31 +date: 2023-11-03 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 f6480ff5152f6..db7e802a701eb 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-10-31 +date: 2023-11-03 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 fd84d4969a6fa..10881db71a08c 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-10-31 +date: 2023-11-03 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 7d145ed09eb8a..390fd57d967cb 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-10-31 +date: 2023-11-03 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 8ebe9e4a962af..416f0e4fd4329 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-10-31 +date: 2023-11-03 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 9e0366e53d2d8..29bd11f3a2d28 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-10-31 +date: 2023-11-03 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 8703dd038330d..7324a5a9de5ae 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-10-31 +date: 2023-11-03 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 5d1f8e2bdca4b..f4d6eb4795182 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-10-31 +date: 2023-11-03 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 6d24ca8606134..08f9d46595e6d 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-10-31 +date: 2023-11-03 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 944d824100d66..c972ffa22bdf2 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-router-server-internal'] --- import kbnCoreHttpRouterServerInternalObj from './kbn_core_http_router_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_http_router_server_mocks.mdx b/api_docs/kbn_core_http_router_server_mocks.mdx index f41292834508a..914c851048295 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-10-31 +date: 2023-11-03 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 ad381c939b861..89c82757622b8 100644 --- a/api_docs/kbn_core_http_server.devdocs.json +++ b/api_docs/kbn_core_http_server.devdocs.json @@ -3569,7 +3569,7 @@ }, { "plugin": "alerting", - "path": "x-pack/plugins/alerting/server/routes/resolve_rule.ts" + "path": "x-pack/plugins/alerting/server/routes/rule/apis/resolve/resolve_rule_route.ts" }, { "plugin": "alerting", @@ -3667,6 +3667,18 @@ "plugin": "savedObjectsTagging", "path": "x-pack/plugins/saved_objects_tagging/server/routes/internal/find_tags.ts" }, + { + "plugin": "visTypeTimeseries", + "path": "src/plugins/vis_types/timeseries/server/routes/fields.ts" + }, + { + "plugin": "metricsDataAccess", + "path": "x-pack/plugins/metrics_data_access/server/lib/adapters/framework/kibana_framework_adapter.ts" + }, + { + "plugin": "metricsDataAccess", + "path": "x-pack/plugins/metrics_data_access/server/routes/metric_indices/index.ts" + }, { "plugin": "assetManager", "path": "x-pack/plugins/asset_manager/server/routes/ping.ts" @@ -3791,6 +3803,10 @@ "plugin": "indexManagement", "path": "x-pack/plugins/index_management/server/routes/api/enrich_policies/register_list_route.ts" }, + { + "plugin": "indexManagement", + "path": "x-pack/plugins/index_management/server/routes/api/enrich_policies/register_privileges_route.ts" + }, { "plugin": "remoteClusters", "path": "x-pack/plugins/remote_clusters/server/routes/api/get_route.ts" @@ -4239,10 +4255,6 @@ "plugin": "indexLifecycleManagement", "path": "x-pack/plugins/index_lifecycle_management/server/routes/api/snapshot_repositories/register_fetch_route.ts" }, - { - "plugin": "visTypeTimeseries", - "path": "src/plugins/vis_types/timeseries/server/routes/fields.ts" - }, { "plugin": "infra", "path": "x-pack/plugins/infra/server/lib/adapters/framework/kibana_framework_adapter.ts" @@ -4835,18 +4847,6 @@ "plugin": "alerting", "path": "x-pack/plugins/alerting/server/routes/health.test.ts" }, - { - "plugin": "alerting", - "path": "x-pack/plugins/alerting/server/routes/resolve_rule.test.ts" - }, - { - "plugin": "alerting", - "path": "x-pack/plugins/alerting/server/routes/resolve_rule.test.ts" - }, - { - "plugin": "alerting", - "path": "x-pack/plugins/alerting/server/routes/resolve_rule.test.ts" - }, { "plugin": "alerting", "path": "x-pack/plugins/alerting/server/routes/rule_types.test.ts" @@ -5235,6 +5235,14 @@ "plugin": "indexManagement", "path": "x-pack/plugins/index_management/server/routes/api/component_templates/register_privileges_route.test.ts" }, + { + "plugin": "indexManagement", + "path": "x-pack/plugins/index_management/server/routes/api/enrich_policies/register_privileges_route.test.ts" + }, + { + "plugin": "indexManagement", + "path": "x-pack/plugins/index_management/server/routes/api/enrich_policies/register_privileges_route.test.ts" + }, { "plugin": "spaces", "path": "x-pack/plugins/spaces/server/routes/api/external/get.test.ts" @@ -5303,6 +5311,18 @@ "plugin": "alerting", "path": "x-pack/plugins/alerting/server/routes/rule/apis/get_schedule_frequency/get_schedule_frequency_route.test.ts" }, + { + "plugin": "alerting", + "path": "x-pack/plugins/alerting/server/routes/rule/apis/resolve/resolve_rule_route.test.ts" + }, + { + "plugin": "alerting", + "path": "x-pack/plugins/alerting/server/routes/rule/apis/resolve/resolve_rule_route.test.ts" + }, + { + "plugin": "alerting", + "path": "x-pack/plugins/alerting/server/routes/rule/apis/resolve/resolve_rule_route.test.ts" + }, { "plugin": "alerting", "path": "x-pack/plugins/alerting/server/routes/rule/apis/tags/get_rule_tags.test.ts" @@ -6051,11 +6071,11 @@ }, { "plugin": "alerting", - "path": "x-pack/plugins/alerting/server/routes/snooze_rule.ts" + "path": "x-pack/plugins/alerting/server/routes/rule/apis/snooze/snooze_rule_route.ts" }, { "plugin": "alerting", - "path": "x-pack/plugins/alerting/server/routes/unsnooze_rule.ts" + "path": "x-pack/plugins/alerting/server/routes/rule/apis/unsnooze/unsnooze_rule_route.ts" }, { "plugin": "alerting", @@ -6161,6 +6181,14 @@ "plugin": "savedObjectsTagging", "path": "x-pack/plugins/saved_objects_tagging/server/routes/internal/bulk_delete.ts" }, + { + "plugin": "visTypeTimeseries", + "path": "src/plugins/vis_types/timeseries/server/routes/vis.ts" + }, + { + "plugin": "metricsDataAccess", + "path": "x-pack/plugins/metrics_data_access/server/lib/adapters/framework/kibana_framework_adapter.ts" + }, { "plugin": "assetManager", "path": "x-pack/plugins/asset_manager/server/routes/sample_assets.ts" @@ -6645,10 +6673,6 @@ "plugin": "indexLifecycleManagement", "path": "x-pack/plugins/index_lifecycle_management/server/routes/api/templates/register_add_policy_route.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" @@ -7137,18 +7161,6 @@ "plugin": "alerting", "path": "x-pack/plugins/alerting/server/routes/run_soon.test.ts" }, - { - "plugin": "alerting", - "path": "x-pack/plugins/alerting/server/routes/snooze_rule.test.ts" - }, - { - "plugin": "alerting", - "path": "x-pack/plugins/alerting/server/routes/snooze_rule.test.ts" - }, - { - "plugin": "alerting", - "path": "x-pack/plugins/alerting/server/routes/snooze_rule.test.ts" - }, { "plugin": "alerting", "path": "x-pack/plugins/alerting/server/routes/unmute_alert.test.ts" @@ -7165,14 +7177,6 @@ "plugin": "alerting", "path": "x-pack/plugins/alerting/server/routes/unmute_all_rule.test.ts" }, - { - "plugin": "alerting", - "path": "x-pack/plugins/alerting/server/routes/unsnooze_rule.test.ts" - }, - { - "plugin": "alerting", - "path": "x-pack/plugins/alerting/server/routes/unsnooze_rule.test.ts" - }, { "plugin": "alerting", "path": "x-pack/plugins/alerting/server/routes/update_flapping_settings.test.ts" @@ -7569,6 +7573,26 @@ "plugin": "alerting", "path": "x-pack/plugins/alerting/server/routes/rule/apis/mute_alert/mute_alert.test.ts" }, + { + "plugin": "alerting", + "path": "x-pack/plugins/alerting/server/routes/rule/apis/snooze/snooze_rule_route.test.ts" + }, + { + "plugin": "alerting", + "path": "x-pack/plugins/alerting/server/routes/rule/apis/snooze/snooze_rule_route.test.ts" + }, + { + "plugin": "alerting", + "path": "x-pack/plugins/alerting/server/routes/rule/apis/snooze/snooze_rule_route.test.ts" + }, + { + "plugin": "alerting", + "path": "x-pack/plugins/alerting/server/routes/rule/apis/unsnooze/unsnooze_rule_route.test.ts" + }, + { + "plugin": "alerting", + "path": "x-pack/plugins/alerting/server/routes/rule/apis/unsnooze/unsnooze_rule_route.test.ts" + }, { "plugin": "alerting", "path": "x-pack/plugins/alerting/server/routes/rules_settings/apis/update/update_query_delay_settings.test.ts" @@ -7939,6 +7963,10 @@ "plugin": "guidedOnboarding", "path": "src/plugins/guided_onboarding/server/routes/plugin_state_routes.ts" }, + { + "plugin": "metricsDataAccess", + "path": "x-pack/plugins/metrics_data_access/server/lib/adapters/framework/kibana_framework_adapter.ts" + }, { "plugin": "reporting", "path": "x-pack/plugins/reporting/server/routes/internal/deprecations/deprecations.ts" @@ -8593,6 +8621,10 @@ "plugin": "alerting", "path": "x-pack/plugins/alerting/server/routes/rule/apis/bulk_disable/bulk_disable_rules_route.ts" }, + { + "plugin": "metricsDataAccess", + "path": "x-pack/plugins/metrics_data_access/server/lib/adapters/framework/kibana_framework_adapter.ts" + }, { "plugin": "enterpriseSearch", "path": "x-pack/plugins/enterprise_search/server/routes/workplace_search/security.ts" @@ -8939,6 +8971,10 @@ "plugin": "savedObjectsTagging", "path": "x-pack/plugins/saved_objects_tagging/server/routes/tags/delete_tag.ts" }, + { + "plugin": "metricsDataAccess", + "path": "x-pack/plugins/metrics_data_access/server/lib/adapters/framework/kibana_framework_adapter.ts" + }, { "plugin": "assetManager", "path": "x-pack/plugins/asset_manager/server/routes/sample_assets.ts" @@ -13189,6 +13225,10 @@ "plugin": "fleet", "path": "x-pack/plugins/fleet/server/services/security/fleet_router.ts" }, + { + "plugin": "metricsDataAccess", + "path": "x-pack/plugins/metrics_data_access/server/lib/adapters/framework/kibana_framework_adapter.ts" + }, { "plugin": "canvas", "path": "x-pack/plugins/canvas/server/routes/custom_elements/find.ts" @@ -13917,6 +13957,10 @@ "plugin": "fleet", "path": "x-pack/plugins/fleet/server/services/security/fleet_router.ts" }, + { + "plugin": "metricsDataAccess", + "path": "x-pack/plugins/metrics_data_access/server/lib/adapters/framework/kibana_framework_adapter.ts" + }, { "plugin": "canvas", "path": "x-pack/plugins/canvas/server/routes/custom_elements/update.ts" @@ -14509,6 +14553,10 @@ "plugin": "fleet", "path": "x-pack/plugins/fleet/server/services/security/fleet_router.ts" }, + { + "plugin": "metricsDataAccess", + "path": "x-pack/plugins/metrics_data_access/server/lib/adapters/framework/kibana_framework_adapter.ts" + }, { "plugin": "canvas", "path": "x-pack/plugins/canvas/server/routes/custom_elements/create.ts" @@ -15017,6 +15065,10 @@ "plugin": "fleet", "path": "x-pack/plugins/fleet/server/services/security/fleet_router.ts" }, + { + "plugin": "metricsDataAccess", + "path": "x-pack/plugins/metrics_data_access/server/lib/adapters/framework/kibana_framework_adapter.ts" + }, { "plugin": "logsShared", "path": "x-pack/plugins/logs_shared/server/lib/adapters/framework/kibana_framework_adapter.ts" @@ -15201,6 +15253,10 @@ "plugin": "fleet", "path": "x-pack/plugins/fleet/server/services/security/fleet_router.ts" }, + { + "plugin": "metricsDataAccess", + "path": "x-pack/plugins/metrics_data_access/server/lib/adapters/framework/kibana_framework_adapter.ts" + }, { "plugin": "canvas", "path": "x-pack/plugins/canvas/server/routes/custom_elements/delete.ts" diff --git a/api_docs/kbn_core_http_server.mdx b/api_docs/kbn_core_http_server.mdx index e8dd6dfe6e585..6fd49f21e1b73 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-10-31 +date: 2023-11-03 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 8f8ed48546939..3f29bd231375c 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-10-31 +date: 2023-11-03 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.devdocs.json b/api_docs/kbn_core_http_server_mocks.devdocs.json index 3572d725cbf20..2c0ed686470bf 100644 --- a/api_docs/kbn_core_http_server_mocks.devdocs.json +++ b/api_docs/kbn_core_http_server_mocks.devdocs.json @@ -139,9 +139,9 @@ "\nCreates a concrete HttpServer with a mocked context." ], "signature": [ - "(overrides?: Partial<", + "({ buildNum, ...overrides }?: Partial<", "CoreContext", - ">) => ", + " & { buildNum: number; }>) => ", "HttpService" ], "path": "packages/core/http/core-http-server-mocks/src/test_utils.ts", @@ -153,12 +153,12 @@ "id": "def-common.createHttpServer.$1", "type": "Object", "tags": [], - "label": "overrides", + "label": "{\n buildNum,\n ...overrides\n}", "description": [], "signature": [ "Partial<", "CoreContext", - ">" + " & { buildNum: number; }>" ], "path": "packages/core/http/core-http-server-mocks/src/test_utils.ts", "deprecated": false, diff --git a/api_docs/kbn_core_http_server_mocks.mdx b/api_docs/kbn_core_http_server_mocks.mdx index 601438e643d10..c8bd76ea10cb7 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-10-31 +date: 2023-11-03 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 9511e2ff2824b..f39841928eca1 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-10-31 +date: 2023-11-03 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 0a74943162d12..73b4a6123e1c2 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-10-31 +date: 2023-11-03 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 d2cfcf73099c1..fd5aec7e665fe 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-10-31 +date: 2023-11-03 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 936961af7b231..8ee24d14f5fad 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-10-31 +date: 2023-11-03 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 21a17c2ef4543..594b0f59b5476 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-10-31 +date: 2023-11-03 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 795d2eb957b95..692a2fb490e47 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-10-31 +date: 2023-11-03 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 2c61e3e9726d3..96b70a5de8ac2 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-10-31 +date: 2023-11-03 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 3bcb9af271736..b3c40cfa9f215 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-integrations-browser-mocks'] --- import kbnCoreIntegrationsBrowserMocksObj from './kbn_core_integrations_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_lifecycle_browser.mdx b/api_docs/kbn_core_lifecycle_browser.mdx index dd231502d8fd2..8c1328c57593d 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-10-31 +date: 2023-11-03 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 8d6ce299ba9a3..8b2b446374de6 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-10-31 +date: 2023-11-03 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 3695298eb1308..408b432a6d138 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-10-31 +date: 2023-11-03 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 1e62ab8d3d1a6..6965e4ee018d4 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-10-31 +date: 2023-11-03 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 9afda472cbe9d..02b022bb2a2cf 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-10-31 +date: 2023-11-03 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 6ba7bea4d4eda..8592227da327a 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-10-31 +date: 2023-11-03 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 a70477d6aabec..8e13c06b05c21 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-10-31 +date: 2023-11-03 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 fc84d1b50ae02..da31e152b905d 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-10-31 +date: 2023-11-03 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 f688634350ab3..099cc473d2d27 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-10-31 +date: 2023-11-03 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 b06538ad599b5..ecf06e32fe8b4 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-10-31 +date: 2023-11-03 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 39477d34f8131..5c95c5d933b70 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-10-31 +date: 2023-11-03 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 00072a022c999..4dbd29f0a9825 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-10-31 +date: 2023-11-03 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 511e00527b157..63bdc4505096c 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-10-31 +date: 2023-11-03 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 2c76d6e74c6dc..75aa1cda3cbf8 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-10-31 +date: 2023-11-03 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 cc27ee152868d..2af012cf1bc4c 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-10-31 +date: 2023-11-03 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 0427dbdf5a64b..bf29f6cc7b4ad 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-10-31 +date: 2023-11-03 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 7916fd73c474a..64f92520ad94f 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-10-31 +date: 2023-11-03 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 441c8a79665fa..68d96b7b9d540 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-10-31 +date: 2023-11-03 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 4ebfcbbe37d86..5939ccc2a791c 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-10-31 +date: 2023-11-03 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 63e9c91bd70e3..e98b9f170415e 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-10-31 +date: 2023-11-03 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 ede4b800d7191..fc9bee2dec419 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-10-31 +date: 2023-11-03 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 5f2fbc9a1d058..6257c0c0efff7 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-10-31 +date: 2023-11-03 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 70daae2e385fd..3d9f617b25623 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-10-31 +date: 2023-11-03 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 1332d25e5b241..639844a1e9f9e 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-10-31 +date: 2023-11-03 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 e1da008a4e4b4..83c5ca4f3ac38 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-plugins-browser'] --- import kbnCorePluginsBrowserObj from './kbn_core_plugins_browser.devdocs.json'; diff --git a/api_docs/kbn_core_plugins_browser_mocks.mdx b/api_docs/kbn_core_plugins_browser_mocks.mdx index 6bfc843a72c32..d13961fb4cfa9 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-plugins-browser-mocks'] --- import kbnCorePluginsBrowserMocksObj from './kbn_core_plugins_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_plugins_contracts_browser.mdx b/api_docs/kbn_core_plugins_contracts_browser.mdx index d11c0af3c0535..0b3e1f46f3e94 100644 --- a/api_docs/kbn_core_plugins_contracts_browser.mdx +++ b/api_docs/kbn_core_plugins_contracts_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-plugins-contracts-browser title: "@kbn/core-plugins-contracts-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-plugins-contracts-browser plugin -date: 2023-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-plugins-contracts-browser'] --- import kbnCorePluginsContractsBrowserObj from './kbn_core_plugins_contracts_browser.devdocs.json'; diff --git a/api_docs/kbn_core_plugins_contracts_server.mdx b/api_docs/kbn_core_plugins_contracts_server.mdx index 9feba18a61020..3ea1d474763fe 100644 --- a/api_docs/kbn_core_plugins_contracts_server.mdx +++ b/api_docs/kbn_core_plugins_contracts_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-plugins-contracts-server title: "@kbn/core-plugins-contracts-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-plugins-contracts-server plugin -date: 2023-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-plugins-contracts-server'] --- import kbnCorePluginsContractsServerObj from './kbn_core_plugins_contracts_server.devdocs.json'; diff --git a/api_docs/kbn_core_plugins_server.mdx b/api_docs/kbn_core_plugins_server.mdx index 47bc738e0d504..3e4ff8d56a481 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-plugins-server'] --- import kbnCorePluginsServerObj from './kbn_core_plugins_server.devdocs.json'; diff --git a/api_docs/kbn_core_plugins_server_mocks.mdx b/api_docs/kbn_core_plugins_server_mocks.mdx index 7e36776a53de8..0cc5362f6cedb 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-10-31 +date: 2023-11-03 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 0ab356217c406..c586d1cf7032c 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-10-31 +date: 2023-11-03 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 fed5abd0f22c8..c226f425ca2f9 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-10-31 +date: 2023-11-03 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 d9e89701a279d..2fa6b29aa36b3 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-10-31 +date: 2023-11-03 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 b0f27b93ff6dc..55bb783e78543 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-10-31 +date: 2023-11-03 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 ada783eb1bd03..89643765c807a 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-10-31 +date: 2023-11-03 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 165c6c8a51fa4..a00faedae2e4b 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-10-31 +date: 2023-11-03 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 6094383b06ca3..942eca39273a1 100644 --- a/api_docs/kbn_core_saved_objects_api_browser.devdocs.json +++ b/api_docs/kbn_core_saved_objects_api_browser.devdocs.json @@ -220,7 +220,7 @@ "\nThe outcome for a successful `resolve` call is one of the following values:\n\n * `'exactMatch'` -- One document exactly matched the given ID.\n * `'aliasMatch'` -- One document with a legacy URL alias matched the given ID; in this case the `saved_object.id` field is different\n than the given ID.\n * `'conflict'` -- Two documents matched the given ID, one was an exact match and another with a legacy URL alias; in this case the\n `saved_object` object is the exact match, and the `saved_object.id` field is the same as the given ID." ], "signature": [ - "\"conflict\" | \"exactMatch\" | \"aliasMatch\"" + "\"exactMatch\" | \"aliasMatch\" | \"conflict\"" ], "path": "packages/core/saved-objects/core-saved-objects-api-browser/src/apis/resolve.ts", "deprecated": false, diff --git a/api_docs/kbn_core_saved_objects_api_browser.mdx b/api_docs/kbn_core_saved_objects_api_browser.mdx index e8526d3ac9d54..468bf47d15d97 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-10-31 +date: 2023-11-03 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 8ac098e14dffb..143bed79f4d08 100644 --- a/api_docs/kbn_core_saved_objects_api_server.devdocs.json +++ b/api_docs/kbn_core_saved_objects_api_server.devdocs.json @@ -7607,7 +7607,7 @@ "\nThe outcome for a successful `resolve` call is one of the following values:\n\n * `'exactMatch'` -- One document exactly matched the given ID.\n * `'aliasMatch'` -- One document with a legacy URL alias matched the given ID; in this case the `saved_object.id` field is different\n than the given ID.\n * `'conflict'` -- Two documents matched the given ID, one was an exact match and another with a legacy URL alias; in this case the\n `saved_object` object is the exact match, and the `saved_object.id` field is the same as the given ID." ], "signature": [ - "\"conflict\" | \"exactMatch\" | \"aliasMatch\"" + "\"exactMatch\" | \"aliasMatch\" | \"conflict\"" ], "path": "packages/core/saved-objects/core-saved-objects-api-server/src/apis/resolve.ts", "deprecated": false, diff --git a/api_docs/kbn_core_saved_objects_api_server.mdx b/api_docs/kbn_core_saved_objects_api_server.mdx index 33b7f9c2a546f..b716118cdc3c9 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-api-server'] --- import kbnCoreSavedObjectsApiServerObj from './kbn_core_saved_objects_api_server.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_api_server_mocks.mdx b/api_docs/kbn_core_saved_objects_api_server_mocks.mdx index 4daf8f4531266..09f15a2fe6878 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-10-31 +date: 2023-11-03 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 659b612c10917..a54f49f423b99 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-10-31 +date: 2023-11-03 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 5101d8b650b9d..1e552e53056bb 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-base-server-mocks'] --- import kbnCoreSavedObjectsBaseServerMocksObj from './kbn_core_saved_objects_base_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_browser.mdx b/api_docs/kbn_core_saved_objects_browser.mdx index 08ad91dce96c7..955fa449175f6 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-10-31 +date: 2023-11-03 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 4c325d736b150..826ec10444afe 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-10-31 +date: 2023-11-03 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 c099913d2f485..d670796a2d9aa 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-browser-mocks'] --- import kbnCoreSavedObjectsBrowserMocksObj from './kbn_core_saved_objects_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_common.mdx b/api_docs/kbn_core_saved_objects_common.mdx index ab2351289b0cc..6fee259fe68ba 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-10-31 +date: 2023-11-03 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 98957fd2d44e7..dba2d1195a061 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-10-31 +date: 2023-11-03 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 5b05ae1659094..90becbd7ba80e 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-import-export-server-mocks'] --- import kbnCoreSavedObjectsImportExportServerMocksObj from './kbn_core_saved_objects_import_export_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_migration_server_internal.mdx b/api_docs/kbn_core_saved_objects_migration_server_internal.mdx index be4ca0900075d..6b41d87e87735 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-migration-server-internal'] --- import kbnCoreSavedObjectsMigrationServerInternalObj from './kbn_core_saved_objects_migration_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_migration_server_mocks.mdx b/api_docs/kbn_core_saved_objects_migration_server_mocks.mdx index d95cd114970f3..9b9fcac7b0d55 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-10-31 +date: 2023-11-03 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 072a1542c8fed..fc752c0f8b171 100644 --- a/api_docs/kbn_core_saved_objects_server.devdocs.json +++ b/api_docs/kbn_core_saved_objects_server.devdocs.json @@ -10315,6 +10315,10 @@ "plugin": "savedObjectsTagging", "path": "x-pack/plugins/saved_objects_tagging/server/saved_objects/tag.ts" }, + { + "plugin": "visualizations", + "path": "src/plugins/visualizations/server/saved_objects/visualization.ts" + }, { "plugin": "savedSearch", "path": "src/plugins/saved_search/server/saved_objects/search.ts" @@ -10331,10 +10335,6 @@ "plugin": "graph", "path": "x-pack/plugins/graph/server/saved_objects/graph_workspace.ts" }, - { - "plugin": "visualizations", - "path": "src/plugins/visualizations/server/saved_objects/visualization.ts" - }, { "plugin": "lists", "path": "x-pack/plugins/lists/server/saved_objects/exception_list.ts" diff --git a/api_docs/kbn_core_saved_objects_server.mdx b/api_docs/kbn_core_saved_objects_server.mdx index 1f84462298eda..e283f1d09589d 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-server'] --- import kbnCoreSavedObjectsServerObj from './kbn_core_saved_objects_server.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_server_internal.mdx b/api_docs/kbn_core_saved_objects_server_internal.mdx index 8704a046eac79..f57cadef2a3aa 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-10-31 +date: 2023-11-03 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 28b5b6655b018..174dbc9626264 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-10-31 +date: 2023-11-03 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 2db77cba4c92d..1082abdcce402 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-10-31 +date: 2023-11-03 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 3166edf95d755..0bf65e7986e54 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-10-31 +date: 2023-11-03 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 c6dd20de44999..dc7e3d7ac3cd2 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-10-31 +date: 2023-11-03 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 2b42c3bdb21ff..c7659c83a60bb 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-10-31 +date: 2023-11-03 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 e839159f9b4f7..8bf1326f92689 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-10-31 +date: 2023-11-03 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 47095b486e4b1..2b297ef1e0184 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-10-31 +date: 2023-11-03 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 fb79439971536..c6d6afef02dd2 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-10-31 +date: 2023-11-03 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 bec783e9ca7e8..1232c74bc7d55 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-test-helpers-http-setup-browser'] --- import kbnCoreTestHelpersHttpSetupBrowserObj from './kbn_core_test_helpers_http_setup_browser.devdocs.json'; diff --git a/api_docs/kbn_core_test_helpers_kbn_server.mdx b/api_docs/kbn_core_test_helpers_kbn_server.mdx index 7122d7cf2a6b8..a62cb081c4c4d 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-test-helpers-kbn-server'] --- import kbnCoreTestHelpersKbnServerObj from './kbn_core_test_helpers_kbn_server.devdocs.json'; diff --git a/api_docs/kbn_core_test_helpers_model_versions.mdx b/api_docs/kbn_core_test_helpers_model_versions.mdx index b0674245bc412..02c9c10d21442 100644 --- a/api_docs/kbn_core_test_helpers_model_versions.mdx +++ b/api_docs/kbn_core_test_helpers_model_versions.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-test-helpers-model-versions title: "@kbn/core-test-helpers-model-versions" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-test-helpers-model-versions plugin -date: 2023-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-test-helpers-model-versions'] --- import kbnCoreTestHelpersModelVersionsObj from './kbn_core_test_helpers_model_versions.devdocs.json'; diff --git a/api_docs/kbn_core_test_helpers_so_type_serializer.mdx b/api_docs/kbn_core_test_helpers_so_type_serializer.mdx index f0037c9a5c95e..f01ba8a04ade3 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-10-31 +date: 2023-11-03 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 568f53df387d5..65909290dc81b 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-10-31 +date: 2023-11-03 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 d506b651fc070..0cc28058aeee9 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-10-31 +date: 2023-11-03 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 00c56a96d5eed..55e1021c1abd3 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-10-31 +date: 2023-11-03 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 e07af301852fa..9d5d52715e2ad 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-10-31 +date: 2023-11-03 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 b70d24e5e31d1..d680dacffa1a5 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-10-31 +date: 2023-11-03 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 1ba292ba5e68e..00e1a0546e0f1 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-10-31 +date: 2023-11-03 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 2953e7e1bfa05..672e05f7da7e7 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-10-31 +date: 2023-11-03 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 05f28a3c1d78a..92909ea468011 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-server'] --- import kbnCoreUiSettingsServerObj from './kbn_core_ui_settings_server.devdocs.json'; diff --git a/api_docs/kbn_core_ui_settings_server_internal.mdx b/api_docs/kbn_core_ui_settings_server_internal.mdx index 70de6fad3289e..d7fa8643db31a 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-10-31 +date: 2023-11-03 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 4e4543cf40df1..2f8c8baca3c04 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-server-mocks'] --- import kbnCoreUiSettingsServerMocksObj from './kbn_core_ui_settings_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_usage_data_server.mdx b/api_docs/kbn_core_usage_data_server.mdx index 1234f2a17d8e1..6474d1e6ca583 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-usage-data-server'] --- import kbnCoreUsageDataServerObj from './kbn_core_usage_data_server.devdocs.json'; diff --git a/api_docs/kbn_core_usage_data_server_internal.mdx b/api_docs/kbn_core_usage_data_server_internal.mdx index 632dddcca5019..ab2bc5d55cf52 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-10-31 +date: 2023-11-03 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 86aaf78e1d6b6..81c3189b4875c 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-10-31 +date: 2023-11-03 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 9ae111961b05f..6e803787f0f91 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-10-31 +date: 2023-11-03 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 a76c66fddfc8a..9225e4c6f863c 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-10-31 +date: 2023-11-03 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 2b4f80c51c0c2..6f14df877fe39 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-10-31 +date: 2023-11-03 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 c9dc55156c292..3972d6e35195a 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-10-31 +date: 2023-11-03 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 b0c9fdcf1590a..4a730977268da 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/crypto-browser'] --- import kbnCryptoBrowserObj from './kbn_crypto_browser.devdocs.json'; diff --git a/api_docs/kbn_custom_integrations.mdx b/api_docs/kbn_custom_integrations.mdx index fed37656beff2..7af42cb1c1563 100644 --- a/api_docs/kbn_custom_integrations.mdx +++ b/api_docs/kbn_custom_integrations.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-custom-integrations title: "@kbn/custom-integrations" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/custom-integrations plugin -date: 2023-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/custom-integrations'] --- import kbnCustomIntegrationsObj from './kbn_custom_integrations.devdocs.json'; diff --git a/api_docs/kbn_cypress_config.mdx b/api_docs/kbn_cypress_config.mdx index b30490874db0c..473014b6241ea 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-10-31 +date: 2023-11-03 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 6ae67dde3bed6..c07303609304c 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-10-31 +date: 2023-11-03 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 c2926b3dfe417..9c005b3b337b6 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-10-31 +date: 2023-11-03 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 cd91997f55bd3..966bf33479822 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-10-31 +date: 2023-11-03 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 acf148fb1d822..19cd4c435d9b5 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-10-31 +date: 2023-11-03 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 2855ca49e7427..f7d5448bb8720 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-10-31 +date: 2023-11-03 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 71edaddb3a151..36cc363563e6e 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/deeplinks-ml'] --- import kbnDeeplinksMlObj from './kbn_deeplinks_ml.devdocs.json'; diff --git a/api_docs/kbn_deeplinks_observability.mdx b/api_docs/kbn_deeplinks_observability.mdx index f72355b024468..f9e3bb3e72179 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/deeplinks-observability'] --- import kbnDeeplinksObservabilityObj from './kbn_deeplinks_observability.devdocs.json'; diff --git a/api_docs/kbn_deeplinks_search.mdx b/api_docs/kbn_deeplinks_search.mdx index 70078dc683b49..3fd60d86ec3cf 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/deeplinks-search'] --- import kbnDeeplinksSearchObj from './kbn_deeplinks_search.devdocs.json'; diff --git a/api_docs/kbn_default_nav_analytics.mdx b/api_docs/kbn_default_nav_analytics.mdx index 184c82326651a..ee73a4e7b4705 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/default-nav-analytics'] --- import kbnDefaultNavAnalyticsObj from './kbn_default_nav_analytics.devdocs.json'; diff --git a/api_docs/kbn_default_nav_devtools.mdx b/api_docs/kbn_default_nav_devtools.mdx index 4b21333d97b7a..565c71af96c6e 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/default-nav-devtools'] --- import kbnDefaultNavDevtoolsObj from './kbn_default_nav_devtools.devdocs.json'; diff --git a/api_docs/kbn_default_nav_management.mdx b/api_docs/kbn_default_nav_management.mdx index fd60f4e436113..42009bb40fcf7 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/default-nav-management'] --- import kbnDefaultNavManagementObj from './kbn_default_nav_management.devdocs.json'; diff --git a/api_docs/kbn_default_nav_ml.mdx b/api_docs/kbn_default_nav_ml.mdx index af9ecfa5c5409..e9f4ec3af35f1 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/default-nav-ml'] --- import kbnDefaultNavMlObj from './kbn_default_nav_ml.devdocs.json'; diff --git a/api_docs/kbn_dev_cli_errors.mdx b/api_docs/kbn_dev_cli_errors.mdx index b1959dc57f517..e87edfe31acc1 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-10-31 +date: 2023-11-03 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 dd97114a746e8..80157c9a486ac 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-10-31 +date: 2023-11-03 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 79ad0731aeaee..0e4bddde04aca 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/dev-proc-runner'] --- import kbnDevProcRunnerObj from './kbn_dev_proc_runner.devdocs.json'; diff --git a/api_docs/kbn_dev_utils.mdx b/api_docs/kbn_dev_utils.mdx index 515c50d5200ac..c430f47852313 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/dev-utils'] --- import kbnDevUtilsObj from './kbn_dev_utils.devdocs.json'; diff --git a/api_docs/kbn_discover_utils.mdx b/api_docs/kbn_discover_utils.mdx index e1f744b3504df..d0abfe5b3cd55 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/discover-utils'] --- import kbnDiscoverUtilsObj from './kbn_discover_utils.devdocs.json'; diff --git a/api_docs/kbn_doc_links.mdx b/api_docs/kbn_doc_links.mdx index 076491d8a715b..d1a7ecf1122cf 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/doc-links'] --- import kbnDocLinksObj from './kbn_doc_links.devdocs.json'; diff --git a/api_docs/kbn_docs_utils.mdx b/api_docs/kbn_docs_utils.mdx index f963eae279d66..af1f5503f1557 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-10-31 +date: 2023-11-03 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 1244304d7045a..98dd8cb127217 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-10-31 +date: 2023-11-03 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 4cb54eaf7942a..db81cf5c8b065 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-10-31 +date: 2023-11-03 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 8e98fa1c46e00..3fcb07623dcbd 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ecs'] --- import kbnEcsObj from './kbn_ecs.devdocs.json'; diff --git a/api_docs/kbn_ecs_data_quality_dashboard.mdx b/api_docs/kbn_ecs_data_quality_dashboard.mdx index eb98790b59dd2..8ba3590d1de2c 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ecs-data-quality-dashboard'] --- import kbnEcsDataQualityDashboardObj from './kbn_ecs_data_quality_dashboard.devdocs.json'; diff --git a/api_docs/kbn_elastic_assistant.mdx b/api_docs/kbn_elastic_assistant.mdx index ecc3c2d2f4061..e0174efc8975f 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/elastic-assistant'] --- import kbnElasticAssistantObj from './kbn_elastic_assistant.devdocs.json'; diff --git a/api_docs/kbn_es.mdx b/api_docs/kbn_es.mdx index bf1043a3e44b3..b2ccdd07e7c75 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/es'] --- import kbnEsObj from './kbn_es.devdocs.json'; diff --git a/api_docs/kbn_es_archiver.mdx b/api_docs/kbn_es_archiver.mdx index c0dc4b2feb85d..7015d53e96cf4 100644 --- a/api_docs/kbn_es_archiver.mdx +++ b/api_docs/kbn_es_archiver.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-es-archiver title: "@kbn/es-archiver" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/es-archiver plugin -date: 2023-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/es-archiver'] --- import kbnEsArchiverObj from './kbn_es_archiver.devdocs.json'; diff --git a/api_docs/kbn_es_errors.mdx b/api_docs/kbn_es_errors.mdx index 4e857e64d57ac..3b90758c02adb 100644 --- a/api_docs/kbn_es_errors.mdx +++ b/api_docs/kbn_es_errors.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-es-errors title: "@kbn/es-errors" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/es-errors plugin -date: 2023-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/es-errors'] --- import kbnEsErrorsObj from './kbn_es_errors.devdocs.json'; diff --git a/api_docs/kbn_es_query.mdx b/api_docs/kbn_es_query.mdx index 24d5d070d8ce6..1e4b8d8269b72 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/es-query'] --- import kbnEsQueryObj from './kbn_es_query.devdocs.json'; diff --git a/api_docs/kbn_es_types.mdx b/api_docs/kbn_es_types.mdx index 33f8b8a2b18cd..6de6efbe1f528 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-10-31 +date: 2023-11-03 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 acf4ca2ec5fb3..5774a1a51ee1f 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/eslint-plugin-imports'] --- import kbnEslintPluginImportsObj from './kbn_eslint_plugin_imports.devdocs.json'; diff --git a/api_docs/kbn_event_annotation_common.mdx b/api_docs/kbn_event_annotation_common.mdx index 413d18501b3d8..a89010a81f329 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/event-annotation-common'] --- import kbnEventAnnotationCommonObj from './kbn_event_annotation_common.devdocs.json'; diff --git a/api_docs/kbn_event_annotation_components.mdx b/api_docs/kbn_event_annotation_components.mdx index 855cb2eecb68c..c023b70f906c2 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/event-annotation-components'] --- import kbnEventAnnotationComponentsObj from './kbn_event_annotation_components.devdocs.json'; diff --git a/api_docs/kbn_expandable_flyout.mdx b/api_docs/kbn_expandable_flyout.mdx index 71d882832e426..488d05cf78055 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-10-31 +date: 2023-11-03 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 9e6a2979eee54..229e34694535e 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/field-types'] --- import kbnFieldTypesObj from './kbn_field_types.devdocs.json'; diff --git a/api_docs/kbn_field_utils.mdx b/api_docs/kbn_field_utils.mdx index 4e0bfa0e9b861..3d02ae47f6378 100644 --- a/api_docs/kbn_field_utils.mdx +++ b/api_docs/kbn_field_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-field-utils title: "@kbn/field-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/field-utils plugin -date: 2023-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/field-utils'] --- import kbnFieldUtilsObj from './kbn_field_utils.devdocs.json'; diff --git a/api_docs/kbn_find_used_node_modules.mdx b/api_docs/kbn_find_used_node_modules.mdx index fc210781ad1df..c471766e13e5b 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-10-31 +date: 2023-11-03 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 8a1f77021f0f5..1f435ab84d48b 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-10-31 +date: 2023-11-03 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 df7ca280dd309..a79bbf9b3f0fc 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-10-31 +date: 2023-11-03 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 d59d743b293f2..7c6120c1b00d6 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-10-31 +date: 2023-11-03 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 44cc0a628ce9b..393af6aa0086c 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-10-31 +date: 2023-11-03 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 f37de7f5336e6..9d75b732925f0 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-10-31 +date: 2023-11-03 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 7cbb5931d8b41..5a688eb8d569a 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-10-31 +date: 2023-11-03 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 b84c6012efeb5..bf55e83250c8f 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-10-31 +date: 2023-11-03 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 f6931ab5b150b..9705ef2fcf7b5 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-10-31 +date: 2023-11-03 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 99e0c0505f75b..e2eab0fcaba7b 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-10-31 +date: 2023-11-03 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 e453c9add9afa..5b77f1e486394 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-10-31 +date: 2023-11-03 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 c13ee01512919..69462e3a4996b 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/home-sample-data-tab'] --- import kbnHomeSampleDataTabObj from './kbn_home_sample_data_tab.devdocs.json'; diff --git a/api_docs/kbn_i18n.mdx b/api_docs/kbn_i18n.mdx index c11fb849ed09a..5d66204dd0366 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-10-31 +date: 2023-11-03 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 f07a0234a9d39..484871d0cd9e5 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-10-31 +date: 2023-11-03 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 5d26059763190..d8064e02a079a 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-10-31 +date: 2023-11-03 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 90a7c44524b39..d2ee66006bf9d 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-10-31 +date: 2023-11-03 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 777109ad7cbe2..3a2fea54a5097 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/interpreter'] --- import kbnInterpreterObj from './kbn_interpreter.devdocs.json'; diff --git a/api_docs/kbn_io_ts_utils.mdx b/api_docs/kbn_io_ts_utils.mdx index 46f8a0fcbf2d2..a2d92aaf92508 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-10-31 +date: 2023-11-03 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 2f92e1ac5b76c..d7a24ccb104f5 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-10-31 +date: 2023-11-03 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 6ac7c9fdfa5ff..9146b5bc6927a 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-10-31 +date: 2023-11-03 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 20e4ae8799158..ddb8a7c575099 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-10-31 +date: 2023-11-03 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 5b11105a1404f..fb49b7ea67ae0 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-10-31 +date: 2023-11-03 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 e153ec1dcd359..a5c32a37673fa 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-10-31 +date: 2023-11-03 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 45847769b7591..a923c4fef2483 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-10-31 +date: 2023-11-03 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 a0a6a41057fe1..666f4189221af 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-10-31 +date: 2023-11-03 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 cce147e77afad..e69ef5beb39e7 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-10-31 +date: 2023-11-03 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 737470258cdae..e658a838810d6 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-10-31 +date: 2023-11-03 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 45ed9c0c3aebd..e78d93fd4a377 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-cards-navigation'] --- import kbnManagementCardsNavigationObj from './kbn_management_cards_navigation.devdocs.json'; diff --git a/api_docs/kbn_management_settings_application.mdx b/api_docs/kbn_management_settings_application.mdx index c79edce9038a9..e3618f562d69c 100644 --- a/api_docs/kbn_management_settings_application.mdx +++ b/api_docs/kbn_management_settings_application.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-application title: "@kbn/management-settings-application" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-application plugin -date: 2023-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-settings-application'] --- import kbnManagementSettingsApplicationObj from './kbn_management_settings_application.devdocs.json'; diff --git a/api_docs/kbn_management_settings_components_field_category.mdx b/api_docs/kbn_management_settings_components_field_category.mdx index 237fa36884844..d9a46fcaebe4f 100644 --- a/api_docs/kbn_management_settings_components_field_category.mdx +++ b/api_docs/kbn_management_settings_components_field_category.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-components-field-category title: "@kbn/management-settings-components-field-category" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-components-field-category plugin -date: 2023-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-settings-components-field-category'] --- import kbnManagementSettingsComponentsFieldCategoryObj from './kbn_management_settings_components_field_category.devdocs.json'; diff --git a/api_docs/kbn_management_settings_components_field_input.mdx b/api_docs/kbn_management_settings_components_field_input.mdx index fb21058973c91..dc59a820104ed 100644 --- a/api_docs/kbn_management_settings_components_field_input.mdx +++ b/api_docs/kbn_management_settings_components_field_input.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-components-field-input title: "@kbn/management-settings-components-field-input" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-components-field-input plugin -date: 2023-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-settings-components-field-input'] --- import kbnManagementSettingsComponentsFieldInputObj from './kbn_management_settings_components_field_input.devdocs.json'; diff --git a/api_docs/kbn_management_settings_components_field_row.mdx b/api_docs/kbn_management_settings_components_field_row.mdx index 0568554e5b301..85e5c9492235e 100644 --- a/api_docs/kbn_management_settings_components_field_row.mdx +++ b/api_docs/kbn_management_settings_components_field_row.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-components-field-row title: "@kbn/management-settings-components-field-row" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-components-field-row plugin -date: 2023-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-settings-components-field-row'] --- import kbnManagementSettingsComponentsFieldRowObj from './kbn_management_settings_components_field_row.devdocs.json'; diff --git a/api_docs/kbn_management_settings_components_form.mdx b/api_docs/kbn_management_settings_components_form.mdx index a05896cc3284d..8724d6100a52d 100644 --- a/api_docs/kbn_management_settings_components_form.mdx +++ b/api_docs/kbn_management_settings_components_form.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-components-form title: "@kbn/management-settings-components-form" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-components-form plugin -date: 2023-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-settings-components-form'] --- import kbnManagementSettingsComponentsFormObj from './kbn_management_settings_components_form.devdocs.json'; diff --git a/api_docs/kbn_management_settings_field_definition.mdx b/api_docs/kbn_management_settings_field_definition.mdx index 9c8133f1e98ed..cd40a7010a8a3 100644 --- a/api_docs/kbn_management_settings_field_definition.mdx +++ b/api_docs/kbn_management_settings_field_definition.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-field-definition title: "@kbn/management-settings-field-definition" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-field-definition plugin -date: 2023-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-settings-field-definition'] --- import kbnManagementSettingsFieldDefinitionObj from './kbn_management_settings_field_definition.devdocs.json'; diff --git a/api_docs/kbn_management_settings_ids.devdocs.json b/api_docs/kbn_management_settings_ids.devdocs.json index af86fa04d57b9..735d127df79ee 100644 --- a/api_docs/kbn_management_settings_ids.devdocs.json +++ b/api_docs/kbn_management_settings_ids.devdocs.json @@ -1477,6 +1477,21 @@ "trackAdoption": false, "initialIsOpen": false }, + { + "parentPluginId": "@kbn/management-settings-ids", + "id": "def-common.SECURITY_SOLUTION_DEFAULT_ALERT_TAGS_KEY", + "type": "string", + "tags": [], + "label": "SECURITY_SOLUTION_DEFAULT_ALERT_TAGS_KEY", + "description": [], + "signature": [ + "\"securitySolution:alertTags\"" + ], + "path": "packages/kbn-management/settings/setting_ids/index.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, { "parentPluginId": "@kbn/management-settings-ids", "id": "def-common.SECURITY_SOLUTION_DEFAULT_ANOMALY_SCORE_ID", @@ -1537,6 +1552,23 @@ "trackAdoption": false, "initialIsOpen": false }, + { + "parentPluginId": "@kbn/management-settings-ids", + "id": "def-common.SECURITY_SOLUTION_ENABLE_EXPANDABLE_FLYOUT_SETTING", + "type": "string", + "tags": [], + "label": "SECURITY_SOLUTION_ENABLE_EXPANDABLE_FLYOUT_SETTING", + "description": [ + "This Kibana Advanced Setting allows users to enable/disable the Expandable Flyout" + ], + "signature": [ + "\"securitySolution:enableExpandableFlyout\"" + ], + "path": "packages/kbn-management/settings/setting_ids/index.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, { "parentPluginId": "@kbn/management-settings-ids", "id": "def-common.SECURITY_SOLUTION_ENABLE_GROUPED_NAV_ID", diff --git a/api_docs/kbn_management_settings_ids.mdx b/api_docs/kbn_management_settings_ids.mdx index cec126a11556c..3dc053268d3f9 100644 --- a/api_docs/kbn_management_settings_ids.mdx +++ b/api_docs/kbn_management_settings_ids.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-ids title: "@kbn/management-settings-ids" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-ids plugin -date: 2023-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-settings-ids'] --- import kbnManagementSettingsIdsObj from './kbn_management_settings_ids.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/appex-sharedux @elastic/platform-deployment-management](https: | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 129 | 0 | 129 | 0 | +| 131 | 0 | 130 | 0 | ## Common diff --git a/api_docs/kbn_management_settings_section_registry.mdx b/api_docs/kbn_management_settings_section_registry.mdx index 40691bdbf7ad7..86568f3c702ca 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-settings-section-registry'] --- import kbnManagementSettingsSectionRegistryObj from './kbn_management_settings_section_registry.devdocs.json'; diff --git a/api_docs/kbn_management_settings_types.mdx b/api_docs/kbn_management_settings_types.mdx index 8717c5e9b4d53..7fa7c633af3ff 100644 --- a/api_docs/kbn_management_settings_types.mdx +++ b/api_docs/kbn_management_settings_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-types title: "@kbn/management-settings-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-types plugin -date: 2023-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-settings-types'] --- import kbnManagementSettingsTypesObj from './kbn_management_settings_types.devdocs.json'; diff --git a/api_docs/kbn_management_settings_utilities.mdx b/api_docs/kbn_management_settings_utilities.mdx index 6779c942dcc3a..2ac9f46a2dd47 100644 --- a/api_docs/kbn_management_settings_utilities.mdx +++ b/api_docs/kbn_management_settings_utilities.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-utilities title: "@kbn/management-settings-utilities" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-utilities plugin -date: 2023-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-settings-utilities'] --- import kbnManagementSettingsUtilitiesObj from './kbn_management_settings_utilities.devdocs.json'; diff --git a/api_docs/kbn_management_storybook_config.mdx b/api_docs/kbn_management_storybook_config.mdx index 3193939d0496b..701df43c839af 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-10-31 +date: 2023-11-03 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..29866944ea667 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\" | \"render\" | \"rotate\" | \"resize\" | \"zoom\" | \"load\" | \"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\" | \"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 4b7efdb410684..0945da8708283 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-10-31 +date: 2023-11-03 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 7369a10de7c40..fee906ec22dd3 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-10-31 +date: 2023-11-03 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 b8384af1d320e..ce0fc0af67710 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-10-31 +date: 2023-11-03 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 97f592d6830d3..a18eb7dcdac6c 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-10-31 +date: 2023-11-03 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 a68620a930fd4..8842a4a58295a 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-category-validator'] --- import kbnMlCategoryValidatorObj from './kbn_ml_category_validator.devdocs.json'; diff --git a/api_docs/kbn_ml_chi2test.mdx b/api_docs/kbn_ml_chi2test.mdx index 3c99bea2d6fe3..37c2b403f4cc6 100644 --- a/api_docs/kbn_ml_chi2test.mdx +++ b/api_docs/kbn_ml_chi2test.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-chi2test title: "@kbn/ml-chi2test" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-chi2test plugin -date: 2023-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-chi2test'] --- import kbnMlChi2testObj from './kbn_ml_chi2test.devdocs.json'; diff --git a/api_docs/kbn_ml_data_frame_analytics_utils.mdx b/api_docs/kbn_ml_data_frame_analytics_utils.mdx index 336a362c1cda2..10654615221e1 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-10-31 +date: 2023-11-03 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 6d0e015988373..bb11e73368f32 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-data-grid'] --- import kbnMlDataGridObj from './kbn_ml_data_grid.devdocs.json'; diff --git a/api_docs/kbn_ml_date_picker.mdx b/api_docs/kbn_ml_date_picker.mdx index 84b7e18cb7804..3f0e88d21eb5f 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-date-picker'] --- import kbnMlDatePickerObj from './kbn_ml_date_picker.devdocs.json'; diff --git a/api_docs/kbn_ml_date_utils.mdx b/api_docs/kbn_ml_date_utils.mdx index 9678057247ae6..6dd1b47f2d0c6 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-10-31 +date: 2023-11-03 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 d2dd021313386..fcff36bd22501 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-10-31 +date: 2023-11-03 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 1c9fd365aa8e1..d4edafb17c584 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-10-31 +date: 2023-11-03 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 3df83ade005ed..c3b441b55f2a0 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-10-31 +date: 2023-11-03 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 560131fc39e99..6a93802d22af9 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-10-31 +date: 2023-11-03 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 faa9f7ad850a1..6d68e9dda6703 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-10-31 +date: 2023-11-03 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 177c24479c552..04099d65e2dc4 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-10-31 +date: 2023-11-03 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 f7ee9d228494a..0379ccf0a01b8 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-10-31 +date: 2023-11-03 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 04ec905ae49e7..b2e8b52876238 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-10-31 +date: 2023-11-03 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 7190766b2f72d..085110c13c447 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-10-31 +date: 2023-11-03 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 3cc1a2c99b38b..f2d13e5933587 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-10-31 +date: 2023-11-03 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 52bbd8b470b2f..a553ea7ec8ff4 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-10-31 +date: 2023-11-03 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 392aed12c4352..d074554cd0805 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-10-31 +date: 2023-11-03 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 0a5fd43b28497..49018edd4ee64 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-string-hash'] --- import kbnMlStringHashObj from './kbn_ml_string_hash.devdocs.json'; diff --git a/api_docs/kbn_ml_trained_models_utils.mdx b/api_docs/kbn_ml_trained_models_utils.mdx index a97e27c694e2b..b4a5971ed0b73 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-trained-models-utils'] --- import kbnMlTrainedModelsUtilsObj from './kbn_ml_trained_models_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_url_state.mdx b/api_docs/kbn_ml_url_state.mdx index 3724502411f98..b406ba1aab14b 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-url-state'] --- import kbnMlUrlStateObj from './kbn_ml_url_state.devdocs.json'; diff --git a/api_docs/kbn_monaco.mdx b/api_docs/kbn_monaco.mdx index e09f2fe2cc84c..6073b3faedfec 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/monaco'] --- import kbnMonacoObj from './kbn_monaco.devdocs.json'; diff --git a/api_docs/kbn_object_versioning.mdx b/api_docs/kbn_object_versioning.mdx index 2610d5b1b88da..0fb02b1879022 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-10-31 +date: 2023-11-03 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 bda5d5cfdfb35..90949db7c51ae 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/observability-alert-details'] --- import kbnObservabilityAlertDetailsObj from './kbn_observability_alert_details.devdocs.json'; diff --git a/api_docs/kbn_observability_alerting_test_data.mdx b/api_docs/kbn_observability_alerting_test_data.mdx index 6420dc53171f0..e5fec49e72265 100644 --- a/api_docs/kbn_observability_alerting_test_data.mdx +++ b/api_docs/kbn_observability_alerting_test_data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-observability-alerting-test-data title: "@kbn/observability-alerting-test-data" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/observability-alerting-test-data plugin -date: 2023-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/observability-alerting-test-data'] --- import kbnObservabilityAlertingTestDataObj from './kbn_observability_alerting_test_data.devdocs.json'; diff --git a/api_docs/kbn_openapi_generator.mdx b/api_docs/kbn_openapi_generator.mdx index 1e7d199acdca3..1bb04ec5a764b 100644 --- a/api_docs/kbn_openapi_generator.mdx +++ b/api_docs/kbn_openapi_generator.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-openapi-generator title: "@kbn/openapi-generator" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/openapi-generator plugin -date: 2023-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/openapi-generator'] --- import kbnOpenapiGeneratorObj from './kbn_openapi_generator.devdocs.json'; diff --git a/api_docs/kbn_optimizer.mdx b/api_docs/kbn_optimizer.mdx index 9858fd681b267..6d979668d8d60 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-10-31 +date: 2023-11-03 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 121a152c891c0..72f8a9e4c4aaf 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-10-31 +date: 2023-11-03 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 383206e5e897b..108426eaa5bf3 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-10-31 +date: 2023-11-03 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 a9d8bed95e753..637443be81171 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-10-31 +date: 2023-11-03 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 3e95cdb46d3a2..0429fc72dd725 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-10-31 +date: 2023-11-03 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 b54a844662331..163511cd543a9 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/plugin-helpers'] --- import kbnPluginHelpersObj from './kbn_plugin_helpers.devdocs.json'; diff --git a/api_docs/kbn_profiling_utils.devdocs.json b/api_docs/kbn_profiling_utils.devdocs.json index 79259edc2989c..597124dd75175 100644 --- a/api_docs/kbn_profiling_utils.devdocs.json +++ b/api_docs/kbn_profiling_utils.devdocs.json @@ -1425,6 +1425,39 @@ "path": "packages/kbn-profiling-utils/common/flamegraph.ts", "deprecated": false, "trackAdoption": false + }, + { + "parentPluginId": "@kbn/profiling-utils", + "id": "def-common.BaseFlameGraph.TotalSamples", + "type": "number", + "tags": [], + "label": "TotalSamples", + "description": [], + "path": "packages/kbn-profiling-utils/common/flamegraph.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/profiling-utils", + "id": "def-common.BaseFlameGraph.TotalCPU", + "type": "number", + "tags": [], + "label": "TotalCPU", + "description": [], + "path": "packages/kbn-profiling-utils/common/flamegraph.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/profiling-utils", + "id": "def-common.BaseFlameGraph.SelfCPU", + "type": "number", + "tags": [], + "label": "SelfCPU", + "description": [], + "path": "packages/kbn-profiling-utils/common/flamegraph.ts", + "deprecated": false, + "trackAdoption": false } ], "initialIsOpen": false @@ -1646,6 +1679,39 @@ "path": "packages/kbn-profiling-utils/common/callee.ts", "deprecated": false, "trackAdoption": false + }, + { + "parentPluginId": "@kbn/profiling-utils", + "id": "def-common.CalleeTree.TotalSamples", + "type": "number", + "tags": [], + "label": "TotalSamples", + "description": [], + "path": "packages/kbn-profiling-utils/common/callee.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/profiling-utils", + "id": "def-common.CalleeTree.TotalCPU", + "type": "number", + "tags": [], + "label": "TotalCPU", + "description": [], + "path": "packages/kbn-profiling-utils/common/callee.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/profiling-utils", + "id": "def-common.CalleeTree.SelfCPU", + "type": "number", + "tags": [], + "label": "SelfCPU", + "description": [], + "path": "packages/kbn-profiling-utils/common/callee.ts", + "deprecated": false, + "trackAdoption": false } ], "initialIsOpen": false diff --git a/api_docs/kbn_profiling_utils.mdx b/api_docs/kbn_profiling_utils.mdx index 5be401488c900..35a5c60160a47 100644 --- a/api_docs/kbn_profiling_utils.mdx +++ b/api_docs/kbn_profiling_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-profiling-utils title: "@kbn/profiling-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/profiling-utils plugin -date: 2023-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/profiling-utils'] --- import kbnProfilingUtilsObj from './kbn_profiling_utils.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 | |-------------------|-----------|------------------------|-----------------| -| 165 | 0 | 22 | 0 | +| 171 | 0 | 28 | 0 | ## Common diff --git a/api_docs/kbn_random_sampling.mdx b/api_docs/kbn_random_sampling.mdx index db12a5b1da300..a4fb7448deb34 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-10-31 +date: 2023-11-03 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 7675607a5a47b..87bb0e88b5e87 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-10-31 +date: 2023-11-03 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 7b30920141869..e0a0e16fb9b0b 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-10-31 +date: 2023-11-03 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 55db33dd55612..9d139bbe2bf82 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-10-31 +date: 2023-11-03 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 b4a432a16f227..61309905159cb 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-10-31 +date: 2023-11-03 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 ecde2734465ff..ca6901fea0e76 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-10-31 +date: 2023-11-03 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 c7e2321379b46..cf3730e284525 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-10-31 +date: 2023-11-03 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 2ad38bc68e953..109a2a61f424a 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-10-31 +date: 2023-11-03 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 52781885c0e0f..fcbe5a08e9a69 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-10-31 +date: 2023-11-03 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 6c5a5ca39a71c..4ffc3c36cddc4 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-10-31 +date: 2023-11-03 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 0cb5cf091af79..81feef51a1a93 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-10-31 +date: 2023-11-03 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 5eaf0b505d723..550b070cdcdf7 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/repo-source-classifier'] --- import kbnRepoSourceClassifierObj from './kbn_repo_source_classifier.devdocs.json'; diff --git a/api_docs/kbn_reporting_common.mdx b/api_docs/kbn_reporting_common.mdx index bb74177964ec2..eafbd1893296e 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-common'] --- import kbnReportingCommonObj from './kbn_reporting_common.devdocs.json'; diff --git a/api_docs/kbn_resizable_layout.mdx b/api_docs/kbn_resizable_layout.mdx index 4a6800d489ffc..0288734a1b329 100644 --- a/api_docs/kbn_resizable_layout.mdx +++ b/api_docs/kbn_resizable_layout.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-resizable-layout title: "@kbn/resizable-layout" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/resizable-layout plugin -date: 2023-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/resizable-layout'] --- import kbnResizableLayoutObj from './kbn_resizable_layout.devdocs.json'; diff --git a/api_docs/kbn_rison.mdx b/api_docs/kbn_rison.mdx index dbcc41ac1a703..c5be2141b29a7 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-10-31 +date: 2023-11-03 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 f08fc86b3da58..a6e4b502386a9 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/rrule'] --- import kbnRruleObj from './kbn_rrule.devdocs.json'; diff --git a/api_docs/kbn_rule_data_utils.devdocs.json b/api_docs/kbn_rule_data_utils.devdocs.json index d4826b462e574..20def9bb105f6 100644 --- a/api_docs/kbn_rule_data_utils.devdocs.json +++ b/api_docs/kbn_rule_data_utils.devdocs.json @@ -176,7 +176,20 @@ } ], "interfaces": [], - "enums": [], + "enums": [ + { + "parentPluginId": "@kbn/rule-data-utils", + "id": "def-common.ApmRuleType", + "type": "Enum", + "tags": [], + "label": "ApmRuleType", + "description": [], + "path": "packages/kbn-rule-data-utils/src/rule_types/o11y_rules.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + } + ], "misc": [ { "parentPluginId": "@kbn/rule-data-utils", @@ -1416,7 +1429,7 @@ "label": "AlertConsumers", "description": [], "signature": [ - "\"uptime\" | \"siem\" | \"apm\" | \"observability\" | \"logs\" | \"infrastructure\" | \"slo\"" + "\"uptime\" | \"siem\" | \"observability\" | \"apm\" | \"logs\" | \"infrastructure\" | \"slo\"" ], "path": "packages/kbn-rule-data-utils/src/alerts_as_data_rbac.ts", "deprecated": false, @@ -1716,7 +1729,7 @@ "label": "ValidFeatureId", "description": [], "signature": [ - "\"uptime\" | \"siem\" | \"apm\" | \"observability\" | \"logs\" | \"infrastructure\" | \"slo\"" + "\"uptime\" | \"siem\" | \"observability\" | \"apm\" | \"logs\" | \"infrastructure\" | \"slo\"" ], "path": "packages/kbn-rule-data-utils/src/alerts_as_data_rbac.ts", "deprecated": false, diff --git a/api_docs/kbn_rule_data_utils.mdx b/api_docs/kbn_rule_data_utils.mdx index 2f6571a6b3da1..71fb2fffe5854 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/rule-data-utils'] --- import kbnRuleDataUtilsObj from './kbn_rule_data_utils.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/security-detections-response](https://github.com/orgs/elastic/ | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 114 | 0 | 111 | 0 | +| 115 | 0 | 112 | 0 | ## Common @@ -31,6 +31,9 @@ Contact [@elastic/security-detections-response](https://github.com/orgs/elastic/ ### Functions +### Enums + + ### Consts, variables and types diff --git a/api_docs/kbn_saved_objects_settings.mdx b/api_docs/kbn_saved_objects_settings.mdx index e49876d323476..66f319598fa99 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/saved-objects-settings'] --- import kbnSavedObjectsSettingsObj from './kbn_saved_objects_settings.devdocs.json'; diff --git a/api_docs/kbn_search_api_panels.mdx b/api_docs/kbn_search_api_panels.mdx index 20da446c1d950..a0ad9d46429ef 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/search-api-panels'] --- import kbnSearchApiPanelsObj from './kbn_search_api_panels.devdocs.json'; diff --git a/api_docs/kbn_search_connectors.mdx b/api_docs/kbn_search_connectors.mdx index 73cfd4d23551f..0c22e5862a1d6 100644 --- a/api_docs/kbn_search_connectors.mdx +++ b/api_docs/kbn_search_connectors.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-search-connectors title: "@kbn/search-connectors" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/search-connectors plugin -date: 2023-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/search-connectors'] --- import kbnSearchConnectorsObj from './kbn_search_connectors.devdocs.json'; diff --git a/api_docs/kbn_search_response_warnings.mdx b/api_docs/kbn_search_response_warnings.mdx index 78c69e2d0304a..2e72da84acd52 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/search-response-warnings'] --- import kbnSearchResponseWarningsObj from './kbn_search_response_warnings.devdocs.json'; diff --git a/api_docs/kbn_security_solution_features.mdx b/api_docs/kbn_security_solution_features.mdx index 6b5e645d839b7..06118e0ca922a 100644 --- a/api_docs/kbn_security_solution_features.mdx +++ b/api_docs/kbn_security_solution_features.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-security-solution-features title: "@kbn/security-solution-features" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/security-solution-features plugin -date: 2023-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-solution-features'] --- import kbnSecuritySolutionFeaturesObj from './kbn_security_solution_features.devdocs.json'; diff --git a/api_docs/kbn_security_solution_navigation.mdx b/api_docs/kbn_security_solution_navigation.mdx index e2a0084374416..75d415a917df5 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-10-31 +date: 2023-11-03 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 0c55705afb548..0746bb2bb2cd7 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-10-31 +date: 2023-11-03 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 0b04869b0270c..1493ccd8cdc12 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-solution-storybook-config'] --- import kbnSecuritySolutionStorybookConfigObj from './kbn_security_solution_storybook_config.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_autocomplete.mdx b/api_docs/kbn_securitysolution_autocomplete.mdx index 6316de6e1143d..b92af0b3fccb3 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-10-31 +date: 2023-11-03 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 69669e2b3c0b1..d6f3fe7b9206b 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-10-31 +date: 2023-11-03 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 e781f523f0e26..b5b0b0db4526e 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-ecs'] --- import kbnSecuritysolutionEcsObj from './kbn_securitysolution_ecs.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_es_utils.mdx b/api_docs/kbn_securitysolution_es_utils.mdx index 045cebbe01bcd..456c0b9093760 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-es-utils'] --- import kbnSecuritysolutionEsUtilsObj from './kbn_securitysolution_es_utils.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_exception_list_components.mdx b/api_docs/kbn_securitysolution_exception_list_components.mdx index abd0ef1ff1fd7..84d00a1516cb4 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-10-31 +date: 2023-11-03 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 3629cbea1f7a0..58bf4900df839 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-10-31 +date: 2023-11-03 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 693b989413b36..6d7d2efcb9a63 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-10-31 +date: 2023-11-03 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 d4c59308a590f..a6887b63d1f20 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-io-ts-alerting-types'] --- import kbnSecuritysolutionIoTsAlertingTypesObj from './kbn_securitysolution_io_ts_alerting_types.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_io_ts_list_types.mdx b/api_docs/kbn_securitysolution_io_ts_list_types.mdx index 3733b3815f724..c5a74cd43bf8f 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-io-ts-list-types'] --- import kbnSecuritysolutionIoTsListTypesObj from './kbn_securitysolution_io_ts_list_types.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_io_ts_types.mdx b/api_docs/kbn_securitysolution_io_ts_types.mdx index b53e34b5034de..9085e2e13c449 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-10-31 +date: 2023-11-03 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 7a393e144c425..94ab02d574868 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-io-ts-utils'] --- import kbnSecuritysolutionIoTsUtilsObj from './kbn_securitysolution_io_ts_utils.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_list_api.mdx b/api_docs/kbn_securitysolution_list_api.mdx index da4d9c386a00c..1b16383934d0c 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-list-api'] --- import kbnSecuritysolutionListApiObj from './kbn_securitysolution_list_api.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_list_constants.mdx b/api_docs/kbn_securitysolution_list_constants.mdx index 444823063599e..d483ada75c998 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-list-constants'] --- import kbnSecuritysolutionListConstantsObj from './kbn_securitysolution_list_constants.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_list_hooks.mdx b/api_docs/kbn_securitysolution_list_hooks.mdx index 0783b15061afb..9cd515c997d6d 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-list-hooks'] --- import kbnSecuritysolutionListHooksObj from './kbn_securitysolution_list_hooks.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_list_utils.mdx b/api_docs/kbn_securitysolution_list_utils.mdx index bc63d0a5eb618..a38d38fc9a47b 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-list-utils'] --- import kbnSecuritysolutionListUtilsObj from './kbn_securitysolution_list_utils.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_rules.mdx b/api_docs/kbn_securitysolution_rules.mdx index 20ac10fe82eeb..a7b954f497dfe 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-10-31 +date: 2023-11-03 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 f1ddad8807fe1..c9c1ee8fa39e3 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-t-grid'] --- import kbnSecuritysolutionTGridObj from './kbn_securitysolution_t_grid.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_utils.mdx b/api_docs/kbn_securitysolution_utils.mdx index cb868303faeed..5700818ff9d19 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-utils'] --- import kbnSecuritysolutionUtilsObj from './kbn_securitysolution_utils.devdocs.json'; diff --git a/api_docs/kbn_server_http_tools.mdx b/api_docs/kbn_server_http_tools.mdx index 0fae5d522e9a6..248335c3f5ba6 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-10-31 +date: 2023-11-03 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 ec3cf4e375d49..771a07d81a9c7 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/server-route-repository'] --- import kbnServerRouteRepositoryObj from './kbn_server_route_repository.devdocs.json'; diff --git a/api_docs/kbn_serverless_common_settings.mdx b/api_docs/kbn_serverless_common_settings.mdx index 1730ac299be6a..d62ade4d8e44e 100644 --- a/api_docs/kbn_serverless_common_settings.mdx +++ b/api_docs/kbn_serverless_common_settings.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-serverless-common-settings title: "@kbn/serverless-common-settings" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/serverless-common-settings plugin -date: 2023-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/serverless-common-settings'] --- import kbnServerlessCommonSettingsObj from './kbn_serverless_common_settings.devdocs.json'; diff --git a/api_docs/kbn_serverless_observability_settings.mdx b/api_docs/kbn_serverless_observability_settings.mdx index 1225f47b3c82a..d9d8979678a96 100644 --- a/api_docs/kbn_serverless_observability_settings.mdx +++ b/api_docs/kbn_serverless_observability_settings.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-serverless-observability-settings title: "@kbn/serverless-observability-settings" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/serverless-observability-settings plugin -date: 2023-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/serverless-observability-settings'] --- import kbnServerlessObservabilitySettingsObj from './kbn_serverless_observability_settings.devdocs.json'; diff --git a/api_docs/kbn_serverless_project_switcher.mdx b/api_docs/kbn_serverless_project_switcher.mdx index 47e5e919692db..00cd27f510cc3 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/serverless-project-switcher'] --- import kbnServerlessProjectSwitcherObj from './kbn_serverless_project_switcher.devdocs.json'; diff --git a/api_docs/kbn_serverless_search_settings.mdx b/api_docs/kbn_serverless_search_settings.mdx index 96d84e07d8fbd..e33a77eadbfc5 100644 --- a/api_docs/kbn_serverless_search_settings.mdx +++ b/api_docs/kbn_serverless_search_settings.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-serverless-search-settings title: "@kbn/serverless-search-settings" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/serverless-search-settings plugin -date: 2023-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/serverless-search-settings'] --- import kbnServerlessSearchSettingsObj from './kbn_serverless_search_settings.devdocs.json'; diff --git a/api_docs/kbn_serverless_security_settings.mdx b/api_docs/kbn_serverless_security_settings.mdx index d94e980cb4883..fef93d99a4632 100644 --- a/api_docs/kbn_serverless_security_settings.mdx +++ b/api_docs/kbn_serverless_security_settings.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-serverless-security-settings title: "@kbn/serverless-security-settings" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/serverless-security-settings plugin -date: 2023-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/serverless-security-settings'] --- import kbnServerlessSecuritySettingsObj from './kbn_serverless_security_settings.devdocs.json'; diff --git a/api_docs/kbn_serverless_storybook_config.mdx b/api_docs/kbn_serverless_storybook_config.mdx index d84840c2961db..ab16a66be9611 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-10-31 +date: 2023-11-03 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 81f7f9e438bf8..b8013e00fb9f5 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-10-31 +date: 2023-11-03 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 574889d88cb3c..0ffaa6fb26628 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-avatar-solution'] --- import kbnSharedUxAvatarSolutionObj from './kbn_shared_ux_avatar_solution.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_button_exit_full_screen.mdx b/api_docs/kbn_shared_ux_button_exit_full_screen.mdx index 592a82c01fb68..bdc0ce83f7827 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-10-31 +date: 2023-11-03 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 5b4c5ecc483e0..c21e70da0c8a7 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-10-31 +date: 2023-11-03 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 cb1f4a429ddfd..4b7ccca01ad3c 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-button-toolbar'] --- import kbnSharedUxButtonToolbarObj from './kbn_shared_ux_button_toolbar.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_card_no_data.mdx b/api_docs/kbn_shared_ux_card_no_data.mdx index d3b0796b2a411..75c03f9f88d8e 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-card-no-data'] --- import kbnSharedUxCardNoDataObj from './kbn_shared_ux_card_no_data.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_card_no_data_mocks.mdx b/api_docs/kbn_shared_ux_card_no_data_mocks.mdx index 5cca0ccd0a07d..ccc681809ea0d 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-10-31 +date: 2023-11-03 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.devdocs.json b/api_docs/kbn_shared_ux_chrome_navigation.devdocs.json index aeacbea9f98c0..c3b285c9899c7 100644 --- a/api_docs/kbn_shared_ux_chrome_navigation.devdocs.json +++ b/api_docs/kbn_shared_ux_chrome_navigation.devdocs.json @@ -1256,6 +1256,42 @@ ], "enums": [], "misc": [ + { + "parentPluginId": "@kbn/shared-ux-chrome-navigation", + "id": "def-common.ContentProvider", + "type": "Type", + "tags": [], + "label": "ContentProvider", + "description": [], + "signature": [ + "(nodeId: string) => void | ", + { + "pluginId": "@kbn/shared-ux-chrome-navigation", + "scope": "common", + "docId": "kibKbnSharedUxChromeNavigationPluginApi", + "section": "def-common.PanelContent", + "text": "PanelContent" + } + ], + "path": "packages/shared-ux/chrome/navigation/src/ui/components/panel/types.ts", + "deprecated": false, + "trackAdoption": false, + "returnComment": [], + "children": [ + { + "parentPluginId": "@kbn/shared-ux-chrome-navigation", + "id": "def-common.ContentProvider.$1", + "type": "string", + "tags": [], + "label": "nodeId", + "description": [], + "path": "packages/shared-ux/chrome/navigation/src/ui/components/panel/types.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, { "parentPluginId": "@kbn/shared-ux-chrome-navigation", "id": "def-common.NavigationGroupPreset", diff --git a/api_docs/kbn_shared_ux_chrome_navigation.mdx b/api_docs/kbn_shared_ux_chrome_navigation.mdx index 9df34bcbe3642..1fac1bc30f20a 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-chrome-navigation'] --- import kbnSharedUxChromeNavigationObj from './kbn_shared_ux_chrome_navigation.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 | |-------------------|-----------|------------------------|-----------------| -| 58 | 0 | 47 | 4 | +| 60 | 0 | 49 | 4 | ## Common diff --git a/api_docs/kbn_shared_ux_error_boundary.mdx b/api_docs/kbn_shared_ux_error_boundary.mdx index f2b657297e79b..f3e37dad59518 100644 --- a/api_docs/kbn_shared_ux_error_boundary.mdx +++ b/api_docs/kbn_shared_ux_error_boundary.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-error-boundary title: "@kbn/shared-ux-error-boundary" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-error-boundary plugin -date: 2023-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-error-boundary'] --- import kbnSharedUxErrorBoundaryObj from './kbn_shared_ux_error_boundary.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_context.mdx b/api_docs/kbn_shared_ux_file_context.mdx index 0517eb9711c44..2d6ccad6ce224 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-10-31 +date: 2023-11-03 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 06355af83f4d4..62e8aa71bd685 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-10-31 +date: 2023-11-03 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 524643e266537..4617cebdfa5b9 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-10-31 +date: 2023-11-03 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 16b3fe7a86ddf..a439ffb1de6dd 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-10-31 +date: 2023-11-03 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 14a10a13cbeff..281914256954a 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-10-31 +date: 2023-11-03 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 4c30c91b6e86c..ec96ae9dc9d46 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-10-31 +date: 2023-11-03 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 a8818a368b098..306cc79842456 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-10-31 +date: 2023-11-03 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 84a4885d3a82e..aa4d7d22a3f84 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-10-31 +date: 2023-11-03 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 60425f1609987..e0b194605e463 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-10-31 +date: 2023-11-03 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 685d8c1408b7d..aee8bc573ed07 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-10-31 +date: 2023-11-03 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 a83679d4d3999..76ed73ec13d7b 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-10-31 +date: 2023-11-03 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 1c50b43799a76..7a1628652e6f6 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-markdown-mocks'] --- import kbnSharedUxMarkdownMocksObj from './kbn_shared_ux_markdown_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_analytics_no_data.mdx b/api_docs/kbn_shared_ux_page_analytics_no_data.mdx index 9d9d9354dd581..c0b211bc0141f 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-10-31 +date: 2023-11-03 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 45fc72c44a1ec..ad5f5ae2f4bf8 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-10-31 +date: 2023-11-03 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 be1670941e2ce..c69861ab89603 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-10-31 +date: 2023-11-03 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 16e1bb182c415..7bc837c03d52d 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-10-31 +date: 2023-11-03 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 6580e24c80ca2..1b1df3184f2f8 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-10-31 +date: 2023-11-03 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 8d9ea4fdfdd9e..7d1b40187e7f0 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-kibana-template-mocks'] --- import kbnSharedUxPageKibanaTemplateMocksObj from './kbn_shared_ux_page_kibana_template_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_no_data.mdx b/api_docs/kbn_shared_ux_page_no_data.mdx index 2eccdcdaad395..103b5a8413b70 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-10-31 +date: 2023-11-03 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 f6a3e4edf93a3..64d008806c7a2 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-10-31 +date: 2023-11-03 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 351905baeaaf2..e7dfb8bbbd261 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-10-31 +date: 2023-11-03 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 7d5aa0060425c..b9cf35348f85f 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-10-31 +date: 2023-11-03 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 614edb06296c7..47c346a4b944a 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-10-31 +date: 2023-11-03 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 e51cbdd69f1d2..9ba65a475af51 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-10-31 +date: 2023-11-03 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 fab151d9bb276..9617dc770af57 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-10-31 +date: 2023-11-03 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 4f25e2f509dc6..636749b97248c 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-10-31 +date: 2023-11-03 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 61612d2557c6a..66534d5ee64fc 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-10-31 +date: 2023-11-03 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 8e3ffe546929a..a2457c22be525 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-10-31 +date: 2023-11-03 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 fd4e25894fbcb..635b863b8dda0 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-10-31 +date: 2023-11-03 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 624c06019bce4..adbb988cf3d45 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-10-31 +date: 2023-11-03 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 bf590c0d26eb0..6910cee4be855 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-utility'] --- import kbnSharedUxUtilityObj from './kbn_shared_ux_utility.devdocs.json'; diff --git a/api_docs/kbn_slo_schema.mdx b/api_docs/kbn_slo_schema.mdx index 81755507ff944..59d708d0a6f4c 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/slo-schema'] --- import kbnSloSchemaObj from './kbn_slo_schema.devdocs.json'; diff --git a/api_docs/kbn_some_dev_log.mdx b/api_docs/kbn_some_dev_log.mdx index 75ef1a782549b..790872116289f 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-10-31 +date: 2023-11-03 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 5da04991818db..02c32243ffce4 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-10-31 +date: 2023-11-03 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 67a93f699ca8b..2bd81cde4daf0 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-10-31 +date: 2023-11-03 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 a6645589d681a..4ea5c495a2183 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/storybook'] --- import kbnStorybookObj from './kbn_storybook.devdocs.json'; diff --git a/api_docs/kbn_subscription_tracking.mdx b/api_docs/kbn_subscription_tracking.mdx index 2603071b449ee..e5f381efd969c 100644 --- a/api_docs/kbn_subscription_tracking.mdx +++ b/api_docs/kbn_subscription_tracking.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-subscription-tracking title: "@kbn/subscription-tracking" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/subscription-tracking plugin -date: 2023-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/subscription-tracking'] --- import kbnSubscriptionTrackingObj from './kbn_subscription_tracking.devdocs.json'; diff --git a/api_docs/kbn_telemetry_tools.mdx b/api_docs/kbn_telemetry_tools.mdx index 64c90dfdc42a8..a5236d3b513c6 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-10-31 +date: 2023-11-03 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 2d9a82dde4b9e..67c1c7a4a48c1 100644 --- a/api_docs/kbn_test.devdocs.json +++ b/api_docs/kbn_test.devdocs.json @@ -2556,7 +2556,7 @@ "section": "def-common.Config", "text": "Config" }, - "; installDir?: string | undefined; extraKbnOpts?: string[] | undefined; logsDir?: string | undefined; onEarlyExit?: ((msg: string) => void) | undefined; }) => Promise" + "; installDir?: string | undefined; extraKbnOpts?: string[] | undefined; logsDir?: string | undefined; onEarlyExit?: ((msg: string) => void) | undefined; inspect?: boolean | undefined; }) => Promise" ], "path": "packages/kbn-test/src/functional_tests/lib/run_kibana_server.ts", "deprecated": false, @@ -2686,6 +2686,20 @@ } ], "returnComment": [] + }, + { + "parentPluginId": "@kbn/test", + "id": "def-common.runKibanaServer.$1.inspect", + "type": "CompoundType", + "tags": [], + "label": "inspect", + "description": [], + "signature": [ + "boolean | undefined" + ], + "path": "packages/kbn-test/src/functional_tests/lib/run_kibana_server.ts", + "deprecated": false, + "trackAdoption": false } ] } diff --git a/api_docs/kbn_test.mdx b/api_docs/kbn_test.mdx index a5667a034dd49..fbc32995f977b 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-10-31 +date: 2023-11-03 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 | |-------------------|-----------|------------------------|-----------------| -| 290 | 4 | 243 | 12 | +| 291 | 4 | 244 | 12 | ## Common diff --git a/api_docs/kbn_test_jest_helpers.mdx b/api_docs/kbn_test_jest_helpers.mdx index 1de95631e8c3c..64d363e0657c7 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-10-31 +date: 2023-11-03 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 bb7bf99b6dc26..038bc1c323c19 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/test-subj-selector'] --- import kbnTestSubjSelectorObj from './kbn_test_subj_selector.devdocs.json'; diff --git a/api_docs/kbn_text_based_editor.mdx b/api_docs/kbn_text_based_editor.mdx index ae083338feec4..48879d4f64b85 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/text-based-editor'] --- import kbnTextBasedEditorObj from './kbn_text_based_editor.devdocs.json'; diff --git a/api_docs/kbn_tooling_log.mdx b/api_docs/kbn_tooling_log.mdx index 3ab466edec212..0ef0a75fb206a 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-10-31 +date: 2023-11-03 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 7d92f3956024b..ef1034c2103d7 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-10-31 +date: 2023-11-03 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 866c98ee13b3d..7d805e49137ab 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/typed-react-router-config'] --- import kbnTypedReactRouterConfigObj from './kbn_typed_react_router_config.devdocs.json'; diff --git a/api_docs/kbn_ui_actions_browser.mdx b/api_docs/kbn_ui_actions_browser.mdx index ddf5d590f293f..9df15d467c50d 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ui-actions-browser'] --- import kbnUiActionsBrowserObj from './kbn_ui_actions_browser.devdocs.json'; diff --git a/api_docs/kbn_ui_shared_deps_src.mdx b/api_docs/kbn_ui_shared_deps_src.mdx index 879279592b27e..80206eab123a6 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-10-31 +date: 2023-11-03 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 c454312b3aea1..3190a59154e61 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ui-theme'] --- import kbnUiThemeObj from './kbn_ui_theme.devdocs.json'; diff --git a/api_docs/kbn_unified_data_table.mdx b/api_docs/kbn_unified_data_table.mdx index 6e98110e4e68b..a0637ec191bf4 100644 --- a/api_docs/kbn_unified_data_table.mdx +++ b/api_docs/kbn_unified_data_table.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-unified-data-table title: "@kbn/unified-data-table" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/unified-data-table plugin -date: 2023-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/unified-data-table'] --- import kbnUnifiedDataTableObj from './kbn_unified_data_table.devdocs.json'; diff --git a/api_docs/kbn_unified_doc_viewer.mdx b/api_docs/kbn_unified_doc_viewer.mdx index 666bd58eaad9b..2d0d90be86aa2 100644 --- a/api_docs/kbn_unified_doc_viewer.mdx +++ b/api_docs/kbn_unified_doc_viewer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-unified-doc-viewer title: "@kbn/unified-doc-viewer" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/unified-doc-viewer plugin -date: 2023-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/unified-doc-viewer'] --- import kbnUnifiedDocViewerObj from './kbn_unified_doc_viewer.devdocs.json'; diff --git a/api_docs/kbn_unified_field_list.mdx b/api_docs/kbn_unified_field_list.mdx index 9bc53a061aa05..8f859cf40d897 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/unified-field-list'] --- import kbnUnifiedFieldListObj from './kbn_unified_field_list.devdocs.json'; diff --git a/api_docs/kbn_url_state.mdx b/api_docs/kbn_url_state.mdx index eaf9c99efbc17..1bf81f870f44f 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-10-31 +date: 2023-11-03 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 121976726a933..c3d696ad965ad 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-10-31 +date: 2023-11-03 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 0c5303da3244b..902e90a90c622 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/user-profile-components'] --- import kbnUserProfileComponentsObj from './kbn_user_profile_components.devdocs.json'; diff --git a/api_docs/kbn_utility_types.mdx b/api_docs/kbn_utility_types.mdx index c2cb8a77fa4e1..4de3eb90bc980 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/utility-types'] --- import kbnUtilityTypesObj from './kbn_utility_types.devdocs.json'; diff --git a/api_docs/kbn_utility_types_jest.mdx b/api_docs/kbn_utility_types_jest.mdx index 795344175bb63..8c9c4bb8e3c86 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-10-31 +date: 2023-11-03 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 6fd9bba7c564c..eb0b5866e0921 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/utils'] --- import kbnUtilsObj from './kbn_utils.devdocs.json'; diff --git a/api_docs/kbn_visualization_ui_components.mdx b/api_docs/kbn_visualization_ui_components.mdx index 748093893fd26..6ba7980e44d86 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/visualization-ui-components'] --- import kbnVisualizationUiComponentsObj from './kbn_visualization_ui_components.devdocs.json'; diff --git a/api_docs/kbn_xstate_utils.mdx b/api_docs/kbn_xstate_utils.mdx index d537bb99c77c3..fc0df5e5bca92 100644 --- a/api_docs/kbn_xstate_utils.mdx +++ b/api_docs/kbn_xstate_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-xstate-utils title: "@kbn/xstate-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/xstate-utils plugin -date: 2023-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/xstate-utils'] --- import kbnXstateUtilsObj from './kbn_xstate_utils.devdocs.json'; diff --git a/api_docs/kbn_yarn_lock_validator.mdx b/api_docs/kbn_yarn_lock_validator.mdx index ef944064b4f63..c99ebd6cdeaf2 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/yarn-lock-validator'] --- import kbnYarnLockValidatorObj from './kbn_yarn_lock_validator.devdocs.json'; diff --git a/api_docs/kbn_zod_helpers.mdx b/api_docs/kbn_zod_helpers.mdx index 3ba877e80b423..0c1e995569328 100644 --- a/api_docs/kbn_zod_helpers.mdx +++ b/api_docs/kbn_zod_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-zod-helpers title: "@kbn/zod-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/zod-helpers plugin -date: 2023-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/zod-helpers'] --- import kbnZodHelpersObj from './kbn_zod_helpers.devdocs.json'; diff --git a/api_docs/kibana_overview.mdx b/api_docs/kibana_overview.mdx index 2bf40f4639719..c4db5c1cf5cad 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-10-31 +date: 2023-11-03 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 913b1ed574427..d7188e68af935 100644 --- a/api_docs/kibana_react.devdocs.json +++ b/api_docs/kibana_react.devdocs.json @@ -1223,6 +1223,18 @@ "plugin": "fleet", "path": "x-pack/plugins/fleet/public/applications/fleet/app.tsx" }, + { + "plugin": "metricsDataAccess", + "path": "x-pack/plugins/metrics_data_access/public/apps/common_providers.tsx" + }, + { + "plugin": "metricsDataAccess", + "path": "x-pack/plugins/metrics_data_access/public/apps/common_providers.tsx" + }, + { + "plugin": "metricsDataAccess", + "path": "x-pack/plugins/metrics_data_access/public/apps/common_providers.tsx" + }, { "plugin": "licenseManagement", "path": "x-pack/plugins/license_management/public/shared_imports.ts" @@ -1359,18 +1371,6 @@ "plugin": "ml", "path": "x-pack/plugins/ml/public/application/management/jobs_list/components/jobs_list_page/jobs_list_page.tsx" }, - { - "plugin": "infra", - "path": "x-pack/plugins/infra/public/apps/common_providers.tsx" - }, - { - "plugin": "infra", - "path": "x-pack/plugins/infra/public/apps/common_providers.tsx" - }, - { - "plugin": "infra", - "path": "x-pack/plugins/infra/public/apps/common_providers.tsx" - }, { "plugin": "profiling", "path": "x-pack/plugins/profiling/public/app.tsx" @@ -1563,6 +1563,18 @@ "plugin": "indexLifecycleManagement", "path": "x-pack/plugins/index_lifecycle_management/public/application/index.tsx" }, + { + "plugin": "infra", + "path": "x-pack/plugins/infra/public/apps/common_providers.tsx" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/infra/public/apps/common_providers.tsx" + }, + { + "plugin": "infra", + "path": "x-pack/plugins/infra/public/apps/common_providers.tsx" + }, { "plugin": "ingestPipelines", "path": "x-pack/plugins/ingest_pipelines/public/shared_imports.ts" diff --git a/api_docs/kibana_react.mdx b/api_docs/kibana_react.mdx index c445b9fb5f54e..9935315b7b41e 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'kibanaReact'] --- import kibanaReactObj from './kibana_react.devdocs.json'; diff --git a/api_docs/kibana_utils.mdx b/api_docs/kibana_utils.mdx index f817d3431d7ee..130c02d802a5c 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'kibanaUtils'] --- import kibanaUtilsObj from './kibana_utils.devdocs.json'; diff --git a/api_docs/kubernetes_security.mdx b/api_docs/kubernetes_security.mdx index f9ff56a5539b3..091800e3adb1a 100644 --- a/api_docs/kubernetes_security.mdx +++ b/api_docs/kubernetes_security.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kubernetesSecurity title: "kubernetesSecurity" image: https://source.unsplash.com/400x175/?github description: API docs for the kubernetesSecurity plugin -date: 2023-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'kubernetesSecurity'] --- import kubernetesSecurityObj from './kubernetes_security.devdocs.json'; diff --git a/api_docs/lens.mdx b/api_docs/lens.mdx index ab995f630e824..ec22ee08b8f98 100644 --- a/api_docs/lens.mdx +++ b/api_docs/lens.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/lens title: "lens" image: https://source.unsplash.com/400x175/?github description: API docs for the lens plugin -date: 2023-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'lens'] --- import lensObj from './lens.devdocs.json'; diff --git a/api_docs/license_api_guard.mdx b/api_docs/license_api_guard.mdx index f67b35d98df23..6b5b4103c7d49 100644 --- a/api_docs/license_api_guard.mdx +++ b/api_docs/license_api_guard.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/licenseApiGuard title: "licenseApiGuard" image: https://source.unsplash.com/400x175/?github description: API docs for the licenseApiGuard plugin -date: 2023-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'licenseApiGuard'] --- import licenseApiGuardObj from './license_api_guard.devdocs.json'; diff --git a/api_docs/license_management.mdx b/api_docs/license_management.mdx index 12755ca78d13e..16af3a33ee19e 100644 --- a/api_docs/license_management.mdx +++ b/api_docs/license_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/licenseManagement title: "licenseManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the licenseManagement plugin -date: 2023-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'licenseManagement'] --- import licenseManagementObj from './license_management.devdocs.json'; diff --git a/api_docs/licensing.mdx b/api_docs/licensing.mdx index 2f1cd588a2bf4..955475b0ebe51 100644 --- a/api_docs/licensing.mdx +++ b/api_docs/licensing.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/licensing title: "licensing" image: https://source.unsplash.com/400x175/?github description: API docs for the licensing plugin -date: 2023-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'licensing'] --- import licensingObj from './licensing.devdocs.json'; diff --git a/api_docs/links.mdx b/api_docs/links.mdx index 42b6e435c2296..720afde920e61 100644 --- a/api_docs/links.mdx +++ b/api_docs/links.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/links title: "links" image: https://source.unsplash.com/400x175/?github description: API docs for the links plugin -date: 2023-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'links'] --- import linksObj from './links.devdocs.json'; diff --git a/api_docs/lists.mdx b/api_docs/lists.mdx index c68f665104aca..e9754a6d6e548 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'lists'] --- import listsObj from './lists.devdocs.json'; diff --git a/api_docs/log_explorer.mdx b/api_docs/log_explorer.mdx index 5e805d008ef27..b6fdaee0fa5f8 100644 --- a/api_docs/log_explorer.mdx +++ b/api_docs/log_explorer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/logExplorer title: "logExplorer" image: https://source.unsplash.com/400x175/?github description: API docs for the logExplorer plugin -date: 2023-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'logExplorer'] --- import logExplorerObj from './log_explorer.devdocs.json'; diff --git a/api_docs/logs_shared.devdocs.json b/api_docs/logs_shared.devdocs.json index 8890c3f9cdfff..e911fdaa0f16b 100644 --- a/api_docs/logs_shared.devdocs.json +++ b/api_docs/logs_shared.devdocs.json @@ -4931,6 +4931,153 @@ } ], "interfaces": [ + { + "parentPluginId": "logsShared", + "id": "def-common.LogsLocatorParams", + "type": "Interface", + "tags": [], + "label": "LogsLocatorParams", + "description": [], + "signature": [ + { + "pluginId": "logsShared", + "scope": "common", + "docId": "kibLogsSharedPluginApi", + "section": "def-common.LogsLocatorParams", + "text": "LogsLocatorParams" + }, + " extends ", + { + "pluginId": "@kbn/utility-types", + "scope": "common", + "docId": "kibKbnUtilityTypesPluginApi", + "section": "def-common.SerializableRecord", + "text": "SerializableRecord" + } + ], + "path": "x-pack/plugins/logs_shared/common/locators/logs_locator.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "logsShared", + "id": "def-common.LogsLocatorParams.time", + "type": "number", + "tags": [], + "label": "time", + "description": [ + "Defines log position" + ], + "signature": [ + "number | undefined" + ], + "path": "x-pack/plugins/logs_shared/common/locators/logs_locator.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "logsShared", + "id": "def-common.LogsLocatorParams.timeRange", + "type": "Object", + "tags": [], + "label": "timeRange", + "description": [ + "\nOptionally set the time range in the time picker." + ], + "signature": [ + "{ startTime: number; endTime: number; } | undefined" + ], + "path": "x-pack/plugins/logs_shared/common/locators/logs_locator.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "logsShared", + "id": "def-common.LogsLocatorParams.filter", + "type": "string", + "tags": [], + "label": "filter", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "x-pack/plugins/logs_shared/common/locators/logs_locator.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "logsShared", + "id": "def-common.LogsLocatorParams.logView", + "type": "CompoundType", + "tags": [], + "label": "logView", + "description": [], + "signature": [ + "{ logViewId: string; type: \"log-view-reference\"; } | { type: \"log-view-inline\"; id: string; attributes: { name: string; description: string; logIndices: { type: \"data_view\"; dataViewId: string; } | { type: \"index_name\"; indexName: string; }; logColumns: ({ timestampColumn: { id: string; }; } | { messageColumn: { id: string; }; } | { fieldColumn: { id: string; } & { field: string; }; })[]; }; } | undefined" + ], + "path": "x-pack/plugins/logs_shared/common/locators/logs_locator.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "logsShared", + "id": "def-common.NodeLogsLocatorParams", + "type": "Interface", + "tags": [], + "label": "NodeLogsLocatorParams", + "description": [], + "signature": [ + { + "pluginId": "logsShared", + "scope": "common", + "docId": "kibLogsSharedPluginApi", + "section": "def-common.NodeLogsLocatorParams", + "text": "NodeLogsLocatorParams" + }, + " extends ", + { + "pluginId": "logsShared", + "scope": "common", + "docId": "kibLogsSharedPluginApi", + "section": "def-common.LogsLocatorParams", + "text": "LogsLocatorParams" + } + ], + "path": "x-pack/plugins/logs_shared/common/locators/node_logs_locator.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "logsShared", + "id": "def-common.NodeLogsLocatorParams.nodeId", + "type": "string", + "tags": [], + "label": "nodeId", + "description": [], + "path": "x-pack/plugins/logs_shared/common/locators/node_logs_locator.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "logsShared", + "id": "def-common.NodeLogsLocatorParams.nodeType", + "type": "CompoundType", + "tags": [], + "label": "nodeType", + "description": [], + "signature": [ + "\"host\" | \"container\" | \"pod\" | \"awsEC2\" | \"awsS3\" | \"awsSQS\" | \"awsRDS\"" + ], + "path": "x-pack/plugins/logs_shared/common/locators/node_logs_locator.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, { "parentPluginId": "logsShared", "id": "def-common.ResolvedLogView", @@ -5505,6 +5652,21 @@ "trackAdoption": false, "initialIsOpen": false }, + { + "parentPluginId": "logsShared", + "id": "def-common.LOGS_LOCATOR_ID", + "type": "string", + "tags": [], + "label": "LOGS_LOCATOR_ID", + "description": [], + "signature": [ + "\"LOGS_LOCATOR\"" + ], + "path": "x-pack/plugins/logs_shared/common/locators/logs_locator.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, { "parentPluginId": "logsShared", "id": "def-common.LogTimestampColumn", @@ -5595,6 +5757,21 @@ "trackAdoption": false, "initialIsOpen": false }, + { + "parentPluginId": "logsShared", + "id": "def-common.NODE_LOGS_LOCATOR_ID", + "type": "string", + "tags": [], + "label": "NODE_LOGS_LOCATOR_ID", + "description": [], + "signature": [ + "\"NODE_LOGS_LOCATOR\"" + ], + "path": "x-pack/plugins/logs_shared/common/locators/node_logs_locator.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, { "parentPluginId": "logsShared", "id": "def-common.PersistedLogViewReference", diff --git a/api_docs/logs_shared.mdx b/api_docs/logs_shared.mdx index a229b80c79e05..2fabaae9b81d4 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'logsShared'] --- import logsSharedObj from './logs_shared.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/infra-monitoring-ui](https://github.com/orgs/elastic/teams/inf | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 269 | 10 | 256 | 27 | +| 279 | 10 | 264 | 27 | ## Client diff --git a/api_docs/management.mdx b/api_docs/management.mdx index b44ec3d7223bd..fe8a518d81e97 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-10-31 +date: 2023-11-03 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 7309b27ae968e..3f2a92d86c3a8 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-10-31 +date: 2023-11-03 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 7c6e8a8b72279..e7f593eb40edd 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'mapsEms'] --- import mapsEmsObj from './maps_ems.devdocs.json'; diff --git a/api_docs/metrics_data_access.devdocs.json b/api_docs/metrics_data_access.devdocs.json index de32b9fe2732f..fa981b59de281 100644 --- a/api_docs/metrics_data_access.devdocs.json +++ b/api_docs/metrics_data_access.devdocs.json @@ -6,7 +6,167 @@ "interfaces": [], "enums": [], "misc": [], - "objects": [] + "objects": [], + "setup": { + "parentPluginId": "metricsDataAccess", + "id": "def-public.MetricsDataPluginSetup", + "type": "Interface", + "tags": [], + "label": "MetricsDataPluginSetup", + "description": [], + "path": "x-pack/plugins/metrics_data_access/public/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "metricsDataAccess", + "id": "def-public.MetricsDataPluginSetup.metricsClient", + "type": "Object", + "tags": [], + "label": "metricsClient", + "description": [], + "signature": [ + "MetricsDataClient" + ], + "path": "x-pack/plugins/metrics_data_access/public/types.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "lifecycle": "setup", + "initialIsOpen": true + }, + "start": { + "parentPluginId": "metricsDataAccess", + "id": "def-public.MetricsDataPluginStart", + "type": "Interface", + "tags": [], + "label": "MetricsDataPluginStart", + "description": [], + "path": "x-pack/plugins/metrics_data_access/public/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "metricsDataAccess", + "id": "def-public.MetricsDataPluginStart.metricsClient", + "type": "Object", + "tags": [], + "label": "metricsClient", + "description": [], + "signature": [ + "MetricsDataClient" + ], + "path": "x-pack/plugins/metrics_data_access/public/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "metricsDataAccess", + "id": "def-public.MetricsDataPluginStart.HostMetricsTable", + "type": "Function", + "tags": [], + "label": "HostMetricsTable", + "description": [], + "signature": [ + "(props: ", + "NodeMetricsTableProps", + ") => JSX.Element" + ], + "path": "x-pack/plugins/metrics_data_access/public/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "metricsDataAccess", + "id": "def-public.MetricsDataPluginStart.HostMetricsTable.$1", + "type": "CompoundType", + "tags": [], + "label": "props", + "description": [], + "signature": [ + "NodeMetricsTableProps" + ], + "path": "x-pack/plugins/metrics_data_access/public/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "metricsDataAccess", + "id": "def-public.MetricsDataPluginStart.PodMetricsTable", + "type": "Function", + "tags": [], + "label": "PodMetricsTable", + "description": [], + "signature": [ + "(props: ", + "NodeMetricsTableProps", + ") => JSX.Element" + ], + "path": "x-pack/plugins/metrics_data_access/public/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "metricsDataAccess", + "id": "def-public.MetricsDataPluginStart.PodMetricsTable.$1", + "type": "CompoundType", + "tags": [], + "label": "props", + "description": [], + "signature": [ + "NodeMetricsTableProps" + ], + "path": "x-pack/plugins/metrics_data_access/public/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "metricsDataAccess", + "id": "def-public.MetricsDataPluginStart.ContainerMetricsTable", + "type": "Function", + "tags": [], + "label": "ContainerMetricsTable", + "description": [], + "signature": [ + "(props: ", + "NodeMetricsTableProps", + ") => JSX.Element" + ], + "path": "x-pack/plugins/metrics_data_access/public/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "metricsDataAccess", + "id": "def-public.MetricsDataPluginStart.ContainerMetricsTable.$1", + "type": "CompoundType", + "tags": [], + "label": "props", + "description": [], + "signature": [ + "NodeMetricsTableProps" + ], + "path": "x-pack/plugins/metrics_data_access/public/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + } + ], + "lifecycle": "start", + "initialIsOpen": true + } }, "server": { "classes": [ @@ -348,10 +508,1320 @@ }, "common": { "classes": [], - "functions": [], + "functions": [ + { + "parentPluginId": "metricsDataAccess", + "id": "def-common.findInventoryFields", + "type": "Function", + "tags": [], + "label": "findInventoryFields", + "description": [], + "signature": [ + "(type: \"host\" | \"container\" | \"pod\" | \"awsEC2\" | \"awsS3\" | \"awsSQS\" | \"awsRDS\") => { id: string; name: string; os?: string | undefined; ip?: string | undefined; cloudProvider?: string | undefined; }" + ], + "path": "x-pack/plugins/metrics_data_access/common/inventory_models/index.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "metricsDataAccess", + "id": "def-common.findInventoryFields.$1", + "type": "CompoundType", + "tags": [], + "label": "type", + "description": [], + "signature": [ + "\"host\" | \"container\" | \"pod\" | \"awsEC2\" | \"awsS3\" | \"awsSQS\" | \"awsRDS\"" + ], + "path": "x-pack/plugins/metrics_data_access/common/inventory_models/index.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "metricsDataAccess", + "id": "def-common.findInventoryModel", + "type": "Function", + "tags": [], + "label": "findInventoryModel", + "description": [], + "signature": [ + "(type: \"host\" | \"container\" | \"pod\" | \"awsEC2\" | \"awsS3\" | \"awsSQS\" | \"awsRDS\") => ", + "InventoryModel" + ], + "path": "x-pack/plugins/metrics_data_access/common/inventory_models/index.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "metricsDataAccess", + "id": "def-common.findInventoryModel.$1", + "type": "CompoundType", + "tags": [], + "label": "type", + "description": [], + "signature": [ + "\"host\" | \"container\" | \"pod\" | \"awsEC2\" | \"awsS3\" | \"awsSQS\" | \"awsRDS\"" + ], + "path": "x-pack/plugins/metrics_data_access/common/inventory_models/index.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "metricsDataAccess", + "id": "def-common.getFieldByType", + "type": "Function", + "tags": [], + "label": "getFieldByType", + "description": [], + "signature": [ + "(type: \"host\" | \"container\" | \"pod\" | \"awsEC2\" | \"awsS3\" | \"awsSQS\" | \"awsRDS\") => \"container.id\" | \"host.name\" | \"kubernetes.pod.uid\" | undefined" + ], + "path": "x-pack/plugins/metrics_data_access/common/inventory_models/index.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "metricsDataAccess", + "id": "def-common.getFieldByType.$1", + "type": "CompoundType", + "tags": [], + "label": "type", + "description": [], + "signature": [ + "\"host\" | \"container\" | \"pod\" | \"awsEC2\" | \"awsS3\" | \"awsSQS\" | \"awsRDS\"" + ], + "path": "x-pack/plugins/metrics_data_access/common/inventory_models/index.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "metricsDataAccess", + "id": "def-common.networkTraffic", + "type": "Function", + "tags": [], + "label": "networkTraffic", + "description": [], + "signature": [ + "(id: string, field: string) => { [x: string]: { [x: string]: { field: string; } | undefined; } | { percentiles: { field: string; percents: number[]; }; } | { bucket_script: { buckets_path: { [x: string]: string; }; script: { source: string; lang: \"painless\" | \"expression\"; }; } & { gap_policy?: \"insert_zeros\" | \"skip\" | undefined; }; } | { cumulative_sum: { buckets_path: string; }; } | { derivative: { buckets_path: string; gap_policy: \"insert_zeros\" | \"skip\"; unit: string; }; } | { sum_bucket: { buckets_path: string; }; } | ", + "SnapshotTermsWithAggregation", + " | { cardinality: { field?: string | undefined; }; } | { top_metrics: { metrics: { field: string; }[] | { field: string; }; } & { size?: number | undefined; sort?: { [x: string]: \"asc\" | \"desc\"; } | undefined; }; } | { filter: { exists: { field: string; }; }; aggs: { period: { max: { field: string; }; }; }; }; }" + ], + "path": "x-pack/plugins/metrics_data_access/common/inventory_models/shared/metrics/snapshot/network_traffic.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "metricsDataAccess", + "id": "def-common.networkTraffic.$1", + "type": "string", + "tags": [], + "label": "id", + "description": [], + "signature": [ + "string" + ], + "path": "x-pack/plugins/metrics_data_access/common/inventory_models/shared/metrics/snapshot/network_traffic.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "metricsDataAccess", + "id": "def-common.networkTraffic.$2", + "type": "string", + "tags": [], + "label": "field", + "description": [], + "signature": [ + "string" + ], + "path": "x-pack/plugins/metrics_data_access/common/inventory_models/shared/metrics/snapshot/network_traffic.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + } + ], "interfaces": [], "enums": [], - "misc": [], - "objects": [] + "misc": [ + { + "parentPluginId": "metricsDataAccess", + "id": "def-common.awsEC2SnapshotMetricTypes", + "type": "Array", + "tags": [], + "label": "awsEC2SnapshotMetricTypes", + "description": [], + "signature": [ + "(\"rx\" | \"cpu\" | \"tx\" | \"diskIOReadBytes\" | \"diskIOWriteBytes\")[]" + ], + "path": "x-pack/plugins/metrics_data_access/common/inventory_models/aws_ec2/metrics/index.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "metricsDataAccess", + "id": "def-common.awsRDSSnapshotMetricTypes", + "type": "Array", + "tags": [], + "label": "awsRDSSnapshotMetricTypes", + "description": [], + "signature": [ + "(\"cpu\" | \"rdsConnections\" | \"rdsQueriesExecuted\" | \"rdsActiveTransactions\" | \"rdsLatency\")[]" + ], + "path": "x-pack/plugins/metrics_data_access/common/inventory_models/aws_rds/metrics/index.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "metricsDataAccess", + "id": "def-common.awsS3SnapshotMetricTypes", + "type": "Array", + "tags": [], + "label": "awsS3SnapshotMetricTypes", + "description": [], + "signature": [ + "(\"s3TotalRequests\" | \"s3NumberOfObjects\" | \"s3BucketSize\" | \"s3DownloadBytes\" | \"s3UploadBytes\")[]" + ], + "path": "x-pack/plugins/metrics_data_access/common/inventory_models/aws_s3/metrics/index.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "metricsDataAccess", + "id": "def-common.awsSQSSnapshotMetricTypes", + "type": "Array", + "tags": [], + "label": "awsSQSSnapshotMetricTypes", + "description": [], + "signature": [ + "(\"sqsMessagesVisible\" | \"sqsMessagesDelayed\" | \"sqsMessagesSent\" | \"sqsMessagesEmpty\" | \"sqsOldestMessage\")[]" + ], + "path": "x-pack/plugins/metrics_data_access/common/inventory_models/aws_sqs/metrics/index.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "metricsDataAccess", + "id": "def-common.containerSnapshotMetricTypes", + "type": "Array", + "tags": [], + "label": "containerSnapshotMetricTypes", + "description": [], + "signature": [ + "(\"memory\" | \"rx\" | \"cpu\" | \"tx\")[]" + ], + "path": "x-pack/plugins/metrics_data_access/common/inventory_models/container/metrics/index.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "metricsDataAccess", + "id": "def-common.hostSnapshotMetricTypes", + "type": "Array", + "tags": [], + "label": "hostSnapshotMetricTypes", + "description": [], + "signature": [ + "(\"memory\" | \"rx\" | \"cpu\" | \"diskLatency\" | \"diskSpaceUsage\" | \"load\" | \"memoryFree\" | \"memoryTotal\" | \"normalizedLoad1m\" | \"tx\" | \"logRate\")[]" + ], + "path": "x-pack/plugins/metrics_data_access/common/inventory_models/host/metrics/index.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "metricsDataAccess", + "id": "def-common.InventoryFormatterType", + "type": "Type", + "tags": [], + "label": "InventoryFormatterType", + "description": [], + "signature": [ + "\"number\" | \"percent\" | \"bytes\" | \"abbreviatedNumber\" | \"bits\" | \"highPrecision\"" + ], + "path": "x-pack/plugins/metrics_data_access/common/inventory_models/types.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "metricsDataAccess", + "id": "def-common.InventoryItemType", + "type": "Type", + "tags": [], + "label": "InventoryItemType", + "description": [], + "signature": [ + "\"host\" | \"container\" | \"pod\" | \"awsEC2\" | \"awsS3\" | \"awsSQS\" | \"awsRDS\"" + ], + "path": "x-pack/plugins/metrics_data_access/common/inventory_models/types.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "metricsDataAccess", + "id": "def-common.InventoryMetric", + "type": "Type", + "tags": [], + "label": "InventoryMetric", + "description": [], + "signature": [ + "\"custom\" | \"hostSystemOverview\" | \"hostCpuUsage\" | \"hostFilesystem\" | \"hostK8sOverview\" | \"hostK8sCpuCap\" | \"hostK8sDiskCap\" | \"hostK8sMemoryCap\" | \"hostK8sPodCap\" | \"hostLoad\" | \"hostMemoryUsage\" | \"hostNetworkTraffic\" | \"hostDockerOverview\" | \"hostDockerInfo\" | \"hostDockerTop5ByCpu\" | \"hostDockerTop5ByMemory\" | \"podOverview\" | \"podCpuUsage\" | \"podMemoryUsage\" | \"podLogUsage\" | \"podNetworkTraffic\" | \"containerOverview\" | \"containerCpuKernel\" | \"containerCpuUsage\" | \"containerDiskIOOps\" | \"containerDiskIOBytes\" | \"containerMemory\" | \"containerNetworkTraffic\" | \"containerK8sOverview\" | \"containerK8sCpuUsage\" | \"containerK8sMemoryUsage\" | \"nginxHits\" | \"nginxRequestRate\" | \"nginxActiveConnections\" | \"nginxRequestsPerConnection\" | \"awsOverview\" | \"awsCpuUtilization\" | \"awsNetworkBytes\" | \"awsNetworkPackets\" | \"awsDiskioBytes\" | \"awsDiskioOps\" | \"awsEC2CpuUtilization\" | \"awsEC2NetworkTraffic\" | \"awsEC2DiskIOBytes\" | \"awsS3TotalRequests\" | \"awsS3NumberOfObjects\" | \"awsS3BucketSize\" | \"awsS3DownloadBytes\" | \"awsS3UploadBytes\" | \"awsRDSCpuTotal\" | \"awsRDSConnections\" | \"awsRDSQueriesExecuted\" | \"awsRDSActiveTransactions\" | \"awsRDSLatency\" | \"awsSQSMessagesVisible\" | \"awsSQSMessagesDelayed\" | \"awsSQSMessagesSent\" | \"awsSQSMessagesEmpty\" | \"awsSQSOldestMessage\"" + ], + "path": "x-pack/plugins/metrics_data_access/common/inventory_models/types.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "metricsDataAccess", + "id": "def-common.inventoryModels", + "type": "Array", + "tags": [], + "label": "inventoryModels", + "description": [], + "signature": [ + "InventoryModel", + "[]" + ], + "path": "x-pack/plugins/metrics_data_access/common/inventory_models/index.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "metricsDataAccess", + "id": "def-common.InventoryVisType", + "type": "Type", + "tags": [], + "label": "InventoryVisType", + "description": [], + "signature": [ + "\"bar\" | \"line\" | \"area\"" + ], + "path": "x-pack/plugins/metrics_data_access/common/inventory_models/types.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "metricsDataAccess", + "id": "def-common.MetricsUIAggregation", + "type": "Type", + "tags": [], + "label": "MetricsUIAggregation", + "description": [], + "signature": [ + "{ [x: string]: { [x: string]: { field: string; } | undefined; } | { percentiles: { field: string; percents: number[]; }; } | { bucket_script: { buckets_path: { [x: string]: string; }; script: { source: string; lang: \"painless\" | \"expression\"; }; } & { gap_policy?: \"insert_zeros\" | \"skip\" | undefined; }; } | { cumulative_sum: { buckets_path: string; }; } | { derivative: { buckets_path: string; gap_policy: \"insert_zeros\" | \"skip\"; unit: string; }; } | { sum_bucket: { buckets_path: string; }; } | ", + "SnapshotTermsWithAggregation", + " | { cardinality: { field?: string | undefined; }; } | { top_metrics: { metrics: { field: string; }[] | { field: string; }; } & { size?: number | undefined; sort?: { [x: string]: \"asc\" | \"desc\"; } | undefined; }; } | { filter: { exists: { field: string; }; }; aggs: { period: { max: { field: string; }; }; }; }; }" + ], + "path": "x-pack/plugins/metrics_data_access/common/inventory_models/types.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "metricsDataAccess", + "id": "def-common.podSnapshotMetricTypes", + "type": "Array", + "tags": [], + "label": "podSnapshotMetricTypes", + "description": [], + "signature": [ + "(\"memory\" | \"rx\" | \"cpu\" | \"tx\")[]" + ], + "path": "x-pack/plugins/metrics_data_access/common/inventory_models/pod/metrics/index.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "metricsDataAccess", + "id": "def-common.SnapshotMetricType", + "type": "Type", + "tags": [], + "label": "SnapshotMetricType", + "description": [], + "signature": [ + "\"count\" | \"custom\" | \"memory\" | \"rx\" | \"cpu\" | \"diskLatency\" | \"diskSpaceUsage\" | \"load\" | \"memoryFree\" | \"memoryTotal\" | \"normalizedLoad1m\" | \"tx\" | \"logRate\" | \"diskIOReadBytes\" | \"diskIOWriteBytes\" | \"s3TotalRequests\" | \"s3NumberOfObjects\" | \"s3BucketSize\" | \"s3DownloadBytes\" | \"s3UploadBytes\" | \"rdsConnections\" | \"rdsQueriesExecuted\" | \"rdsActiveTransactions\" | \"rdsLatency\" | \"sqsMessagesVisible\" | \"sqsMessagesDelayed\" | \"sqsMessagesSent\" | \"sqsMessagesEmpty\" | \"sqsOldestMessage\"" + ], + "path": "x-pack/plugins/metrics_data_access/common/inventory_models/types.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "metricsDataAccess", + "id": "def-common.TSVBMetricModel", + "type": "Type", + "tags": [], + "label": "TSVBMetricModel", + "description": [], + "signature": [ + "{ id: \"custom\" | \"hostSystemOverview\" | \"hostCpuUsage\" | \"hostFilesystem\" | \"hostK8sOverview\" | \"hostK8sCpuCap\" | \"hostK8sDiskCap\" | \"hostK8sMemoryCap\" | \"hostK8sPodCap\" | \"hostLoad\" | \"hostMemoryUsage\" | \"hostNetworkTraffic\" | \"hostDockerOverview\" | \"hostDockerInfo\" | \"hostDockerTop5ByCpu\" | \"hostDockerTop5ByMemory\" | \"podOverview\" | \"podCpuUsage\" | \"podMemoryUsage\" | \"podLogUsage\" | \"podNetworkTraffic\" | \"containerOverview\" | \"containerCpuKernel\" | \"containerCpuUsage\" | \"containerDiskIOOps\" | \"containerDiskIOBytes\" | \"containerMemory\" | \"containerNetworkTraffic\" | \"containerK8sOverview\" | \"containerK8sCpuUsage\" | \"containerK8sMemoryUsage\" | \"nginxHits\" | \"nginxRequestRate\" | \"nginxActiveConnections\" | \"nginxRequestsPerConnection\" | \"awsOverview\" | \"awsCpuUtilization\" | \"awsNetworkBytes\" | \"awsNetworkPackets\" | \"awsDiskioBytes\" | \"awsDiskioOps\" | \"awsEC2CpuUtilization\" | \"awsEC2NetworkTraffic\" | \"awsEC2DiskIOBytes\" | \"awsS3TotalRequests\" | \"awsS3NumberOfObjects\" | \"awsS3BucketSize\" | \"awsS3DownloadBytes\" | \"awsS3UploadBytes\" | \"awsRDSCpuTotal\" | \"awsRDSConnections\" | \"awsRDSQueriesExecuted\" | \"awsRDSActiveTransactions\" | \"awsRDSLatency\" | \"awsSQSMessagesVisible\" | \"awsSQSMessagesDelayed\" | \"awsSQSMessagesSent\" | \"awsSQSMessagesEmpty\" | \"awsSQSOldestMessage\"; requires: string[]; index_pattern: string | string[]; interval: string; time_field: string; type: string; series: ({ id: string; metrics: ({ id: string; type: \"count\"; } | ({ id: string; type: \"min\" | \"max\" | \"sum\" | \"avg\" | \"count\" | \"cardinality\" | \"cumulative_sum\" | \"derivative\" | \"calculation\" | \"series_agg\" | \"positive_only\"; } & { field?: string | undefined; }) | { id: string; script: string; type: \"calculation\"; variables: { field: string; id: string; name: string; }[]; } | { id: string; field: string; unit: string; type: \"derivative\"; } | ({ id: string; type: \"percentile\"; percentiles: { id: string; value: number; }[]; } & { field?: string | undefined; }) | { id: string; function: string; type: \"series_agg\"; })[]; split_mode: string; } & { terms_field?: string | undefined; terms_size?: number | undefined; terms_order_by?: string | undefined; filter?: { query: string; language: \"kuery\" | \"lucene\"; } | undefined; })[]; } & { filter?: string | undefined; map_field_to?: string | undefined; id_type?: \"cloud\" | \"node\" | undefined; drop_last_bucket?: boolean | undefined; }" + ], + "path": "x-pack/plugins/metrics_data_access/common/inventory_models/types.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "metricsDataAccess", + "id": "def-common.TSVBMetricModelCreator", + "type": "Type", + "tags": [], + "label": "TSVBMetricModelCreator", + "description": [], + "signature": [ + "(timeField: string, indexPattern: string | string[], interval: string) => { id: \"custom\" | \"hostSystemOverview\" | \"hostCpuUsage\" | \"hostFilesystem\" | \"hostK8sOverview\" | \"hostK8sCpuCap\" | \"hostK8sDiskCap\" | \"hostK8sMemoryCap\" | \"hostK8sPodCap\" | \"hostLoad\" | \"hostMemoryUsage\" | \"hostNetworkTraffic\" | \"hostDockerOverview\" | \"hostDockerInfo\" | \"hostDockerTop5ByCpu\" | \"hostDockerTop5ByMemory\" | \"podOverview\" | \"podCpuUsage\" | \"podMemoryUsage\" | \"podLogUsage\" | \"podNetworkTraffic\" | \"containerOverview\" | \"containerCpuKernel\" | \"containerCpuUsage\" | \"containerDiskIOOps\" | \"containerDiskIOBytes\" | \"containerMemory\" | \"containerNetworkTraffic\" | \"containerK8sOverview\" | \"containerK8sCpuUsage\" | \"containerK8sMemoryUsage\" | \"nginxHits\" | \"nginxRequestRate\" | \"nginxActiveConnections\" | \"nginxRequestsPerConnection\" | \"awsOverview\" | \"awsCpuUtilization\" | \"awsNetworkBytes\" | \"awsNetworkPackets\" | \"awsDiskioBytes\" | \"awsDiskioOps\" | \"awsEC2CpuUtilization\" | \"awsEC2NetworkTraffic\" | \"awsEC2DiskIOBytes\" | \"awsS3TotalRequests\" | \"awsS3NumberOfObjects\" | \"awsS3BucketSize\" | \"awsS3DownloadBytes\" | \"awsS3UploadBytes\" | \"awsRDSCpuTotal\" | \"awsRDSConnections\" | \"awsRDSQueriesExecuted\" | \"awsRDSActiveTransactions\" | \"awsRDSLatency\" | \"awsSQSMessagesVisible\" | \"awsSQSMessagesDelayed\" | \"awsSQSMessagesSent\" | \"awsSQSMessagesEmpty\" | \"awsSQSOldestMessage\"; requires: string[]; index_pattern: string | string[]; interval: string; time_field: string; type: string; series: ({ id: string; metrics: ({ id: string; type: \"count\"; } | ({ id: string; type: \"min\" | \"max\" | \"sum\" | \"avg\" | \"count\" | \"cardinality\" | \"cumulative_sum\" | \"derivative\" | \"calculation\" | \"series_agg\" | \"positive_only\"; } & { field?: string | undefined; }) | { id: string; script: string; type: \"calculation\"; variables: { field: string; id: string; name: string; }[]; } | { id: string; field: string; unit: string; type: \"derivative\"; } | ({ id: string; type: \"percentile\"; percentiles: { id: string; value: number; }[]; } & { field?: string | undefined; }) | { id: string; function: string; type: \"series_agg\"; })[]; split_mode: string; } & { terms_field?: string | undefined; terms_size?: number | undefined; terms_order_by?: string | undefined; filter?: { query: string; language: \"kuery\" | \"lucene\"; } | undefined; })[]; } & { filter?: string | undefined; map_field_to?: string | undefined; id_type?: \"cloud\" | \"node\" | undefined; drop_last_bucket?: boolean | undefined; }" + ], + "path": "x-pack/plugins/metrics_data_access/common/inventory_models/types.ts", + "deprecated": false, + "trackAdoption": false, + "returnComment": [], + "children": [ + { + "parentPluginId": "metricsDataAccess", + "id": "def-common.TSVBMetricModelCreator.$1", + "type": "string", + "tags": [], + "label": "timeField", + "description": [], + "path": "x-pack/plugins/metrics_data_access/common/inventory_models/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "metricsDataAccess", + "id": "def-common.TSVBMetricModelCreator.$2", + "type": "CompoundType", + "tags": [], + "label": "indexPattern", + "description": [], + "signature": [ + "string | string[]" + ], + "path": "x-pack/plugins/metrics_data_access/common/inventory_models/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "metricsDataAccess", + "id": "def-common.TSVBMetricModelCreator.$3", + "type": "string", + "tags": [], + "label": "interval", + "description": [], + "path": "x-pack/plugins/metrics_data_access/common/inventory_models/types.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + } + ], + "objects": [ + { + "parentPluginId": "metricsDataAccess", + "id": "def-common.ESBasicMetricAggRT", + "type": "Object", + "tags": [], + "label": "ESBasicMetricAggRT", + "description": [], + "signature": [ + "RecordC", + "<", + "StringC", + ", ", + "UnionC", + "<[", + "UndefinedC", + ", ", + "TypeC", + "<{ field: ", + "StringC", + "; }>]>>" + ], + "path": "x-pack/plugins/metrics_data_access/common/inventory_models/types.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "metricsDataAccess", + "id": "def-common.ESDerivativeAggRT", + "type": "Object", + "tags": [], + "label": "ESDerivativeAggRT", + "description": [], + "signature": [ + "TypeC", + "<{ derivative: ", + "TypeC", + "<{ buckets_path: ", + "StringC", + "; gap_policy: ", + "KeyofC", + "<{ skip: null; insert_zeros: null; }>; unit: ", + "StringC", + "; }>; }>" + ], + "path": "x-pack/plugins/metrics_data_access/common/inventory_models/types.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "metricsDataAccess", + "id": "def-common.ESSumBucketAggRT", + "type": "Object", + "tags": [], + "label": "ESSumBucketAggRT", + "description": [], + "signature": [ + "TypeC", + "<{ sum_bucket: ", + "TypeC", + "<{ buckets_path: ", + "StringC", + "; }>; }>" + ], + "path": "x-pack/plugins/metrics_data_access/common/inventory_models/types.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "metricsDataAccess", + "id": "def-common.ESTermsWithAggregationRT", + "type": "Object", + "tags": [], + "label": "ESTermsWithAggregationRT", + "description": [], + "signature": [ + "Type", + "<", + "SnapshotTermsWithAggregation", + ", ", + "SnapshotTermsWithAggregation", + ", unknown>" + ], + "path": "x-pack/plugins/metrics_data_access/common/inventory_models/types.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "metricsDataAccess", + "id": "def-common.InventoryFormatterTypeRT", + "type": "Object", + "tags": [], + "label": "InventoryFormatterTypeRT", + "description": [], + "signature": [ + "KeyofC", + "<{ abbreviatedNumber: null; bits: null; bytes: null; number: null; percent: null; highPrecision: null; }>" + ], + "path": "x-pack/plugins/metrics_data_access/common/inventory_models/types.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "metricsDataAccess", + "id": "def-common.InventoryMetricRT", + "type": "Object", + "tags": [], + "label": "InventoryMetricRT", + "description": [], + "signature": [ + "KeyofC", + "<{ hostSystemOverview: null; hostCpuUsage: null; hostFilesystem: null; hostK8sOverview: null; hostK8sCpuCap: null; hostK8sDiskCap: null; hostK8sMemoryCap: null; hostK8sPodCap: null; hostLoad: null; hostMemoryUsage: null; hostNetworkTraffic: null; hostDockerOverview: null; hostDockerInfo: null; hostDockerTop5ByCpu: null; hostDockerTop5ByMemory: null; podOverview: null; podCpuUsage: null; podMemoryUsage: null; podLogUsage: null; podNetworkTraffic: null; containerOverview: null; containerCpuKernel: null; containerCpuUsage: null; containerDiskIOOps: null; containerDiskIOBytes: null; containerMemory: null; containerNetworkTraffic: null; containerK8sOverview: null; containerK8sCpuUsage: null; containerK8sMemoryUsage: null; nginxHits: null; nginxRequestRate: null; nginxActiveConnections: null; nginxRequestsPerConnection: null; awsOverview: null; awsCpuUtilization: null; awsNetworkBytes: null; awsNetworkPackets: null; awsDiskioBytes: null; awsDiskioOps: null; awsEC2CpuUtilization: null; awsEC2NetworkTraffic: null; awsEC2DiskIOBytes: null; awsS3TotalRequests: null; awsS3NumberOfObjects: null; awsS3BucketSize: null; awsS3DownloadBytes: null; awsS3UploadBytes: null; awsRDSCpuTotal: null; awsRDSConnections: null; awsRDSQueriesExecuted: null; awsRDSActiveTransactions: null; awsRDSLatency: null; awsSQSMessagesVisible: null; awsSQSMessagesDelayed: null; awsSQSMessagesSent: null; awsSQSMessagesEmpty: null; awsSQSOldestMessage: null; custom: null; }>" + ], + "path": "x-pack/plugins/metrics_data_access/common/inventory_models/types.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "metricsDataAccess", + "id": "def-common.InventoryVisTypeRT", + "type": "Object", + "tags": [], + "label": "InventoryVisTypeRT", + "description": [], + "signature": [ + "KeyofC", + "<{ line: null; area: null; bar: null; }>" + ], + "path": "x-pack/plugins/metrics_data_access/common/inventory_models/types.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "metricsDataAccess", + "id": "def-common.ItemTypeRT", + "type": "Object", + "tags": [], + "label": "ItemTypeRT", + "description": [], + "signature": [ + "KeyofC", + "<{ host: null; pod: null; container: null; awsEC2: null; awsS3: null; awsSQS: null; awsRDS: null; }>" + ], + "path": "x-pack/plugins/metrics_data_access/common/inventory_models/types.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "metricsDataAccess", + "id": "def-common.metrics", + "type": "Object", + "tags": [], + "label": "metrics", + "description": [], + "path": "x-pack/plugins/metrics_data_access/common/inventory_models/metrics.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "metricsDataAccess", + "id": "def-common.metrics.tsvb", + "type": "Object", + "tags": [], + "label": "tsvb", + "description": [], + "path": "x-pack/plugins/metrics_data_access/common/inventory_models/metrics.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "metricsDataAccess", + "id": "def-common.metrics.tsvb.Unnamed", + "type": "Any", + "tags": [], + "label": "Unnamed", + "description": [], + "signature": [ + "any" + ], + "path": "x-pack/plugins/metrics_data_access/common/inventory_models/metrics.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "metricsDataAccess", + "id": "def-common.metrics.tsvb.Unnamed", + "type": "Any", + "tags": [], + "label": "Unnamed", + "description": [], + "signature": [ + "any" + ], + "path": "x-pack/plugins/metrics_data_access/common/inventory_models/metrics.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "metricsDataAccess", + "id": "def-common.metrics.tsvb.Unnamed", + "type": "Any", + "tags": [], + "label": "Unnamed", + "description": [], + "signature": [ + "any" + ], + "path": "x-pack/plugins/metrics_data_access/common/inventory_models/metrics.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "metricsDataAccess", + "id": "def-common.metrics.tsvb.Unnamed", + "type": "Any", + "tags": [], + "label": "Unnamed", + "description": [], + "signature": [ + "any" + ], + "path": "x-pack/plugins/metrics_data_access/common/inventory_models/metrics.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "metricsDataAccess", + "id": "def-common.metrics.tsvb.Unnamed", + "type": "Any", + "tags": [], + "label": "Unnamed", + "description": [], + "signature": [ + "any" + ], + "path": "x-pack/plugins/metrics_data_access/common/inventory_models/metrics.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "metricsDataAccess", + "id": "def-common.metrics.tsvb.Unnamed", + "type": "Any", + "tags": [], + "label": "Unnamed", + "description": [], + "signature": [ + "any" + ], + "path": "x-pack/plugins/metrics_data_access/common/inventory_models/metrics.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "metricsDataAccess", + "id": "def-common.metrics.tsvb.Unnamed", + "type": "Any", + "tags": [], + "label": "Unnamed", + "description": [], + "signature": [ + "any" + ], + "path": "x-pack/plugins/metrics_data_access/common/inventory_models/metrics.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "metricsDataAccess", + "id": "def-common.metrics.tsvb.Unnamed", + "type": "Any", + "tags": [], + "label": "Unnamed", + "description": [], + "signature": [ + "any" + ], + "path": "x-pack/plugins/metrics_data_access/common/inventory_models/metrics.ts", + "deprecated": false, + "trackAdoption": false + } + ] + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "metricsDataAccess", + "id": "def-common.MetricsUIAggregationRT", + "type": "Object", + "tags": [], + "label": "MetricsUIAggregationRT", + "description": [], + "signature": [ + "RecordC", + "<", + "StringC", + ", ", + "UnionC", + "<[", + "RecordC", + "<", + "StringC", + ", ", + "UnionC", + "<[", + "UndefinedC", + ", ", + "TypeC", + "<{ field: ", + "StringC", + "; }>]>>, ", + "TypeC", + "<{ percentiles: ", + "TypeC", + "<{ field: ", + "StringC", + "; percents: ", + "ArrayC", + "<", + "NumberC", + ">; }>; }>, ", + "TypeC", + "<{ bucket_script: ", + "IntersectionC", + "<[", + "TypeC", + "<{ buckets_path: ", + "RecordC", + "<", + "StringC", + ", ", + "StringC", + ">; script: ", + "TypeC", + "<{ source: ", + "StringC", + "; lang: ", + "KeyofC", + "<{ painless: null; expression: null; }>; }>; }>, ", + "PartialC", + "<{ gap_policy: ", + "KeyofC", + "<{ skip: null; insert_zeros: null; }>; }>]>; }>, ", + "TypeC", + "<{ cumulative_sum: ", + "TypeC", + "<{ buckets_path: ", + "StringC", + "; }>; }>, ", + "TypeC", + "<{ derivative: ", + "TypeC", + "<{ buckets_path: ", + "StringC", + "; gap_policy: ", + "KeyofC", + "<{ skip: null; insert_zeros: null; }>; unit: ", + "StringC", + "; }>; }>, ", + "TypeC", + "<{ sum_bucket: ", + "TypeC", + "<{ buckets_path: ", + "StringC", + "; }>; }>, ", + "Type", + "<", + "SnapshotTermsWithAggregation", + ", ", + "SnapshotTermsWithAggregation", + ", unknown>, ", + "TypeC", + "<{ cardinality: ", + "PartialC", + "<{ field: ", + "StringC", + "; }>; }>, ", + "TypeC", + "<{ top_metrics: ", + "IntersectionC", + "<[", + "TypeC", + "<{ metrics: ", + "UnionC", + "<[", + "ArrayC", + "<", + "TypeC", + "<{ field: ", + "StringC", + "; }>>, ", + "TypeC", + "<{ field: ", + "StringC", + "; }>]>; }>, ", + "PartialC", + "<{ size: ", + "NumberC", + "; sort: ", + "RecordC", + "<", + "StringC", + ", ", + "UnionC", + "<[", + "LiteralC", + "<\"desc\">, ", + "LiteralC", + "<\"asc\">]>>; }>]>; }>, ", + "TypeC", + "<{ filter: ", + "TypeC", + "<{ exists: ", + "TypeC", + "<{ field: ", + "StringC", + "; }>; }>; aggs: ", + "TypeC", + "<{ period: ", + "TypeC", + "<{ max: ", + "TypeC", + "<{ field: ", + "StringC", + "; }>; }>; }>; }>]>>" + ], + "path": "x-pack/plugins/metrics_data_access/common/inventory_models/types.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "metricsDataAccess", + "id": "def-common.SnapshotMetricTypeKeys", + "type": "Object", + "tags": [], + "label": "SnapshotMetricTypeKeys", + "description": [], + "path": "x-pack/plugins/metrics_data_access/common/inventory_models/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "metricsDataAccess", + "id": "def-common.SnapshotMetricTypeKeys.count", + "type": "Uncategorized", + "tags": [], + "label": "count", + "description": [], + "signature": [ + "null" + ], + "path": "x-pack/plugins/metrics_data_access/common/inventory_models/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "metricsDataAccess", + "id": "def-common.SnapshotMetricTypeKeys.cpu", + "type": "Uncategorized", + "tags": [], + "label": "cpu", + "description": [], + "signature": [ + "null" + ], + "path": "x-pack/plugins/metrics_data_access/common/inventory_models/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "metricsDataAccess", + "id": "def-common.SnapshotMetricTypeKeys.diskLatency", + "type": "Uncategorized", + "tags": [], + "label": "diskLatency", + "description": [], + "signature": [ + "null" + ], + "path": "x-pack/plugins/metrics_data_access/common/inventory_models/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "metricsDataAccess", + "id": "def-common.SnapshotMetricTypeKeys.diskSpaceUsage", + "type": "Uncategorized", + "tags": [], + "label": "diskSpaceUsage", + "description": [], + "signature": [ + "null" + ], + "path": "x-pack/plugins/metrics_data_access/common/inventory_models/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "metricsDataAccess", + "id": "def-common.SnapshotMetricTypeKeys.load", + "type": "Uncategorized", + "tags": [], + "label": "load", + "description": [], + "signature": [ + "null" + ], + "path": "x-pack/plugins/metrics_data_access/common/inventory_models/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "metricsDataAccess", + "id": "def-common.SnapshotMetricTypeKeys.memory", + "type": "Uncategorized", + "tags": [], + "label": "memory", + "description": [], + "signature": [ + "null" + ], + "path": "x-pack/plugins/metrics_data_access/common/inventory_models/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "metricsDataAccess", + "id": "def-common.SnapshotMetricTypeKeys.memoryFree", + "type": "Uncategorized", + "tags": [], + "label": "memoryFree", + "description": [], + "signature": [ + "null" + ], + "path": "x-pack/plugins/metrics_data_access/common/inventory_models/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "metricsDataAccess", + "id": "def-common.SnapshotMetricTypeKeys.memoryTotal", + "type": "Uncategorized", + "tags": [], + "label": "memoryTotal", + "description": [], + "signature": [ + "null" + ], + "path": "x-pack/plugins/metrics_data_access/common/inventory_models/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "metricsDataAccess", + "id": "def-common.SnapshotMetricTypeKeys.normalizedLoad1m", + "type": "Uncategorized", + "tags": [], + "label": "normalizedLoad1m", + "description": [], + "signature": [ + "null" + ], + "path": "x-pack/plugins/metrics_data_access/common/inventory_models/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "metricsDataAccess", + "id": "def-common.SnapshotMetricTypeKeys.tx", + "type": "Uncategorized", + "tags": [], + "label": "tx", + "description": [], + "signature": [ + "null" + ], + "path": "x-pack/plugins/metrics_data_access/common/inventory_models/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "metricsDataAccess", + "id": "def-common.SnapshotMetricTypeKeys.rx", + "type": "Uncategorized", + "tags": [], + "label": "rx", + "description": [], + "signature": [ + "null" + ], + "path": "x-pack/plugins/metrics_data_access/common/inventory_models/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "metricsDataAccess", + "id": "def-common.SnapshotMetricTypeKeys.logRate", + "type": "Uncategorized", + "tags": [], + "label": "logRate", + "description": [], + "signature": [ + "null" + ], + "path": "x-pack/plugins/metrics_data_access/common/inventory_models/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "metricsDataAccess", + "id": "def-common.SnapshotMetricTypeKeys.diskIOReadBytes", + "type": "Uncategorized", + "tags": [], + "label": "diskIOReadBytes", + "description": [], + "signature": [ + "null" + ], + "path": "x-pack/plugins/metrics_data_access/common/inventory_models/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "metricsDataAccess", + "id": "def-common.SnapshotMetricTypeKeys.diskIOWriteBytes", + "type": "Uncategorized", + "tags": [], + "label": "diskIOWriteBytes", + "description": [], + "signature": [ + "null" + ], + "path": "x-pack/plugins/metrics_data_access/common/inventory_models/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "metricsDataAccess", + "id": "def-common.SnapshotMetricTypeKeys.s3TotalRequests", + "type": "Uncategorized", + "tags": [], + "label": "s3TotalRequests", + "description": [], + "signature": [ + "null" + ], + "path": "x-pack/plugins/metrics_data_access/common/inventory_models/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "metricsDataAccess", + "id": "def-common.SnapshotMetricTypeKeys.s3NumberOfObjects", + "type": "Uncategorized", + "tags": [], + "label": "s3NumberOfObjects", + "description": [], + "signature": [ + "null" + ], + "path": "x-pack/plugins/metrics_data_access/common/inventory_models/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "metricsDataAccess", + "id": "def-common.SnapshotMetricTypeKeys.s3BucketSize", + "type": "Uncategorized", + "tags": [], + "label": "s3BucketSize", + "description": [], + "signature": [ + "null" + ], + "path": "x-pack/plugins/metrics_data_access/common/inventory_models/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "metricsDataAccess", + "id": "def-common.SnapshotMetricTypeKeys.s3DownloadBytes", + "type": "Uncategorized", + "tags": [], + "label": "s3DownloadBytes", + "description": [], + "signature": [ + "null" + ], + "path": "x-pack/plugins/metrics_data_access/common/inventory_models/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "metricsDataAccess", + "id": "def-common.SnapshotMetricTypeKeys.s3UploadBytes", + "type": "Uncategorized", + "tags": [], + "label": "s3UploadBytes", + "description": [], + "signature": [ + "null" + ], + "path": "x-pack/plugins/metrics_data_access/common/inventory_models/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "metricsDataAccess", + "id": "def-common.SnapshotMetricTypeKeys.rdsConnections", + "type": "Uncategorized", + "tags": [], + "label": "rdsConnections", + "description": [], + "signature": [ + "null" + ], + "path": "x-pack/plugins/metrics_data_access/common/inventory_models/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "metricsDataAccess", + "id": "def-common.SnapshotMetricTypeKeys.rdsQueriesExecuted", + "type": "Uncategorized", + "tags": [], + "label": "rdsQueriesExecuted", + "description": [], + "signature": [ + "null" + ], + "path": "x-pack/plugins/metrics_data_access/common/inventory_models/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "metricsDataAccess", + "id": "def-common.SnapshotMetricTypeKeys.rdsActiveTransactions", + "type": "Uncategorized", + "tags": [], + "label": "rdsActiveTransactions", + "description": [], + "signature": [ + "null" + ], + "path": "x-pack/plugins/metrics_data_access/common/inventory_models/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "metricsDataAccess", + "id": "def-common.SnapshotMetricTypeKeys.rdsLatency", + "type": "Uncategorized", + "tags": [], + "label": "rdsLatency", + "description": [], + "signature": [ + "null" + ], + "path": "x-pack/plugins/metrics_data_access/common/inventory_models/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "metricsDataAccess", + "id": "def-common.SnapshotMetricTypeKeys.sqsMessagesVisible", + "type": "Uncategorized", + "tags": [], + "label": "sqsMessagesVisible", + "description": [], + "signature": [ + "null" + ], + "path": "x-pack/plugins/metrics_data_access/common/inventory_models/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "metricsDataAccess", + "id": "def-common.SnapshotMetricTypeKeys.sqsMessagesDelayed", + "type": "Uncategorized", + "tags": [], + "label": "sqsMessagesDelayed", + "description": [], + "signature": [ + "null" + ], + "path": "x-pack/plugins/metrics_data_access/common/inventory_models/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "metricsDataAccess", + "id": "def-common.SnapshotMetricTypeKeys.sqsMessagesSent", + "type": "Uncategorized", + "tags": [], + "label": "sqsMessagesSent", + "description": [], + "signature": [ + "null" + ], + "path": "x-pack/plugins/metrics_data_access/common/inventory_models/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "metricsDataAccess", + "id": "def-common.SnapshotMetricTypeKeys.sqsMessagesEmpty", + "type": "Uncategorized", + "tags": [], + "label": "sqsMessagesEmpty", + "description": [], + "signature": [ + "null" + ], + "path": "x-pack/plugins/metrics_data_access/common/inventory_models/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "metricsDataAccess", + "id": "def-common.SnapshotMetricTypeKeys.sqsOldestMessage", + "type": "Uncategorized", + "tags": [], + "label": "sqsOldestMessage", + "description": [], + "signature": [ + "null" + ], + "path": "x-pack/plugins/metrics_data_access/common/inventory_models/types.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "metricsDataAccess", + "id": "def-common.SnapshotMetricTypeKeys.custom", + "type": "Uncategorized", + "tags": [], + "label": "custom", + "description": [], + "signature": [ + "null" + ], + "path": "x-pack/plugins/metrics_data_access/common/inventory_models/types.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "metricsDataAccess", + "id": "def-common.SnapshotMetricTypeRT", + "type": "Object", + "tags": [], + "label": "SnapshotMetricTypeRT", + "description": [], + "signature": [ + "KeyofC", + "<{ count: null; cpu: null; diskLatency: null; diskSpaceUsage: null; load: null; memory: null; memoryFree: null; memoryTotal: null; normalizedLoad1m: null; tx: null; rx: null; logRate: null; diskIOReadBytes: null; diskIOWriteBytes: null; s3TotalRequests: null; s3NumberOfObjects: null; s3BucketSize: null; s3DownloadBytes: null; s3UploadBytes: null; rdsConnections: null; rdsQueriesExecuted: null; rdsActiveTransactions: null; rdsLatency: null; sqsMessagesVisible: null; sqsMessagesDelayed: null; sqsMessagesSent: null; sqsMessagesEmpty: null; sqsOldestMessage: null; custom: null; }>" + ], + "path": "x-pack/plugins/metrics_data_access/common/inventory_models/types.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + } + ] } } \ No newline at end of file diff --git a/api_docs/metrics_data_access.mdx b/api_docs/metrics_data_access.mdx index fc6be46437f38..5d2180b1b4d1f 100644 --- a/api_docs/metrics_data_access.mdx +++ b/api_docs/metrics_data_access.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/metricsDataAccess title: "metricsDataAccess" image: https://source.unsplash.com/400x175/?github description: API docs for the metricsDataAccess plugin -date: 2023-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'metricsDataAccess'] --- import metricsDataAccessObj from './metrics_data_access.devdocs.json'; @@ -21,7 +21,15 @@ Contact [@elastic/infra-monitoring-ui](https://github.com/orgs/elastic/teams/inf | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 16 | 0 | 16 | 0 | +| 104 | 8 | 104 | 4 | + +## Client + +### Setup + + +### Start + ## Server @@ -40,3 +48,14 @@ Contact [@elastic/infra-monitoring-ui](https://github.com/orgs/elastic/teams/inf ### Consts, variables and types +## Common + +### Objects + + +### Functions + + +### Consts, variables and types + + diff --git a/api_docs/ml.mdx b/api_docs/ml.mdx index 3819f8d0fcf03..4497de8f77cce 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-10-31 +date: 2023-11-03 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 24496f023ae09..a04f47ca8c33f 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'monitoring'] --- import monitoringObj from './monitoring.devdocs.json'; diff --git a/api_docs/monitoring_collection.mdx b/api_docs/monitoring_collection.mdx index 09c2892ffdbff..f4957ff97aa31 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-10-31 +date: 2023-11-03 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 5226407022aae..bf1738fa0b81f 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-10-31 +date: 2023-11-03 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 40b6a289e7464..763d3347e94dd 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'newsfeed'] --- import newsfeedObj from './newsfeed.devdocs.json'; diff --git a/api_docs/no_data_page.mdx b/api_docs/no_data_page.mdx index 3fd858a335a21..3d66312f46ace 100644 --- a/api_docs/no_data_page.mdx +++ b/api_docs/no_data_page.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/noDataPage title: "noDataPage" image: https://source.unsplash.com/400x175/?github description: API docs for the noDataPage plugin -date: 2023-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'noDataPage'] --- import noDataPageObj from './no_data_page.devdocs.json'; diff --git a/api_docs/notifications.mdx b/api_docs/notifications.mdx index 786f7706c04a3..a4d6caa2f98c9 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-10-31 +date: 2023-11-03 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 8b1c1ba453e55..30c588ba4b056 100644 --- a/api_docs/observability.devdocs.json +++ b/api_docs/observability.devdocs.json @@ -8057,7 +8057,7 @@ "label": "config", "description": [], "signature": [ - "{ 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 customThresholdRule: Readonly<{} & { groupByPageSize: number; }>; }" + "{ readonly enabled: boolean; readonly unsafe: Readonly<{} & { alertDetails: Readonly<{} & { uptime: Readonly<{} & { enabled: boolean; }>; observability: Readonly<{} & { enabled: boolean; }>; metrics: Readonly<{} & { enabled: boolean; }>; logs: Readonly<{} & { enabled: boolean; }>; }>; thresholdRule: Readonly<{} & { enabled: boolean; }>; }>; readonly annotations: Readonly<{} & { index: string; enabled: boolean; }>; readonly customThresholdRule: Readonly<{} & { groupByPageSize: number; }>; readonly createO11yGenericFeatureId: boolean; }" ], "path": "x-pack/plugins/observability/server/routes/types.ts", "deprecated": false, @@ -9739,7 +9739,7 @@ "label": "ObservabilityConfig", "description": [], "signature": [ - "{ 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 customThresholdRule: Readonly<{} & { groupByPageSize: number; }>; }" + "{ readonly enabled: boolean; readonly unsafe: Readonly<{} & { alertDetails: Readonly<{} & { uptime: Readonly<{} & { enabled: boolean; }>; observability: Readonly<{} & { enabled: boolean; }>; metrics: Readonly<{} & { enabled: boolean; }>; logs: Readonly<{} & { enabled: boolean; }>; }>; thresholdRule: Readonly<{} & { enabled: boolean; }>; }>; readonly annotations: Readonly<{} & { index: string; enabled: boolean; }>; readonly customThresholdRule: Readonly<{} & { groupByPageSize: number; }>; readonly createO11yGenericFeatureId: boolean; }" ], "path": "x-pack/plugins/observability/server/index.ts", "deprecated": false, @@ -13964,7 +13964,7 @@ "label": "ObservabilityPluginSetup", "description": [], "signature": [ - "{ getAlertDetailsConfig(): Readonly<{} & { uptime: Readonly<{} & { enabled: boolean; }>; metrics: Readonly<{} & { enabled: boolean; }>; observability: Readonly<{} & { enabled: boolean; }>; logs: Readonly<{} & { enabled: boolean; }>; }>; getScopedAnnotationsClient: (requestContext: ", + "{ getAlertDetailsConfig(): Readonly<{} & { uptime: Readonly<{} & { enabled: boolean; }>; observability: Readonly<{} & { enabled: boolean; }>; metrics: Readonly<{} & { enabled: boolean; }>; logs: Readonly<{} & { enabled: boolean; }>; }>; getScopedAnnotationsClient: (requestContext: ", { "pluginId": "@kbn/core-http-request-handler-context-server", "scope": "common", diff --git a/api_docs/observability.mdx b/api_docs/observability.mdx index eaf79bae84526..71ce6c14f14ba 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'observability'] --- import observabilityObj from './observability.devdocs.json'; diff --git a/api_docs/observability_a_i_assistant.mdx b/api_docs/observability_a_i_assistant.mdx index 0da38bb1611b6..7411fe216eb3c 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'observabilityAIAssistant'] --- import observabilityAIAssistantObj from './observability_a_i_assistant.devdocs.json'; diff --git a/api_docs/observability_log_explorer.mdx b/api_docs/observability_log_explorer.mdx index f01b2061162a0..7f77aef3f7780 100644 --- a/api_docs/observability_log_explorer.mdx +++ b/api_docs/observability_log_explorer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/observabilityLogExplorer title: "observabilityLogExplorer" image: https://source.unsplash.com/400x175/?github description: API docs for the observabilityLogExplorer plugin -date: 2023-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'observabilityLogExplorer'] --- import observabilityLogExplorerObj from './observability_log_explorer.devdocs.json'; diff --git a/api_docs/observability_onboarding.mdx b/api_docs/observability_onboarding.mdx index de4d8c3e10a9d..5afddb466c60e 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'observabilityOnboarding'] --- import observabilityOnboardingObj from './observability_onboarding.devdocs.json'; diff --git a/api_docs/observability_shared.mdx b/api_docs/observability_shared.mdx index e9d7759be7bec..559fdda7cb7b3 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-10-31 +date: 2023-11-03 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 479a9309eb111..c4942af11a1ba 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'osquery'] --- import osqueryObj from './osquery.devdocs.json'; diff --git a/api_docs/painless_lab.mdx b/api_docs/painless_lab.mdx index 853eb017e7b4f..2f497ce1707fb 100644 --- a/api_docs/painless_lab.mdx +++ b/api_docs/painless_lab.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/painlessLab title: "painlessLab" image: https://source.unsplash.com/400x175/?github description: API docs for the painlessLab plugin -date: 2023-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'painlessLab'] --- import painlessLabObj from './painless_lab.devdocs.json'; diff --git a/api_docs/plugin_directory.mdx b/api_docs/plugin_directory.mdx index e4490be929281..a2efb89944313 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- @@ -21,7 +21,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | API Count | Any Count | Missing comments | Missing exports | |--------------|----------|-----------------|--------| -| 75925 | 223 | 64928 | 1593 | +| 76053 | 231 | 65052 | 1597 | ## Plugin Directory @@ -89,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. | 176 | 0 | 166 | 13 | -| | [@elastic/kibana-visualizations](https://github.com/orgs/elastic/teams/kibana-visualizations) | Adds expression runtime to Kibana | 2208 | 17 | 1749 | 5 | +| | [@elastic/kibana-visualizations](https://github.com/orgs/elastic/teams/kibana-visualizations) | Adds expression runtime to Kibana | 2224 | 17 | 1765 | 5 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 235 | 0 | 99 | 2 | | | [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | Index pattern fields and ambiguous values formatters | 292 | 5 | 253 | 3 | | | [@elastic/kibana-gis](https://github.com/orgs/elastic/teams/kibana-gis) | The file upload plugin contains components and services for uploading a file, analyzing its data, and then importing the data into an Elasticsearch index. Supported file types include CSV, TSV, newline-delimited JSON and GeoJSON. | 59 | 0 | 59 | 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 | 0 | 2 | 0 | -| | [@elastic/fleet](https://github.com/orgs/elastic/teams/fleet) | - | 1209 | 3 | 1091 | 44 | +| | [@elastic/fleet](https://github.com/orgs/elastic/teams/fleet) | - | 1209 | 3 | 1091 | 45 | | 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 | @@ -106,8 +106,8 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 149 | 0 | 109 | 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) | - | 199 | 0 | 194 | 3 | -| | [@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 | 42 | 0 | 39 | 11 | +| | [@elastic/platform-deployment-management](https://github.com/orgs/elastic/teams/platform-deployment-management) | - | 204 | 0 | 199 | 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 | 35 | 0 | 32 | 9 | | 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 | @@ -124,12 +124,12 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/kibana-presentation](https://github.com/orgs/elastic/teams/kibana-presentation) | A dashboard panel for creating links to dashboards or external links. | 64 | 0 | 62 | 7 | | | [@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. | 22 | 0 | 22 | 7 | -| | [@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 | +| | [@elastic/infra-monitoring-ui](https://github.com/orgs/elastic/teams/infra-monitoring-ui) | Exposes the shared components and APIs to access and visualize logs. | 279 | 10 | 264 | 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) | - | 45 | 0 | 45 | 7 | | | [@elastic/kibana-gis](https://github.com/orgs/elastic/teams/kibana-gis) | - | 259 | 0 | 258 | 28 | | | [@elastic/kibana-gis](https://github.com/orgs/elastic/teams/kibana-gis) | - | 68 | 0 | 68 | 0 | -| | [@elastic/infra-monitoring-ui](https://github.com/orgs/elastic/teams/infra-monitoring-ui) | Exposes utilities for accessing metrics data | 16 | 0 | 16 | 0 | +| | [@elastic/infra-monitoring-ui](https://github.com/orgs/elastic/teams/infra-monitoring-ui) | Exposes utilities for accessing metrics data | 104 | 8 | 104 | 4 | | | [@elastic/ml-ui](https://github.com/orgs/elastic/teams/ml-ui) | This plugin provides access to the machine learning features provided by Elastic. | 150 | 3 | 64 | 33 | | | [@elastic/infra-monitoring-ui](https://github.com/orgs/elastic/teams/infra-monitoring-ui) | - | 15 | 3 | 13 | 1 | | | [@elastic/infra-monitoring-ui](https://github.com/orgs/elastic/teams/infra-monitoring-ui) | - | 9 | 0 | 9 | 0 | @@ -300,7 +300,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@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) | - | 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) | - | 42 | 0 | 37 | 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 | @@ -487,7 +487,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/platform-deployment-management](https://github.com/orgs/elastic/teams/platform-deployment-management) | - | 23 | 0 | 7 | 0 | | | [@elastic/platform-deployment-management](https://github.com/orgs/elastic/teams/platform-deployment-management) | - | 8 | 0 | 2 | 3 | | | [@elastic/platform-deployment-management](https://github.com/orgs/elastic/teams/platform-deployment-management) | - | 45 | 0 | 0 | 0 | -| | [@elastic/appex-sharedux @elastic/platform-deployment-management](https://github.com/orgs/elastic/teams/appex-sharedux ) | - | 129 | 0 | 129 | 0 | +| | [@elastic/appex-sharedux @elastic/platform-deployment-management](https://github.com/orgs/elastic/teams/appex-sharedux ) | - | 131 | 0 | 130 | 0 | | | [@elastic/appex-sharedux @elastic/platform-deployment-management](https://github.com/orgs/elastic/teams/appex-sharedux ) | - | 20 | 0 | 11 | 0 | | | [@elastic/platform-deployment-management](https://github.com/orgs/elastic/teams/platform-deployment-management) | - | 81 | 0 | 3 | 0 | | | [@elastic/platform-deployment-management](https://github.com/orgs/elastic/teams/platform-deployment-management) | - | 54 | 0 | 6 | 0 | @@ -528,7 +528,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/kibana-performance-testing](https://github.com/orgs/elastic/teams/kibana-performance-testing) | - | 3 | 0 | 3 | 1 | | | [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kibana-operations) | - | 1 | 0 | 1 | 0 | | | [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kibana-operations) | - | 1 | 0 | 1 | 0 | -| | [@elastic/profiling-ui](https://github.com/orgs/elastic/teams/profiling-ui) | - | 165 | 0 | 22 | 0 | +| | [@elastic/profiling-ui](https://github.com/orgs/elastic/teams/profiling-ui) | - | 171 | 0 | 28 | 0 | | | [@elastic/kibana-visualizations](https://github.com/orgs/elastic/teams/kibana-visualizations) | - | 13 | 0 | 7 | 0 | | | [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | - | 22 | 0 | 9 | 0 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 8 | 0 | 2 | 0 | @@ -545,7 +545,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | A component for creating resizable layouts containing a fixed width panel and a flexible panel, with support for horizontal and vertical layouts. | 18 | 0 | 5 | 0 | | | [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kibana-operations) | - | 13 | 2 | 8 | 0 | | | [@elastic/response-ops](https://github.com/orgs/elastic/teams/response-ops) | - | 16 | 0 | 16 | 1 | -| | [@elastic/security-detections-response](https://github.com/orgs/elastic/teams/security-detections-response) | - | 114 | 0 | 111 | 0 | +| | [@elastic/security-detections-response](https://github.com/orgs/elastic/teams/security-detections-response) | - | 115 | 0 | 112 | 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) | - | 68 | 0 | 68 | 0 | | | [@elastic/enterprise-search-frontend](https://github.com/orgs/elastic/teams/enterprise-search-frontend) | - | 2211 | 0 | 2211 | 0 | @@ -587,7 +587,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 28 | 0 | 10 | 0 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 10 | 0 | 4 | 0 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 32 | 0 | 28 | 0 | -| | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 58 | 0 | 47 | 4 | +| | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 60 | 0 | 49 | 4 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 6 | 0 | 2 | 0 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 5 | 0 | 4 | 0 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 3 | 0 | 2 | 0 | @@ -627,7 +627,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kibana-operations) | - | 41 | 2 | 21 | 0 | | | [@elastic/security-threat-hunting-investigations](https://github.com/orgs/elastic/teams/security-threat-hunting-investigations) | - | 24 | 0 | 16 | 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) | - | 290 | 4 | 243 | 12 | +| | [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kibana-operations) | - | 291 | 4 | 244 | 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) | - | 22 | 0 | 21 | 0 | diff --git a/api_docs/presentation_util.mdx b/api_docs/presentation_util.mdx index c4d4ad88b08fd..2f36fd329e942 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'presentationUtil'] --- import presentationUtilObj from './presentation_util.devdocs.json'; diff --git a/api_docs/profiling.mdx b/api_docs/profiling.mdx index e04af3c2c41e3..e4374779b9b42 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'profiling'] --- import profilingObj from './profiling.devdocs.json'; diff --git a/api_docs/profiling_data_access.mdx b/api_docs/profiling_data_access.mdx index b2c238f1a1339..ae77a09bab8e0 100644 --- a/api_docs/profiling_data_access.mdx +++ b/api_docs/profiling_data_access.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/profilingDataAccess title: "profilingDataAccess" image: https://source.unsplash.com/400x175/?github description: API docs for the profilingDataAccess plugin -date: 2023-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'profilingDataAccess'] --- import profilingDataAccessObj from './profiling_data_access.devdocs.json'; diff --git a/api_docs/remote_clusters.mdx b/api_docs/remote_clusters.mdx index 16d03238c8062..3db0c9c0a72a5 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-10-31 +date: 2023-11-03 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 06bf1bb0633fa..c65506ac8fb26 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-10-31 +date: 2023-11-03 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 23eedf77b98b5..e180a02c605d1 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-10-31 +date: 2023-11-03 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 7b7a9ba12da62..906b1e98dd57f 100644 --- a/api_docs/rule_registry.devdocs.json +++ b/api_docs/rule_registry.devdocs.json @@ -2285,7 +2285,7 @@ "\nID of the Kibana feature associated with the index.\nUsed by alerts-as-data RBAC.\n\nNote from @dhurley14\nThe purpose of the `feature` param is to force the user to update\nthe data structure which contains the mapping of consumers to alerts\nas data indices. The idea is it is typed such that it forces the\nuser to go to the code and modify it. At least until a better system\nis put in place or we move the alerts as data client out of rule registry.\n" ], "signature": [ - "\"uptime\" | \"siem\" | \"apm\" | \"observability\" | \"logs\" | \"infrastructure\" | \"slo\"" + "\"uptime\" | \"siem\" | \"observability\" | \"apm\" | \"logs\" | \"infrastructure\" | \"slo\"" ], "path": "x-pack/plugins/rule_registry/server/rule_data_plugin_service/index_options.ts", "deprecated": false, diff --git a/api_docs/rule_registry.mdx b/api_docs/rule_registry.mdx index 96e9ce195c0af..15ad84b4dc690 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'ruleRegistry'] --- import ruleRegistryObj from './rule_registry.devdocs.json'; diff --git a/api_docs/runtime_fields.mdx b/api_docs/runtime_fields.mdx index 21f88b316cf0a..acfd01a802220 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-10-31 +date: 2023-11-03 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 f570fdb42e073..5f5a24c19e31c 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-10-31 +date: 2023-11-03 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 2af670acfae21..3a55d0ecef57f 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-10-31 +date: 2023-11-03 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 34f86a8678dcb..a63bb4702367d 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-10-31 +date: 2023-11-03 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 91b050724c97f..c2b084dcccac3 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-10-31 +date: 2023-11-03 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 82c62bb5dc32b..755c294b9f74f 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjectsTaggingOss'] --- import savedObjectsTaggingOssObj from './saved_objects_tagging_oss.devdocs.json'; diff --git a/api_docs/saved_search.devdocs.json b/api_docs/saved_search.devdocs.json index 3945e98295ff1..1268c90a7f331 100644 --- a/api_docs/saved_search.devdocs.json +++ b/api_docs/saved_search.devdocs.json @@ -107,7 +107,7 @@ "label": "sharingSavedObjectProps", "description": [], "signature": [ - "{ outcome?: \"conflict\" | \"exactMatch\" | \"aliasMatch\" | undefined; aliasTargetId?: string | undefined; aliasPurpose?: \"savedObjectConversion\" | \"savedObjectImport\" | undefined; errorJSON?: string | undefined; } | undefined" + "{ outcome?: \"exactMatch\" | \"aliasMatch\" | \"conflict\" | undefined; aliasTargetId?: string | undefined; aliasPurpose?: \"savedObjectConversion\" | \"savedObjectImport\" | undefined; errorJSON?: string | undefined; } | undefined" ], "path": "src/plugins/saved_search/public/services/saved_searches/types.ts", "deprecated": false, @@ -135,7 +135,7 @@ "label": "sharingSavedObjectProps", "description": [], "signature": [ - "{ outcome?: \"conflict\" | \"exactMatch\" | \"aliasMatch\" | undefined; aliasTargetId?: string | undefined; aliasPurpose?: \"savedObjectConversion\" | \"savedObjectImport\" | undefined; errorJSON?: string | undefined; } | undefined" + "{ outcome?: \"exactMatch\" | \"aliasMatch\" | \"conflict\" | undefined; aliasTargetId?: string | undefined; aliasPurpose?: \"savedObjectConversion\" | \"savedObjectImport\" | undefined; errorJSON?: string | undefined; } | undefined" ], "path": "src/plugins/saved_search/public/services/saved_searches/saved_search_attribute_service.ts", "deprecated": false, @@ -1563,7 +1563,7 @@ "label": "sharingSavedObjectProps", "description": [], "signature": [ - "{ outcome?: \"conflict\" | \"exactMatch\" | \"aliasMatch\" | undefined; aliasTargetId?: string | undefined; aliasPurpose?: \"savedObjectConversion\" | \"savedObjectImport\" | undefined; errorJSON?: string | undefined; } | undefined" + "{ outcome?: \"exactMatch\" | \"aliasMatch\" | \"conflict\" | undefined; aliasTargetId?: string | undefined; aliasPurpose?: \"savedObjectConversion\" | \"savedObjectImport\" | undefined; errorJSON?: string | undefined; } | undefined" ], "path": "src/plugins/saved_search/common/types.ts", "deprecated": false, diff --git a/api_docs/saved_search.mdx b/api_docs/saved_search.mdx index 35b99d0d02f0e..94f3af8497671 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-10-31 +date: 2023-11-03 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 8122026773a55..5631f23715ebd 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-10-31 +date: 2023-11-03 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 e3e7efda2c1e7..71d9cd4312df4 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'screenshotting'] --- import screenshottingObj from './screenshotting.devdocs.json'; diff --git a/api_docs/security.mdx b/api_docs/security.mdx index d031c6c1f810c..501deba21308c 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'security'] --- import securityObj from './security.devdocs.json'; diff --git a/api_docs/security_solution.mdx b/api_docs/security_solution.mdx index 6f3e6efdebbd8..d7e5c12fa930f 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'securitySolution'] --- import securitySolutionObj from './security_solution.devdocs.json'; diff --git a/api_docs/security_solution_ess.mdx b/api_docs/security_solution_ess.mdx index e9d8c18167b0f..afcd20d5ca1e8 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-10-31 +date: 2023-11-03 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 751dcc3340bc4..e72a631a33b88 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-10-31 +date: 2023-11-03 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 171c06c6e4e6d..4f604570f8fc0 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-10-31 +date: 2023-11-03 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 b13cc4b75e14d..fa782c9fcb7a1 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-10-31 +date: 2023-11-03 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 fda8beaf59535..2b25ef51fc86e 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-10-31 +date: 2023-11-03 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 34892f1ae634b..0497bac753a51 100644 --- a/api_docs/session_view.mdx +++ b/api_docs/session_view.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/sessionView title: "sessionView" image: https://source.unsplash.com/400x175/?github description: API docs for the sessionView plugin -date: 2023-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'sessionView'] --- import sessionViewObj from './session_view.devdocs.json'; diff --git a/api_docs/share.mdx b/api_docs/share.mdx index f03e6266c6450..3b088d79486ed 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-10-31 +date: 2023-11-03 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 4d5e070785ad7..3ba751b3df2d5 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-10-31 +date: 2023-11-03 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 d0944fe9238fc..bd4fd0400d990 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-10-31 +date: 2023-11-03 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 a58b13b025214..81c9fb78e319d 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-10-31 +date: 2023-11-03 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 c6dbb85764fe3..abdfab356d7ae 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-10-31 +date: 2023-11-03 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 1f41fa3a71e5b..bad6413a0c285 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-10-31 +date: 2023-11-03 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 84caeb5d19797..b20bffbe0cb61 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-10-31 +date: 2023-11-03 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 d292c70d2f0d5..70e043490aded 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-10-31 +date: 2023-11-03 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 af762ec0c0836..c492b8c5cac9b 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-10-31 +date: 2023-11-03 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 079c022549e88..b0135772d3753 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'telemetryManagementSection'] --- import telemetryManagementSectionObj from './telemetry_management_section.devdocs.json'; diff --git a/api_docs/text_based_languages.mdx b/api_docs/text_based_languages.mdx index bb4ade15b21f0..3c76df46a9644 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'textBasedLanguages'] --- import textBasedLanguagesObj from './text_based_languages.devdocs.json'; diff --git a/api_docs/threat_intelligence.mdx b/api_docs/threat_intelligence.mdx index 33730cd1343a0..6216b52fde524 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'threatIntelligence'] --- import threatIntelligenceObj from './threat_intelligence.devdocs.json'; diff --git a/api_docs/timelines.mdx b/api_docs/timelines.mdx index 10a42cbdbb696..05143836f4b2c 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-10-31 +date: 2023-11-03 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 48184d47dc1c3..e15665bac1bcd 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-10-31 +date: 2023-11-03 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 b81c36d0dbc45..048b5b518b383 100644 --- a/api_docs/triggers_actions_ui.devdocs.json +++ b/api_docs/triggers_actions_ui.devdocs.json @@ -6332,7 +6332,7 @@ "label": "RuleCreationValidConsumer", "description": [], "signature": [ - "\"logs\" | \"infrastructure\" | \"stackAlerts\"" + "\"observability\" | \"stackAlerts\" | \"logs\" | \"infrastructure\"" ], "path": "x-pack/plugins/triggers_actions_ui/public/types.ts", "deprecated": false, diff --git a/api_docs/triggers_actions_ui.mdx b/api_docs/triggers_actions_ui.mdx index d01003f52b7f1..3d08502743f32 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'triggersActionsUi'] --- import triggersActionsUiObj from './triggers_actions_ui.devdocs.json'; diff --git a/api_docs/ui_actions.mdx b/api_docs/ui_actions.mdx index 9367f393e25dc..7f1b04d32ee5b 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'uiActions'] --- import uiActionsObj from './ui_actions.devdocs.json'; diff --git a/api_docs/ui_actions_enhanced.mdx b/api_docs/ui_actions_enhanced.mdx index 8a219ee91fd9e..b1a2cfaaebe91 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'uiActionsEnhanced'] --- import uiActionsEnhancedObj from './ui_actions_enhanced.devdocs.json'; diff --git a/api_docs/unified_doc_viewer.mdx b/api_docs/unified_doc_viewer.mdx index cc01b96b57e8d..54e587a9a78be 100644 --- a/api_docs/unified_doc_viewer.mdx +++ b/api_docs/unified_doc_viewer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/unifiedDocViewer title: "unifiedDocViewer" image: https://source.unsplash.com/400x175/?github description: API docs for the unifiedDocViewer plugin -date: 2023-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'unifiedDocViewer'] --- import unifiedDocViewerObj from './unified_doc_viewer.devdocs.json'; diff --git a/api_docs/unified_histogram.mdx b/api_docs/unified_histogram.mdx index 06ccb390005d0..617f5c11258c5 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'unifiedHistogram'] --- import unifiedHistogramObj from './unified_histogram.devdocs.json'; diff --git a/api_docs/unified_search.mdx b/api_docs/unified_search.mdx index 9cf0af8439b3e..b66f9b946f406 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'unifiedSearch'] --- import unifiedSearchObj from './unified_search.devdocs.json'; diff --git a/api_docs/unified_search_autocomplete.mdx b/api_docs/unified_search_autocomplete.mdx index 0d170ed68c8a0..be7cbd28491e1 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'unifiedSearch.autocomplete'] --- import unifiedSearchAutocompleteObj from './unified_search_autocomplete.devdocs.json'; diff --git a/api_docs/uptime.mdx b/api_docs/uptime.mdx index a2c90af10261d..f1ea18f48b6cf 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-10-31 +date: 2023-11-03 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 f4bc5998fc1c1..c3c626a8d8ed3 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'urlForwarding'] --- import urlForwardingObj from './url_forwarding.devdocs.json'; diff --git a/api_docs/usage_collection.mdx b/api_docs/usage_collection.mdx index d5766874175be..a1fc0304b6e82 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-10-31 +date: 2023-11-03 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 2b3ca541f6732..5385f5f2047f1 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-10-31 +date: 2023-11-03 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 a9d45064271fe..b48e29dcea601 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-10-31 +date: 2023-11-03 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 234f3a6eac549..e9c380f9080b5 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-10-31 +date: 2023-11-03 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 16224c9b7bb7b..5f8cb614de766 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-10-31 +date: 2023-11-03 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 56d88ea29ff2b..04a215a7b6597 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-10-31 +date: 2023-11-03 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 770cc58460728..96010ae388cce 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-10-31 +date: 2023-11-03 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 62c78702bf7e1..fe6ec62eed74d 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-10-31 +date: 2023-11-03 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 a3581e38f98b2..bc5ddc4206a69 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-10-31 +date: 2023-11-03 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 60422bc974672..00ff4a1914bbf 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-10-31 +date: 2023-11-03 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 b3ecdd2b8a6c2..30a4351b33406 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeVislib'] --- import visTypeVislibObj from './vis_type_vislib.devdocs.json'; diff --git a/api_docs/vis_type_xy.mdx b/api_docs/vis_type_xy.mdx index 7ffc22dd7713e..f6c5b3f03da44 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-10-31 +date: 2023-11-03 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 12ab849abf499..b9e6229c9486b 100644 --- a/api_docs/visualizations.devdocs.json +++ b/api_docs/visualizations.devdocs.json @@ -3075,7 +3075,7 @@ "label": "sharingSavedObjectProps", "description": [], "signature": [ - "{ outcome?: \"conflict\" | \"exactMatch\" | \"aliasMatch\" | undefined; aliasTargetId?: string | undefined; aliasPurpose?: \"savedObjectConversion\" | \"savedObjectImport\" | undefined; errorJSON?: string | undefined; } | undefined" + "{ outcome?: \"exactMatch\" | \"aliasMatch\" | \"conflict\" | undefined; aliasTargetId?: string | undefined; aliasPurpose?: \"savedObjectConversion\" | \"savedObjectImport\" | undefined; errorJSON?: string | undefined; } | undefined" ], "path": "src/plugins/visualizations/public/types.ts", "deprecated": false, @@ -5583,7 +5583,7 @@ "section": "def-common.SOWithMetadata", "text": "SOWithMetadata" }, - "; meta: { outcome: \"conflict\" | \"exactMatch\" | \"aliasMatch\"; aliasTargetId?: string | undefined; aliasPurpose?: \"savedObjectConversion\" | \"savedObjectImport\" | undefined; }; }>" + "; meta: { outcome: \"exactMatch\" | \"aliasMatch\" | \"conflict\"; aliasTargetId?: string | undefined; aliasPurpose?: \"savedObjectConversion\" | \"savedObjectImport\" | undefined; }; }>" ], "path": "src/plugins/visualizations/public/vis_types/vis_type_alias_registry.ts", "deprecated": false, diff --git a/api_docs/visualizations.mdx b/api_docs/visualizations.mdx index 90af67056d983..1f41c5a3aa064 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-10-31 +date: 2023-11-03 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visualizations'] --- import visualizationsObj from './visualizations.devdocs.json'; diff --git a/bundle/bundled.json b/bundle/bundled.json deleted file mode 100644 index 21c305d6f4216..0000000000000 --- a/bundle/bundled.json +++ /dev/null @@ -1,326 +0,0 @@ -{ - "openapi": "3.1.0", - "info": { - "title": "Saved objects", - "description": "OpenAPI schema for saved object endpoints", - "version": "0.1", - "contact": { - "name": "Kibana Core Team" - }, - "license": { - "name": "Elastic License 2.0", - "url": "https://www.elastic.co/licensing/elastic-license" - } - }, - "servers": [ - { - "url": "http://localhost:5601", - "description": "local" - } - ], - "security": [ - { - "basicAuth": [] - }, - { - "apiKeyAuth": [] - } - ], - "tags": [ - { - "name": "saved objects", - "description": "Manage Kibana saved objects, including dashboards, visualizations, and more." - } - ], - "paths": { - "/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", - "tags": [ - "saved objects" - ], - "parameters": [ - { - "$ref": "#/components/parameters/kbn_xsrf" - } - ], - "requestBody": { - "required": true, - "content": { - "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.", - "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.", - "oneOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ] - } - } - }, - "examples": { - "exportSavedObjectsRequest": { - "$ref": "#/components/examples/export_objects_request" - } - } - } - } - }, - "responses": { - "200": { - "description": "Indicates a successful call.", - "content": { - "multipart/form-data": { - "schema": { - "type": "string" - }, - "examples": { - "exportSavedObjectsResponse": { - "$ref": "#/components/examples/export_objects_response" - } - } - } - } - }, - "400": { - "description": "Bad request.", - "content": { - "application/json": { - "schema": { - "type": "object", - "additionalProperties": true - } - } - } - } - }, - "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", - "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. 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" - }, - { - "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" - } - ], - "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.\n" - } - } - } - }, - "responses": { - "200": { - "description": "Indicates a successful call.", - "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" - } - } - } - } - }, - "400": { - "description": "Bad request.", - "content": { - "application/json": { - "schema": { - "type": "object", - "additionalProperties": true - } - } - } - } - }, - "servers": [ - { - "url": "https://localhost:5601" - } - ] - }, - "servers": [ - { - "url": "https://localhost:5601" - } - ] - } - }, - "components": { - "securitySchemes": { - "basicAuth": { - "type": "http", - "scheme": "basic" - }, - "apiKeyAuth": { - "type": "apiKey", - "in": "header", - "name": "ApiKey" - } - }, - "parameters": { - "kbn_xsrf": { - "schema": { - "type": "string" - }, - "in": "header", - "name": "kbn-xsrf", - "description": "Cross-site request forgery protection", - "required": true - } - }, - "examples": { - "export_objects_request": { - "summary": "Export a specific saved object.", - "value": { - "objects": [ - { - "type": "index-pattern", - "id": "90943e30-9a47-11e8-b64d-95841ca0b247" - } - ], - "includeReferencesDeep": false - } - }, - "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" - }, - "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", - "meta": { - "title": "Kibana Sample Data Logs", - "icon": "indexPatternApp" - }, - "managed": false, - "destinationId": "82d2760c-468f-49cf-83aa-b9a35b6a8943" - } - ] - } - } - } - } -} \ No newline at end of file diff --git a/bundle/bundled.yaml b/bundle/bundled.yaml deleted file mode 100644 index 0facbd5446640..0000000000000 --- a/bundle/bundled.yaml +++ /dev/null @@ -1,209 +0,0 @@ -openapi: 3.1.0 -info: - title: Saved objects - description: OpenAPI schema for saved object endpoints - version: '0.1' - contact: - name: Kibana Core Team - license: - name: Elastic License 2.0 - url: https://www.elastic.co/licensing/elastic-license -servers: - - url: http://localhost:5601 - description: local -security: - - basicAuth: [] - - apiKeyAuth: [] -tags: - - name: saved objects - description: Manage Kibana saved objects, including dashboards, visualizations, and more. -paths: - /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. - tags: - - saved objects - parameters: - - $ref: '#/components/parameters/kbn_xsrf' - requestBody: - required: true - content: - 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. - 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. - oneOf: - - type: string - - type: array - items: - type: string - examples: - exportSavedObjectsRequest: - $ref: '#/components/examples/export_objects_request' - responses: - '200': - description: Indicates a successful call. - content: - multipart/form-data: - schema: - type: string - examples: - exportSavedObjectsResponse: - $ref: '#/components/examples/export_objects_response' - '400': - description: Bad request. - content: - application/json: - schema: - type: object - additionalProperties: true - 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. - 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. Use this option only if you encounter issues with imported saved objects. NOTE: This option cannot be used with the `createNewCopies` option. - - in: query - name: createNewCopies - schema: - type: boolean - required: false - description: | - Creates copies of saved objects, regenerates each object ID, and resets the origin. When used, potential conflict errors are avoided. NOTE: This option cannot be used with the `overwrite` and `compatibilityMode` options. - - in: query - name: overwrite - schema: - type: boolean - required: false - description: | - Overwrites saved objects when they already exist. When used, potential conflict errors are automatically resolved by overwriting the destination object. NOTE: This option cannot be used with the `createNewCopies` option. - 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. - responses: - '200': - description: Indicates a successful call. - 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. - success: - type: boolean - description: | - Indicates when the import was successfully completed. When set to false, some objects may not have been created. For additional information, refer to the `errors` and `successResults` properties. - successCount: - type: integer - description: Indicates the number of successfully imported records. - 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. - warnings: - type: array - examples: - importObjectsResponse: - $ref: '#/components/examples/import_objects_response' - '400': - description: Bad request. - content: - application/json: - schema: - type: object - additionalProperties: true - servers: - - url: https://localhost:5601 - servers: - - url: https://localhost:5601 -components: - securitySchemes: - basicAuth: - type: http - scheme: basic - apiKeyAuth: - type: apiKey - in: header - name: ApiKey - parameters: - kbn_xsrf: - schema: - type: string - in: header - name: kbn-xsrf - description: Cross-site request forgery protection - required: true - examples: - export_objects_request: - summary: Export a specific saved object. - value: - objects: - - type: index-pattern - id: 90943e30-9a47-11e8-b64d-95841ca0b247 - includeReferencesDeep: false - 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":[]} - 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 - meta: - title: Kibana Sample Data Logs - icon: indexPatternApp - managed: false - destinationId: 82d2760c-468f-49cf-83aa-b9a35b6a8943 diff --git a/bundle/entrypoint.json b/bundle/entrypoint.json deleted file mode 100644 index 21c305d6f4216..0000000000000 --- a/bundle/entrypoint.json +++ /dev/null @@ -1,326 +0,0 @@ -{ - "openapi": "3.1.0", - "info": { - "title": "Saved objects", - "description": "OpenAPI schema for saved object endpoints", - "version": "0.1", - "contact": { - "name": "Kibana Core Team" - }, - "license": { - "name": "Elastic License 2.0", - "url": "https://www.elastic.co/licensing/elastic-license" - } - }, - "servers": [ - { - "url": "http://localhost:5601", - "description": "local" - } - ], - "security": [ - { - "basicAuth": [] - }, - { - "apiKeyAuth": [] - } - ], - "tags": [ - { - "name": "saved objects", - "description": "Manage Kibana saved objects, including dashboards, visualizations, and more." - } - ], - "paths": { - "/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", - "tags": [ - "saved objects" - ], - "parameters": [ - { - "$ref": "#/components/parameters/kbn_xsrf" - } - ], - "requestBody": { - "required": true, - "content": { - "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.", - "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.", - "oneOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ] - } - } - }, - "examples": { - "exportSavedObjectsRequest": { - "$ref": "#/components/examples/export_objects_request" - } - } - } - } - }, - "responses": { - "200": { - "description": "Indicates a successful call.", - "content": { - "multipart/form-data": { - "schema": { - "type": "string" - }, - "examples": { - "exportSavedObjectsResponse": { - "$ref": "#/components/examples/export_objects_response" - } - } - } - } - }, - "400": { - "description": "Bad request.", - "content": { - "application/json": { - "schema": { - "type": "object", - "additionalProperties": true - } - } - } - } - }, - "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", - "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. 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" - }, - { - "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" - } - ], - "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.\n" - } - } - } - }, - "responses": { - "200": { - "description": "Indicates a successful call.", - "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" - } - } - } - } - }, - "400": { - "description": "Bad request.", - "content": { - "application/json": { - "schema": { - "type": "object", - "additionalProperties": true - } - } - } - } - }, - "servers": [ - { - "url": "https://localhost:5601" - } - ] - }, - "servers": [ - { - "url": "https://localhost:5601" - } - ] - } - }, - "components": { - "securitySchemes": { - "basicAuth": { - "type": "http", - "scheme": "basic" - }, - "apiKeyAuth": { - "type": "apiKey", - "in": "header", - "name": "ApiKey" - } - }, - "parameters": { - "kbn_xsrf": { - "schema": { - "type": "string" - }, - "in": "header", - "name": "kbn-xsrf", - "description": "Cross-site request forgery protection", - "required": true - } - }, - "examples": { - "export_objects_request": { - "summary": "Export a specific saved object.", - "value": { - "objects": [ - { - "type": "index-pattern", - "id": "90943e30-9a47-11e8-b64d-95841ca0b247" - } - ], - "includeReferencesDeep": false - } - }, - "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" - }, - "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", - "meta": { - "title": "Kibana Sample Data Logs", - "icon": "indexPatternApp" - }, - "managed": false, - "destinationId": "82d2760c-468f-49cf-83aa-b9a35b6a8943" - } - ] - } - } - } - } -} \ No newline at end of file diff --git a/bundle/entrypoint.yaml b/bundle/entrypoint.yaml deleted file mode 100644 index 0facbd5446640..0000000000000 --- a/bundle/entrypoint.yaml +++ /dev/null @@ -1,209 +0,0 @@ -openapi: 3.1.0 -info: - title: Saved objects - description: OpenAPI schema for saved object endpoints - version: '0.1' - contact: - name: Kibana Core Team - license: - name: Elastic License 2.0 - url: https://www.elastic.co/licensing/elastic-license -servers: - - url: http://localhost:5601 - description: local -security: - - basicAuth: [] - - apiKeyAuth: [] -tags: - - name: saved objects - description: Manage Kibana saved objects, including dashboards, visualizations, and more. -paths: - /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. - tags: - - saved objects - parameters: - - $ref: '#/components/parameters/kbn_xsrf' - requestBody: - required: true - content: - 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. - 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. - oneOf: - - type: string - - type: array - items: - type: string - examples: - exportSavedObjectsRequest: - $ref: '#/components/examples/export_objects_request' - responses: - '200': - description: Indicates a successful call. - content: - multipart/form-data: - schema: - type: string - examples: - exportSavedObjectsResponse: - $ref: '#/components/examples/export_objects_response' - '400': - description: Bad request. - content: - application/json: - schema: - type: object - additionalProperties: true - 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. - 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. Use this option only if you encounter issues with imported saved objects. NOTE: This option cannot be used with the `createNewCopies` option. - - in: query - name: createNewCopies - schema: - type: boolean - required: false - description: | - Creates copies of saved objects, regenerates each object ID, and resets the origin. When used, potential conflict errors are avoided. NOTE: This option cannot be used with the `overwrite` and `compatibilityMode` options. - - in: query - name: overwrite - schema: - type: boolean - required: false - description: | - Overwrites saved objects when they already exist. When used, potential conflict errors are automatically resolved by overwriting the destination object. NOTE: This option cannot be used with the `createNewCopies` option. - 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. - responses: - '200': - description: Indicates a successful call. - 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. - success: - type: boolean - description: | - Indicates when the import was successfully completed. When set to false, some objects may not have been created. For additional information, refer to the `errors` and `successResults` properties. - successCount: - type: integer - description: Indicates the number of successfully imported records. - 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. - warnings: - type: array - examples: - importObjectsResponse: - $ref: '#/components/examples/import_objects_response' - '400': - description: Bad request. - content: - application/json: - schema: - type: object - additionalProperties: true - servers: - - url: https://localhost:5601 - servers: - - url: https://localhost:5601 -components: - securitySchemes: - basicAuth: - type: http - scheme: basic - apiKeyAuth: - type: apiKey - in: header - name: ApiKey - parameters: - kbn_xsrf: - schema: - type: string - in: header - name: kbn-xsrf - description: Cross-site request forgery protection - required: true - examples: - export_objects_request: - summary: Export a specific saved object. - value: - objects: - - type: index-pattern - id: 90943e30-9a47-11e8-b64d-95841ca0b247 - includeReferencesDeep: false - 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":[]} - 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 - meta: - title: Kibana Sample Data Logs - icon: indexPatternApp - managed: false - destinationId: 82d2760c-468f-49cf-83aa-b9a35b6a8943 diff --git a/config/serverless.oblt.yml b/config/serverless.oblt.yml index d38e510edbea8..a2d58e930f4cf 100644 --- a/config/serverless.oblt.yml +++ b/config/serverless.oblt.yml @@ -25,6 +25,11 @@ xpack.serverless.plugin.developer.projectSwitcher.currentType: 'observability' ## Disable adding the component template `.fleet_agent_id_verification-1` to every index template for each datastream for each integration xpack.fleet.agentIdVerificationEnabled: false +## Enable the capability for the observability feature ID in the serverless environment to take ownership of the rules. +## The value need to be a featureId observability Or stackAlerts Or siem +xpack.alerting.rules.overwriteProducer: 'observability' +xpack.observability.createO11yGenericFeatureId: true + ## APM Serverless Onboarding flow xpack.apm.serverlessOnboarding: true diff --git a/dev_docs/contributing/best_practices.mdx b/dev_docs/contributing/best_practices.mdx index 4ac7371cb5452..4251ffb07407b 100644 --- a/dev_docs/contributing/best_practices.mdx +++ b/dev_docs/contributing/best_practices.mdx @@ -155,6 +155,14 @@ When making a change like this, import statements that previously pointed to the called `@kbn/imports/exports_moved_packages` which allows contributors to define the exports previously available from one package as now being available from another package and leverage auto-fixing to migration all existing and new uses of this export to the proper package. +## Logging + +- Do not log sensitive information (personally identifiable information, passwords, api keys, etc.), regardless of the log level. Err on the side of caution. Personally identifiable information is common in user input; for example, dashboard titles, index names and Elasticsearch `_search` queries. +- Logs should include just enough information to be actionable. +- Use the right log level, see . +- Use ECS format for any additional LogMeta you add to your logging statements. +- Logs are read by customers, a large number of Elastic employees, and Kibana contributors. As such, log messages should use language that is understandable to a wide audience and should avoid disclosing implementation details (unless they're at the `debug`/`trace` level). + ## Licensing diff --git a/docs/CHANGELOG.asciidoc b/docs/CHANGELOG.asciidoc index 2b24ca538caa9..429f78349942b 100644 --- a/docs/CHANGELOG.asciidoc +++ b/docs/CHANGELOG.asciidoc @@ -194,8 +194,8 @@ Discover:: * Allow fetching more documents on Discover page ({kibana-pull}163784[#163784]). Elastic Security:: For the Elastic Security 8.11.0 release information, refer to {security-guide}/release-notes.html[_Elastic Security Solution Release Notes_]. -Enterprise Search:: -For the Elastic Enterprise Search 8.11.0 release information, refer to {enterprise-search-ref}/changelog.html[_Elastic Enterprise Search Documentation Release notes_]. +Search:: +* Self-managed connector clients now show advanced configuration options in the UI ({kibana-pull}167770[#167770]). Fleet:: * Adds sidebar navigation showing headings extracted from the readme ({kibana-pull}167216[#167216]). Inspector:: @@ -252,8 +252,15 @@ Dashboard:: * Generate new panel IDs on Dashboard clone ({kibana-pull}166299[#166299]). Elastic Security:: For the Elastic Security 8.11.0 release information, refer to {security-guide}/release-notes.html[_Elastic Security Solution Release Notes_]. -Enterprise Search:: -For the Elastic Enterprise Search 8.11.0 release information, refer to {enterprise-search-ref}/changelog.html[_Elastic Enterprise Search Documentation Release notes_]. +Search:: +* Native connector external documentation links are now rendered conditionally to avoid empty links ({kibana-pull}169121[#169121]). +* Fixed an issue which caused Access Control Syncs to be scheduled when Document Level Security was disabled ({kibana-pull}168987[#168987]). +* Restored access and admin checks for App Search and Workplace Search product cards ({kibana-pull}168890[#168890]). +* The filter box in the *Browse documents* tab under *Search > Content > Indices* now escapes Lucene reserved characters instead of throwing errors ({kibana-pull}168092[#168092]). +* Fixed an issue associated with changing the indices underlying a search application. When a user modifies the indices underlying a search application in Kibana, the associated search template is now reverted to the default template ({kibana-pull}167532[#167532]). +* Fixed an issue where the Search plugin was inaccessible for unauthenticated users, eg. for Kibana in read-only demo setups ({kibana-pull}167171[#167171]). +* Fixed an issue with the welcome banner in Search ({kibana-pull}166814[#166814]). +* Self managed connector clients now show advanced configuration options in the UI ({kibana-pull}167770[#167770]). Fleet:: * Vastly improve performance of Fleet final pipeline's date formatting logic for `event.ingested` ({kibana-pull}167318[#167318]). Lens & Visualizations:: diff --git a/docs/apm/apm-alerts.asciidoc b/docs/apm/apm-alerts.asciidoc index cda045e8d8ccd..59cfbc50f38dc 100644 --- a/docs/apm/apm-alerts.asciidoc +++ b/docs/apm/apm-alerts.asciidoc @@ -103,6 +103,22 @@ Based on the criteria above, define the following rule details: * **Group alerts by** - `service.name` `service.environment` * **Check every** - `1 minute` +[NOTE] +==== +Alternatively, you can use a KQL filter to limit the scope of the alert: + +. Toggle on *Use KQL Filter*. +. Add a filter, for example to achieve the same effect as the example above: ++ +[source,txt] +------ +service.name:"{your_service.name}" and service.environment:"{your_service.environment}" and error.grouping_key:"{your_error.ID}" +------ + +Using a KQL Filter to limit the scope is available for _Latency threshold_, _Failed transaction rate threshold_, and +_Error count threshold_ rules. +==== + Select the **Email** connector and click **Create a connector**. Fill out the required details: sender, host, port, etc., and click **save**. diff --git a/docs/apm/images/apm-alert.png b/docs/apm/images/apm-alert.png index 92b6f5dde9730..ccaf2de64ec08 100644 Binary files a/docs/apm/images/apm-alert.png and b/docs/apm/images/apm-alert.png differ diff --git a/docs/concepts/esql.asciidoc b/docs/concepts/esql.asciidoc new file mode 100644 index 0000000000000..413db3ed35bbc --- /dev/null +++ b/docs/concepts/esql.asciidoc @@ -0,0 +1,40 @@ +[[esql]] +=== {esql} + +preview::[] + +The Elasticsearch Query Language, {esql}, has been created to make exploring your data faster and easier using the **Discover** application. From version 8.11 you can try this new feature, which is enabled by default. + +[role="screenshot"] +image:images/esql-data-view-menu.png[An image of the Discover UI where users can access the {esql} feature, width=30%] + +This new piped language allows you to chain together multiple commands to query your data. Based on the query, Lens suggestions in Discover create a visualization of the query results. + +{esql} comes with its own dedicated {esql} Compute Engine for greater efficiency. From one query you can search, aggregate, calculate and perform data transformations without leaving **Discover**. Write your query directly in **Discover** or use the **Dev Tools** with the {ref}/esql-rest.html[{esql} API]. + +{esql} also features in-app help, so you can get started faster and don't have to leave the application to check syntax. + +[role="screenshot"] +image:images/esql-in-app-help.png[An image of the Discover UI where users can browse the in-app help] + +For more detailed information about the {esql} language, refer to {ref}/esql-language.html[Learning {esql}]. + +[float] +[[esql-observability]] +==== {observability} + +{esql} makes it much easier to analyze metrics, logs and traces from a single query. Find performance issues fast by defining fields on the fly, enriching data with lookups, and using simultaneous query processing. Combining {esql} with {ml} and AiOps can improve detection accuracy and use aggregated value thresholds. + +[float] +[[esql-security]] +==== Security + +Use {esql} to retrieve important information for investigation by using lookups. Enrich data and create new fields on the go to gain valuable insight for faster decision-making and actions. For example, perform a lookup on an IP address to identify its geographical location, its association with known malicious entities, or whether it belongs to a known cloud service provider all from one search bar. {esql} ensures more accurate alerts by incorporating aggregated values in detection rules. + +[float] +[[esql-whats-next]] +==== What's next? + +Full documentation for this language is available in the {es} documentation, refer to {ref}/esql.html[{esql}]. + +Alternatively, a short tutorial is available in the **Discover** section <>. \ No newline at end of file diff --git a/docs/concepts/images/esql-activated.png b/docs/concepts/images/esql-activated.png new file mode 100644 index 0000000000000..f1ac82548d4d4 Binary files /dev/null and b/docs/concepts/images/esql-activated.png differ diff --git a/docs/concepts/images/esql-data-view-menu.png b/docs/concepts/images/esql-data-view-menu.png new file mode 100644 index 0000000000000..fbbbdf44d315c Binary files /dev/null and b/docs/concepts/images/esql-data-view-menu.png differ diff --git a/docs/concepts/images/esql-in-app-help.png b/docs/concepts/images/esql-in-app-help.png new file mode 100644 index 0000000000000..eb818a11cbacb Binary files /dev/null and b/docs/concepts/images/esql-in-app-help.png differ diff --git a/docs/concepts/index.asciidoc b/docs/concepts/index.asciidoc index d7a18c7af1e7e..5e02b8f0d4d7c 100644 --- a/docs/concepts/index.asciidoc +++ b/docs/concepts/index.asciidoc @@ -155,8 +155,11 @@ include::data-views.asciidoc[] include::set-time-filter.asciidoc[] +include::esql.asciidoc[] + include::kuery.asciidoc[] include::lucene.asciidoc[] include::save-query.asciidoc[] + diff --git a/docs/developer/plugin-list.asciidoc b/docs/developer/plugin-list.asciidoc index 40c8fbf2b338b..868ef59f47966 100644 --- a/docs/developer/plugin-list.asciidoc +++ b/docs/developer/plugin-list.asciidoc @@ -598,7 +598,7 @@ Index Management by running this series of requests in Console: |{kib-repo}blob/{branch}/x-pack/plugins/index_management/README.md[indexManagement] -|Create an index with special characters and verify it renders correctly: +|This service is exposed from the Index Management setup contract and can be used to add content to the indices list and the index details page. |{kib-repo}blob/{branch}/x-pack/plugins/infra/README.md[infra] diff --git a/docs/discover/images/esql-activated.png b/docs/discover/images/esql-activated.png new file mode 100644 index 0000000000000..f1ac82548d4d4 Binary files /dev/null and b/docs/discover/images/esql-activated.png differ diff --git a/docs/discover/images/esql-full-query.png b/docs/discover/images/esql-full-query.png new file mode 100644 index 0000000000000..1d4a37af23a60 Binary files /dev/null and b/docs/discover/images/esql-full-query.png differ diff --git a/docs/discover/images/esql-limit.png b/docs/discover/images/esql-limit.png new file mode 100644 index 0000000000000..dbc9edc3cdc13 Binary files /dev/null and b/docs/discover/images/esql-limit.png differ diff --git a/docs/discover/images/esql-machine-os-ram.png b/docs/discover/images/esql-machine-os-ram.png new file mode 100644 index 0000000000000..2c936cecb9498 Binary files /dev/null and b/docs/discover/images/esql-machine-os-ram.png differ diff --git a/docs/discover/images/try-esql.png b/docs/discover/images/try-esql.png new file mode 100644 index 0000000000000..87abbf2fd3d73 Binary files /dev/null and b/docs/discover/images/try-esql.png differ diff --git a/docs/discover/log-pattern-analysis.asciidoc b/docs/discover/log-pattern-analysis.asciidoc index 20e07aeb1d8d6..398add21cc38c 100644 --- a/docs/discover/log-pattern-analysis.asciidoc +++ b/docs/discover/log-pattern-analysis.asciidoc @@ -1,38 +1,38 @@ [[run-pattern-analysis-discover]] == Run a pattern analysis on your log data -preview::["This functionality is in technical preview, requires a link:https://www.elastic.co/subscriptions[Platinum subscription], 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."] +preview::["This functionality is in technical preview, requires a link:https://www.elastic.co/subscriptions[Platinum subscription], and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features."] include::../user/ml/index.asciidoc[tag=log-pattern-analysis-intro] Log pattern analysis works on every text field. -This example uses the <>, or you +This example uses the <>, or you can use your own data. . Open the main menu, and click *Discover*. . Expand the {data-source} dropdown, and select *Kibana Sample Data Logs*. -. If you don't see any results, expand the time range, for example, to +. If you don't see any results, expand the time range, for example, to *Last 15 days*. -. Click the `message` field in the **Available fields** list sidebar and click +. Click the `message` field in the **Available fields** list sidebar and click **Run pattern analysis**. + -- [role="screenshot"] image::images/log-pattern-analysis-available-fields.png["Available fields view in Discover showing the message field selected."] -The pattern analysis starts. The results are displayed in a flyout when the +The pattern analysis starts. The results are displayed in a flyout when the analysis is complete. [role="screenshot"] image::images/log-pattern-analysis-results.png["Log pattern analysis results in Discover."] -- -. (optional) Apply filters to one or more patterns. *Discover* only displays -documents that match the selected patterns. Additionally, you can remove -selected patterns from *Discover*, resulting in the display of only those -documents that don't match the selected pattern. These options enable you to -remove unimportant messages and focus on the more important, actionable data +. (optional) Apply filters to one or more patterns. *Discover* only displays +documents that match the selected patterns. Additionally, you can remove +selected patterns from *Discover*, resulting in the display of only those +documents that don't match the selected pattern. These options enable you to +remove unimportant messages and focus on the more important, actionable data during troubleshooting. \ No newline at end of file diff --git a/docs/discover/try-esql.asciidoc b/docs/discover/try-esql.asciidoc new file mode 100644 index 0000000000000..cc6e4d62f17c4 --- /dev/null +++ b/docs/discover/try-esql.asciidoc @@ -0,0 +1,91 @@ +[[try-esql]] +== Try {esql} + +preview::[] + +The Elasticsearch Query Language, {esql}, makes it easier to explore your data without leaving Discover. + +In this tutorial we'll use the {kib} sample web logs in Discover and Lens to explore the data and create visualizations. + +[float] +[[prerequisite]] +=== Prerequisite + +To be able to select **Try {esql}** from the Data views menu the `discover:enableESQL` setting must be enabled from **Stack Management > Advanced Settings**. It is enabled by default. + +[float] +[[tutorial-try-esql]] +=== Trying {esql} + +To load the sample data: + +. On the home page, click **Try sample data**. +. Click **Other sample data sets**. +. On the Sample web logs card, click **Add data**. +. Open the main menu and select *Discover*. +. From the Data views menu, select *Try {esql}*. + +Let's say we want to find out what operating system users have and how much RAM is on their machine. + +. Set the time range to **Last 7 days**. +. Expand image:images/expand-icon-2.png[An image of the expand icon] the query bar. +. Put each processing command on a new line for better readability. +. Copy the query below: ++ +[source,esql] +---- +FROM kibana_sample_data_logs +| KEEP machine.os, machine.ram +---- ++ +. Click **Update**. ++ +[role="screenshot"] +image:images/esql-machine-os-ram.png[An image of the query result] ++ +[NOTE] +==== +{esql} keywords are not case sensitive. +==== + +Let's add `geo.dest` to our query, to find out the geographical destination of the visits, and limit the results. + +. Copy the query below: ++ +[source,esql] +---- +FROM kibana_sample_data_logs +| KEEP machine.os, machine.ram, geo.dest +| LIMIT 10 +---- ++ +. Click **Update**. ++ +[role="screenshot"] +image:images/esql-limit.png[An image of the extended query result] + +Let's sort the data by machine ram and filter out the destination GB. + +. Copy the query below: ++ +[source,esql] +---- +FROM kibana_sample_data_logs +| KEEP machine.os, machine.ram, geo.dest +| SORT machine.ram desc +| WHERE geo.dest != "GB" +| LIMIT 10 +---- ++ +. Click **Update**. ++ +[role="screenshot"] +image:images/esql-full-query.png[] ++ +. Click **Save** to save the query and visualization to a dashboard. + +To make changes to the visualization you can use the visualization drop-down. To make changes to the colors used or the axes, or click the pencil icon. This opens an in-line editor where you can change the colors and axes of the visualization. + +To learn more about {esql}, try other tutorials, see more examples and reference material, refer to {ref}/esql.html[{esql}]. + + diff --git a/docs/setup/docker.asciidoc b/docs/setup/docker.asciidoc index d8c09b39a3cc4..4dcd80d1bfd66 100644 --- a/docs/setup/docker.asciidoc +++ b/docs/setup/docker.asciidoc @@ -10,7 +10,7 @@ :es-docker-image: {es-docker-repo}:{version} Docker images for {kib} are available from the Elastic Docker registry. The -base image is https://hub.docker.com/_/ubuntu[ubuntu:22.04]. +base image is https://hub.docker.com/_/ubuntu[ubuntu:20.04]. A list of all published Docker images and tags is available at https://www.docker.elastic.co[www.docker.elastic.co]. The source code is in diff --git a/docs/user/dashboard/make-dashboards-interactive.asciidoc b/docs/user/dashboard/make-dashboards-interactive.asciidoc index 03d48e308f542..7df824b39af17 100644 --- a/docs/user/dashboard/make-dashboards-interactive.asciidoc +++ b/docs/user/dashboard/make-dashboards-interactive.asciidoc @@ -211,6 +211,70 @@ To use series data interactions, click a data series in the panel. + To use saved search interactions, open the panel menu, then click *More > View saved search*. +[[dashboard-links]] +=== Create links to other dashboards + +preview::["This functionality is in technical preview, and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features."] + +You can use *Links* panels to create links to other dashboards or external websites. When creating links to other dashboards, you have the option to carry the time range and query and filters to apply to the linked dashboard. Links to external websites follow the <> settings. *Links* panels support vertical and horizontal layouts and may be saved to the *Library* for use on other dashboards. + +* <> +* <> +* <> +* <> + +[float] +[[add-links-panel]] +==== Add a links panel + +To add a links panel to your dashboards: + +. On the **Dashboards** page, click the dashboard **Title** you want to open. +. Click **Add panel > Links**. +. In the **Create links panel** flyout choose between the panel displaying vertically or horizontally on your dashboard. +. Click **Add link**. +. Specify the following: +* **Go to** - Dashboard to link to another dashboard, or URL to link to an external website. +* **Choose destination** - Use the dropdown to select another dashboard or enter an external URL. +* **Text** - Enter text for the link, which displays in the panel. +* **Options** - When linking to another dashboard use the sliders to use the filters and queries from the original dashboard, use the date range from the original dashboard, or open the dashboard in a new tab. When linking to an external URL use the sliders to open the URL in a new tab, or encode the URL. +. Click **Add link**. +. Click **Save**. +. Enter the **Title** and **Description**, then click **Save**. + +[float] +[[add-links-panel-from-library]] +==== Add a links panel from the library + +By default links panels are saved to the library. To add a links panel to another dashboard: + +. On the **Dashboards** page, click the dashboard **Title** you want to open. +. Click **Add from library**. +. Select the links panel from the **Add from library** flyout. +. Click **Save**. + +[float] +[[edit-links-panel]] +==== Edit links panels + +To edit links panels: + +. Click image:images/lens_layerActions_8.5.0.png[], then **Edit Links**. +. Click image:images/dashboard_controlsEditControl_8.3.0.png[] on the link. +. Click **Update link**. +. Click **Save**. + +[float] +[[delete-links-panels]] +==== Delete links panels + +To delete links panels: + +. Click image:images/lens_layerActions_8.5.0.png[], then **More**. +. Click **Delete from dashboard**. +. Click **Save**. + + [[create-drilldowns]] === Customize interactions with drilldowns diff --git a/docs/user/discover.asciidoc b/docs/user/discover.asciidoc index 6f35e9a9d59ba..e2b3fc2e0916e 100644 --- a/docs/user/discover.asciidoc +++ b/docs/user/discover.asciidoc @@ -346,4 +346,7 @@ include::{kib-repo-dir}/discover/field-statistics.asciidoc[] include::{kib-repo-dir}/discover/log-pattern-analysis.asciidoc[] -include::{kib-repo-dir}/discover/search-sessions.asciidoc[] \ No newline at end of file +include::{kib-repo-dir}/discover/search-sessions.asciidoc[] + +include::{kib-repo-dir}/discover/try-esql.asciidoc[] + diff --git a/package.json b/package.json index 0831324b29286..1b18b61269b2a 100644 --- a/package.json +++ b/package.json @@ -679,9 +679,7 @@ "@kbn/share-plugin": "link:src/plugins/share", "@kbn/shared-svg": "link:packages/kbn-shared-svg", "@kbn/shared-ux-avatar-solution": "link:packages/shared-ux/avatar/solution", - "@kbn/shared-ux-button-exit-full-screen": "link:packages/shared-ux/button/exit_full_screen/impl", - "@kbn/shared-ux-button-exit-full-screen-mocks": "link:packages/shared-ux/button/exit_full_screen/mocks", - "@kbn/shared-ux-button-exit-full-screen-types": "link:packages/shared-ux/button/exit_full_screen/types", + "@kbn/shared-ux-button-exit-full-screen": "link:packages/shared-ux/button/exit_full_screen", "@kbn/shared-ux-button-toolbar": "link:packages/shared-ux/button_toolbar", "@kbn/shared-ux-card-no-data": "link:packages/shared-ux/card/no_data/impl", "@kbn/shared-ux-card-no-data-mocks": "link:packages/shared-ux/card/no_data/mocks", @@ -1299,7 +1297,6 @@ "@types/chromedriver": "^81.0.2", "@types/classnames": "^2.2.9", "@types/color": "^3.0.3", - "@types/compression-webpack-plugin": "^2.0.2", "@types/cytoscape": "^3.14.0", "@types/d3": "^3.5.43", "@types/d3-array": "^2.12.1", @@ -1327,7 +1324,6 @@ "@types/geojson": "^7946.0.10", "@types/getos": "^3.0.0", "@types/gulp": "^4.0.6", - "@types/gulp-zip": "^4.0.1", "@types/hapi__cookie": "^10.1.3", "@types/hapi__h2o2": "^8.3.3", "@types/hapi__hapi": "^20.0.9", @@ -1459,10 +1455,9 @@ "blob-polyfill": "^7.0.20220408", "callsites": "^3.1.0", "chance": "1.0.18", - "chromedriver": "^117.0.3", + "chromedriver": "^119.0.0", "clean-webpack-plugin": "^3.0.0", "cli-table3": "^0.6.1", - "compression-webpack-plugin": "^4.0.0", "copy-webpack-plugin": "^6.0.2", "cpy": "^8.1.1", "css-loader": "^3.4.2", @@ -1515,7 +1510,6 @@ "gulp-postcss": "^9.0.1", "gulp-sourcemaps": "2.6.5", "gulp-terser": "^2.1.0", - "gulp-zip": "^5.0.2", "has-ansi": "^3.0.0", "hdr-histogram-js": "^1.2.0", "html": "1.0.0", diff --git a/packages/core/analytics/core-analytics-browser-internal/src/track_clicks.test.ts b/packages/core/analytics/core-analytics-browser-internal/src/track_clicks.test.ts index db1b8fc215cf8..427ffc70bc2e1 100644 --- a/packages/core/analytics/core-analytics-browser-internal/src/track_clicks.test.ts +++ b/packages/core/analytics/core-analytics-browser-internal/src/track_clicks.test.ts @@ -84,6 +84,38 @@ describe('trackClicks', () => { `); }); + test('trims values longer than 256 chars', async () => { + // Gather an actual "click" event + const event$ = new ReplaySubject(1); + const parent = document.createElement('div'); + parent.setAttribute('data-test-subj', 'test-click-target-parent'); + const element = document.createElement('button'); + parent.appendChild(element); + const reallyLongText = `test-click-target-${new Array(10000).fill('0').join('')}`; + element.setAttribute('data-test-subj', reallyLongText); + element.innerText = 'test'; // Only to validate that it is not included in the event. + element.value = 'test'; // Only to validate that it is not included in the event. + element.addEventListener('click', (e) => event$.next(e)); + element.click(); + // Using an observable because the event might not be immediately available + const event = await firstValueFrom(event$.pipe(take(1))); + event$.complete(); // No longer needed + + trackClicks(analyticsClientMock, true); + expect(addEventListenerSpy).toHaveBeenCalledTimes(1); + + (addEventListenerSpy.mock.calls[0][1] as EventListener)(event); + expect(analyticsClientMock.reportEvent).toHaveBeenCalledTimes(1); + expect(analyticsClientMock.reportEvent).toHaveBeenCalledWith('click', { + target: [ + 'DIV', + 'data-test-subj=test-click-target-parent', + 'BUTTON', + `data-test-subj=test-click-target-${new Array(256 - 33).fill('0').join('')}`, + ], + }); + }); + test('swallows any processing errors when not in dev mode', async () => { trackClicks(analyticsClientMock, false); expect(addEventListenerSpy).toHaveBeenCalledTimes(1); diff --git a/packages/core/analytics/core-analytics-browser-internal/src/track_clicks.ts b/packages/core/analytics/core-analytics-browser-internal/src/track_clicks.ts index d140a6c99e7b0..6ca58e7d69149 100644 --- a/packages/core/analytics/core-analytics-browser-internal/src/track_clicks.ts +++ b/packages/core/analytics/core-analytics-browser-internal/src/track_clicks.ts @@ -19,6 +19,7 @@ const HTML_ATTRIBUTES_TO_REMOVE = [ 'data-rfd-draggable-id', 'href', 'value', + 'title', ]; /** @@ -81,6 +82,6 @@ function getTargetDefinition(target: HTMLElement): string[] { target.tagName, ...[...target.attributes] .filter((attr) => !HTML_ATTRIBUTES_TO_REMOVE.includes(attr.name)) - .map((attr) => `${attr.name}=${attr.value}`), + .map((attr) => `${attr.name}=${attr.value}`.slice(0, 256)), ]; } diff --git a/packages/core/elasticsearch/core-elasticsearch-client-server-internal/src/log_query_and_deprecation.test.ts b/packages/core/elasticsearch/core-elasticsearch-client-server-internal/src/log_query_and_deprecation.test.ts index 0bf8d61e8f465..edb3ab90e6bc6 100644 --- a/packages/core/elasticsearch/core-elasticsearch-client-server-internal/src/log_query_and_deprecation.test.ts +++ b/packages/core/elasticsearch/core-elasticsearch-client-server-internal/src/log_query_and_deprecation.test.ts @@ -68,6 +68,7 @@ describe('instrumentQueryAndDeprecationLogger', () => { beforeEach(() => { logger = loggingSystemMock.createLogger(); + logger.isLevelEnabled.mockReturnValue(true); parseClientOptionsMock.mockReturnValue({}); ClientMock.mockImplementation(() => createFakeClient()); }); @@ -493,6 +494,29 @@ describe('instrumentQueryAndDeprecationLogger', () => { {\\"seq_no_primary_term\\":true,\\"query\\":{\\"term\\":{\\"user\\":\\"kimchy\\"}}}" `); }); + + it('does not log when debug level is disabled for the query logger', () => { + logger.isLevelEnabled.mockReturnValue(false); + + instrumentEsQueryAndDeprecationLogger({ + logger, + client, + type: 'test type', + apisToRedactInLogs: [], + }); + + const response = createResponseWithBody( + JSON.stringify({ + seq_no_primary_term: true, + query: { + term: { user: 'kimchy' }, + }, + }) + ); + + client.diagnostic.emit('response', null, response); + expect(loggingSystemMock.collect(logger).debug).toMatchInlineSnapshot(`Array []`); + }); }); describe('deprecation warnings from response headers', () => { @@ -712,6 +736,39 @@ describe('instrumentQueryAndDeprecationLogger', () => { ); }); + it('does not log when debug level is disabled for the deprecation logger', () => { + logger.isLevelEnabled.mockReturnValue(false); + + instrumentEsQueryAndDeprecationLogger({ + logger, + client, + type: 'test type', + apisToRedactInLogs: [], + }); + + const response = createApiResponse({ + statusCode: 200, + warnings: ['299 Elasticsearch-8.1.0 "GET /_path is deprecated"'], + params: { + method: 'GET', + path: '/_path', + querystring: { hello: 'dolly' }, + // Set the request header to indicate to Elasticsearch that this is a request over which users have no control + headers: { 'x-elastic-product-origin': 'kibana' }, + }, + body: { + hits: [ + { + _source: 'may the source be with you', + }, + ], + }, + }); + client.diagnostic.emit('response', null, response); + + expect(loggingSystemMock.collect(logger).debug).toMatchInlineSnapshot(`Array []`); + }); + describe('Request body redaction on some APIs', () => { it('redacts for an API in the extended list (path only)', () => { instrumentEsQueryAndDeprecationLogger({ diff --git a/packages/core/elasticsearch/core-elasticsearch-client-server-internal/src/log_query_and_deprecation.ts b/packages/core/elasticsearch/core-elasticsearch-client-server-internal/src/log_query_and_deprecation.ts index 954baec201e45..8d7f0f0a5c2dd 100644 --- a/packages/core/elasticsearch/core-elasticsearch-client-server-internal/src/log_query_and_deprecation.ts +++ b/packages/core/elasticsearch/core-elasticsearch-client-server-internal/src/log_query_and_deprecation.ts @@ -153,6 +153,24 @@ export function getRequestDebugMeta( * */ const isEsWarning = (warning: string) => /\d\d\d Elasticsearch-/.test(warning); +function getQueryMessage( + bytes: number | undefined, + error: errors.ElasticsearchClientError | errors.ResponseError | null, + event: DiagnosticResult, + apisToRedactInLogs: ElasticsearchApiToRedactInLogs[] +) { + const bytesMsg = bytes ? ` - ${numeral(bytes).format('0.0b')}` : ''; + if (error) { + if (error instanceof errors.ResponseError) { + return `${getResponseMessage(event, bytesMsg, apisToRedactInLogs)} ${getErrorMessage(error)}`; + } else { + return getErrorMessage(error); + } + } else { + return getResponseMessage(event, bytesMsg, apisToRedactInLogs); + } +} + export const instrumentEsQueryAndDeprecationLogger = ({ logger, client, @@ -166,28 +184,23 @@ export const instrumentEsQueryAndDeprecationLogger = ({ }) => { const queryLogger = logger.get('query', type); const deprecationLogger = logger.get('deprecation'); + client.diagnostic.on('response', (error, event) => { - if (event) { + // we could check this once and not subscribe to response events if both are disabled, + // but then we would not be supporting hot reload of the logging configuration. + const logQuery = queryLogger.isLevelEnabled('debug'); + const logDeprecation = deprecationLogger.isLevelEnabled('debug'); + + if (event && (logQuery || logDeprecation)) { const bytes = getContentLength(event.headers); - const bytesMsg = bytes ? ` - ${numeral(bytes).format('0.0b')}` : ''; - const meta = getEcsResponseLog(event, bytes); - - let queryMsg = ''; - if (error) { - if (error instanceof errors.ResponseError) { - queryMsg = `${getResponseMessage(event, bytesMsg, apisToRedactInLogs)} ${getErrorMessage( - error - )}`; - } else { - queryMsg = getErrorMessage(error); - } - } else { - queryMsg = getResponseMessage(event, bytesMsg, apisToRedactInLogs); - } + const queryMsg = getQueryMessage(bytes, error, event, apisToRedactInLogs); - queryLogger.debug(queryMsg, meta); + if (logQuery) { + const meta = getEcsResponseLog(event, bytes); + queryLogger.debug(queryMsg, meta); + } - if (event.warnings && event.warnings.filter(isEsWarning).length > 0) { + if (logDeprecation && event.warnings && event.warnings.filter(isEsWarning).length > 0) { // Plugins can explicitly mark requests as originating from a user by // removing the `'x-elastic-product-origin': 'kibana'` header that's // added by default. User requests will be shown to users in the diff --git a/packages/core/elasticsearch/core-elasticsearch-server-internal/src/elasticsearch_config.ts b/packages/core/elasticsearch/core-elasticsearch-server-internal/src/elasticsearch_config.ts index 6619e7cb1488a..b1a4712a7949d 100644 --- a/packages/core/elasticsearch/core-elasticsearch-server-internal/src/elasticsearch_config.ts +++ b/packages/core/elasticsearch/core-elasticsearch-server-internal/src/elasticsearch_config.ts @@ -57,7 +57,7 @@ export const configSchema = schema.object({ }, }) ), - password: schema.maybe(schema.string()), + password: schema.maybe(schema.string({ coerceFromNumber: true })), serviceAccountToken: schema.maybe( schema.conditional( schema.siblingRef('username'), diff --git a/packages/core/http/core-http-browser-internal/src/fetch.ts b/packages/core/http/core-http-browser-internal/src/fetch.ts index f6aa29c497d43..60d71ba0dc72e 100644 --- a/packages/core/http/core-http-browser-internal/src/fetch.ts +++ b/packages/core/http/core-http-browser-internal/src/fetch.ts @@ -23,6 +23,7 @@ import { ELASTIC_HTTP_VERSION_HEADER, X_ELASTIC_INTERNAL_ORIGIN_REQUEST, } from '@kbn/core-http-common'; +import { KIBANA_BUILD_NR_HEADER } from '@kbn/core-http-common'; import { HttpFetchError } from './http_fetch_error'; import { HttpInterceptController } from './http_intercept_controller'; import { interceptRequest, interceptResponse } from './intercept'; @@ -136,7 +137,7 @@ export class Fetch { 'Content-Type': 'application/json', ...options.headers, 'kbn-version': this.params.kibanaVersion, - 'kbn-build-number': this.params.buildNumber, + [KIBANA_BUILD_NR_HEADER]: this.params.buildNumber, [ELASTIC_HTTP_VERSION_HEADER]: version, [X_ELASTIC_INTERNAL_ORIGIN_REQUEST]: 'Kibana', ...(!isEmpty(context) ? new ExecutionContextContainer(context).toHeader() : {}), diff --git a/packages/core/http/core-http-common/index.ts b/packages/core/http/core-http-common/index.ts index 07dbfa5e14d89..2fbcf914c5fbb 100644 --- a/packages/core/http/core-http-common/index.ts +++ b/packages/core/http/core-http-common/index.ts @@ -14,4 +14,5 @@ export { ELASTIC_HTTP_VERSION_QUERY_PARAM, ELASTIC_INTERNAL_ORIGIN_QUERY_PARAM, X_ELASTIC_INTERNAL_ORIGIN_REQUEST, + KIBANA_BUILD_NR_HEADER, } from './src/constants'; diff --git a/packages/core/http/core-http-common/src/constants.ts b/packages/core/http/core-http-common/src/constants.ts index fd7beef090f63..f2d718f2a59d2 100644 --- a/packages/core/http/core-http-common/src/constants.ts +++ b/packages/core/http/core-http-common/src/constants.ts @@ -11,3 +11,6 @@ export const ELASTIC_HTTP_VERSION_HEADER = 'elastic-api-version' as const; export const ELASTIC_HTTP_VERSION_QUERY_PARAM = 'apiVersion' as const; export const ELASTIC_INTERNAL_ORIGIN_QUERY_PARAM = 'elasticInternalOrigin' as const; export const X_ELASTIC_INTERNAL_ORIGIN_REQUEST = 'x-elastic-internal-origin' as const; + +/** @internal */ +export const KIBANA_BUILD_NR_HEADER = 'kbn-build-number' as const; diff --git a/packages/core/http/core-http-server-internal/src/http_service.ts b/packages/core/http/core-http-server-internal/src/http_service.ts index 46d12ddbbd68a..96e9c8a85ba89 100644 --- a/packages/core/http/core-http-server-internal/src/http_service.ts +++ b/packages/core/http/core-http-server-internal/src/http_service.ts @@ -102,7 +102,7 @@ export class HttpService }, }); - registerCoreHandlers(prebootSetup, config, this.env); + registerCoreHandlers(prebootSetup, config, this.env, this.log); if (this.shouldListen(config)) { this.log.debug('starting preboot server'); @@ -162,7 +162,7 @@ export class HttpService deps.executionContext ); - registerCoreHandlers(serverContract, config, this.env); + registerCoreHandlers(serverContract, config, this.env, this.log); this.internalSetup = { ...serverContract, diff --git a/packages/core/http/core-http-server-internal/src/lifecycle_handlers.test.ts b/packages/core/http/core-http-server-internal/src/lifecycle_handlers.test.ts index 6e2c53af82679..72082e0cb1e55 100644 --- a/packages/core/http/core-http-server-internal/src/lifecycle_handlers.test.ts +++ b/packages/core/http/core-http-server-internal/src/lifecycle_handlers.test.ts @@ -14,9 +14,11 @@ import type { OnPostAuthToolkit, OnPreRoutingToolkit, OnPostAuthHandler, + OnPreResponseInfo, } from '@kbn/core-http-server'; import { mockRouter } from '@kbn/core-http-router-server-mocks'; import { + createBuildNrMismatchLoggerPreResponseHandler, createCustomHeadersPreResponseHandler, createRestrictInternalRoutesPostAuthHandler, createVersionCheckPostAuthHandler, @@ -24,6 +26,9 @@ import { } from './lifecycle_handlers'; import { HttpConfig } from './http_config'; +import { loggerMock } from '@kbn/logging-mocks'; +import { Logger } from '@kbn/logging'; +import { KIBANA_BUILD_NR_HEADER } from '@kbn/core-http-common'; type ToolkitMock = jest.Mocked; @@ -43,13 +48,18 @@ const forgeRequest = ({ path = '/', method = 'get', kibanaRouteOptions, + buildNr, }: Partial<{ headers: Record; query: Record; path: string; method: RouteMethod; kibanaRouteOptions: KibanaRouteOptions; + buildNr: undefined | string; }>): KibanaRequest => { + if (buildNr) { + headers[KIBANA_BUILD_NR_HEADER] = buildNr; + } return mockRouter.createKibanaRequest({ headers, path, @@ -452,3 +462,79 @@ describe('customHeaders pre-response handler', () => { }); }); }); + +describe('build number mismatch logger on error pre-response handler', () => { + let logger: jest.Mocked; + + beforeEach(() => { + logger = loggerMock.create(); + }); + + it('injects a logger prefix', () => { + createBuildNrMismatchLoggerPreResponseHandler(123, logger); + expect(logger.get).toHaveBeenCalledTimes(1); + expect(logger.get).toHaveBeenCalledWith(`kbn-build-number-mismatch`); + }); + + it('does not log for same server-client build', () => { + const handler = createBuildNrMismatchLoggerPreResponseHandler(123, logger); + const request = forgeRequest({ buildNr: '123' }); + const response: OnPreResponseInfo = { statusCode: 500 }; // should log for errors, but not this time bc same build nr + handler(request, response, createToolkit()); + expect(logger.warn).not.toHaveBeenCalled(); + }); + + const badStatusCodeTestCases = [ + /** just test a few common ones */ + [400], + [401], + [403], + [499], + [500], + [502], + [999] /* and not so common... */, + ]; + it.each(badStatusCodeTestCases)( + 'logs for %p responses and newer client builds', + (responseStatusCode) => { + const handler = createBuildNrMismatchLoggerPreResponseHandler(123, logger); + const request = forgeRequest({ buildNr: '124' }); + const response: OnPreResponseInfo = { statusCode: responseStatusCode }; + handler(request, response, createToolkit()); + expect(logger.warn).toHaveBeenCalledTimes(1); + expect(logger.warn).toHaveBeenCalledWith( + `Client build (124) is newer than this Kibana server build (123). The [${responseStatusCode}] error status in req id [123] may be due to client-server incompatibility!` + ); + } + ); + + it.each(badStatusCodeTestCases)('logs for %p responses and older client builds', (statusCode) => { + const handler = createBuildNrMismatchLoggerPreResponseHandler(123, logger); + const request = forgeRequest({ buildNr: '122' }); + const response: OnPreResponseInfo = { statusCode }; + handler(request, response, createToolkit()); + expect(logger.warn).toHaveBeenCalledTimes(1); + expect(logger.warn).toHaveBeenCalledWith( + `Client build (122) is older than this Kibana server build (123). The [${statusCode}] error status in req id [123] may be due to client-server incompatibility!` + ); + }); + + it.each([[200], [201], [301], [302]])('does not log for %p responses', (statusCode) => { + const handler = createBuildNrMismatchLoggerPreResponseHandler(123, logger); + const request = forgeRequest({ buildNr: '124' }); + const response: OnPreResponseInfo = { statusCode }; + handler(request, response, createToolkit()); + expect(logger.warn).not.toHaveBeenCalled(); + }); + + it.each([['foo'], [['yes']], [true], [null], [[]], [undefined]])( + 'ignores bogus client build numbers like %p', + (bogusBuild) => { + const handler = createBuildNrMismatchLoggerPreResponseHandler(123, logger); + const request = forgeRequest({ buildNr: bogusBuild as any }); + const response: OnPreResponseInfo = { statusCode: 500 }; + handler(request, response, createToolkit()); + expect(logger.warn).not.toHaveBeenCalled(); + } + ); +}); diff --git a/packages/core/http/core-http-server-internal/src/lifecycle_handlers.ts b/packages/core/http/core-http-server-internal/src/lifecycle_handlers.ts index a86a0e230f609..6cedd4edbd6f8 100644 --- a/packages/core/http/core-http-server-internal/src/lifecycle_handlers.ts +++ b/packages/core/http/core-http-server-internal/src/lifecycle_handlers.ts @@ -6,8 +6,15 @@ * Side Public License, v 1. */ -import type { OnPostAuthHandler, OnPreResponseHandler } from '@kbn/core-http-server'; +import type { + OnPostAuthHandler, + OnPreResponseHandler, + OnPreResponseInfo, + KibanaRequest, +} from '@kbn/core-http-server'; import { isSafeMethod } from '@kbn/core-http-router-server-internal'; +import { Logger } from '@kbn/logging'; +import { KIBANA_BUILD_NR_HEADER } from '@kbn/core-http-common'; import { HttpConfig } from './http_config'; const VERSION_HEADER = 'kbn-version'; @@ -92,3 +99,44 @@ export const createCustomHeadersPreResponseHandler = (config: HttpConfig): OnPre return toolkit.next({ headers: additionalHeaders }); }; }; + +const shouldLogBuildNumberMismatch = ( + serverBuild: { number: number; string: string }, + request: KibanaRequest, + response: OnPreResponseInfo +): { log: true; clientBuild: number } | { log: false } => { + if ( + response.statusCode >= 400 && + request.headers[KIBANA_BUILD_NR_HEADER] !== serverBuild.string + ) { + const clientBuildNumber = parseInt(String(request.headers[KIBANA_BUILD_NR_HEADER]), 10); + if (!isNaN(clientBuildNumber)) { + return { log: true, clientBuild: clientBuildNumber }; + } + } + return { log: false }; +}; + +/** + * This should remain part of the logger prefix so that we can notify/track + * when we see this logged for observability purposes. + */ +const BUILD_NUMBER_MISMATCH_LOGGER_NAME = 'kbn-build-number-mismatch'; +export const createBuildNrMismatchLoggerPreResponseHandler = ( + serverBuildNumber: number, + log: Logger +): OnPreResponseHandler => { + const serverBuild = { number: serverBuildNumber, string: String(serverBuildNumber) }; + log = log.get(BUILD_NUMBER_MISMATCH_LOGGER_NAME); + + return (request, response, toolkit) => { + const result = shouldLogBuildNumberMismatch(serverBuild, request, response); + if (result.log === true) { + const clientCompAdjective = result.clientBuild > serverBuildNumber ? 'newer' : 'older'; + log.warn( + `Client build (${result.clientBuild}) is ${clientCompAdjective} than this Kibana server build (${serverBuildNumber}). The [${response.statusCode}] error status in req id [${request.id}] may be due to client-server incompatibility!` + ); + } + return toolkit.next(); + }; +}; diff --git a/packages/core/http/core-http-server-internal/src/register_lifecycle_handlers.test.ts b/packages/core/http/core-http-server-internal/src/register_lifecycle_handlers.test.ts index ebaefa5ea5dea..8e41ec9a827cb 100644 --- a/packages/core/http/core-http-server-internal/src/register_lifecycle_handlers.test.ts +++ b/packages/core/http/core-http-server-internal/src/register_lifecycle_handlers.test.ts @@ -11,6 +11,9 @@ jest.mock('./lifecycle_handlers', () => { return { ...actual, createVersionCheckPostAuthHandler: jest.fn(actual.createVersionCheckPostAuthHandler), + createBuildNrMismatchLoggerPreResponseHandler: jest.fn( + actual.createBuildNrMismatchLoggerPreResponseHandler + ), }; }); @@ -18,7 +21,11 @@ import { createTestEnv } from '@kbn/config-mocks'; import type { HttpConfig } from './http_config'; import { registerCoreHandlers } from './register_lifecycle_handlers'; -import { createVersionCheckPostAuthHandler } from './lifecycle_handlers'; +import { + createVersionCheckPostAuthHandler, + createBuildNrMismatchLoggerPreResponseHandler, +} from './lifecycle_handlers'; +import { loggerMock } from '@kbn/logging-mocks'; describe('registerCoreHandlers', () => { it('will not register client version checking if disabled via config', () => { @@ -39,11 +46,15 @@ describe('registerCoreHandlers', () => { }, } as unknown as HttpConfig; - registerCoreHandlers(registrarMock, config, createTestEnv()); + const logger = loggerMock.create(); + + registerCoreHandlers(registrarMock, config, createTestEnv(), logger); expect(createVersionCheckPostAuthHandler).toHaveBeenCalledTimes(0); + expect(createBuildNrMismatchLoggerPreResponseHandler).toHaveBeenCalledTimes(1); // we do expect to register a logger config.versioned.strictClientVersionCheck = true; - registerCoreHandlers(registrarMock, config, createTestEnv()); + registerCoreHandlers(registrarMock, config, createTestEnv(), logger); expect(createVersionCheckPostAuthHandler).toHaveBeenCalledTimes(1); + expect(createBuildNrMismatchLoggerPreResponseHandler).toHaveBeenCalledTimes(1); // logger registration should not be called again }); }); diff --git a/packages/core/http/core-http-server-internal/src/register_lifecycle_handlers.ts b/packages/core/http/core-http-server-internal/src/register_lifecycle_handlers.ts index 14561c5d94ef5..fac274af5a283 100644 --- a/packages/core/http/core-http-server-internal/src/register_lifecycle_handlers.ts +++ b/packages/core/http/core-http-server-internal/src/register_lifecycle_handlers.ts @@ -7,19 +7,22 @@ */ import type { Env } from '@kbn/config'; +import { Logger } from '@kbn/logging'; import type { HttpConfig } from './http_config'; import type { LifecycleRegistrar } from './http_server'; import { createCustomHeadersPreResponseHandler, createRestrictInternalRoutesPostAuthHandler, createVersionCheckPostAuthHandler, + createBuildNrMismatchLoggerPreResponseHandler, createXsrfPostAuthHandler, } from './lifecycle_handlers'; export const registerCoreHandlers = ( registrar: LifecycleRegistrar, config: HttpConfig, - env: Env + env: Env, + log: Logger ) => { // add headers based on config registrar.registerOnPreResponse(createCustomHeadersPreResponseHandler(config)); @@ -28,6 +31,10 @@ export const registerCoreHandlers = ( if (config.versioned.strictClientVersionCheck !== false) { // add check on version registrar.registerOnPostAuth(createVersionCheckPostAuthHandler(env.packageInfo.version)); + } else { + registrar.registerOnPreResponse( + createBuildNrMismatchLoggerPreResponseHandler(env.packageInfo.buildNum, log) + ); } // add check on header if the route is internal registrar.registerOnPostAuth(createRestrictInternalRoutesPostAuthHandler(config)); // strictly speaking, we should have access to route.options.access from the request on postAuth diff --git a/packages/core/http/core-http-server-mocks/src/test_utils.ts b/packages/core/http/core-http-server-mocks/src/test_utils.ts index a23fd54e9840e..1588f06056b8b 100644 --- a/packages/core/http/core-http-server-mocks/src/test_utils.ts +++ b/packages/core/http/core-http-server-mocks/src/test_utils.ts @@ -107,6 +107,19 @@ export const createCoreContext = (overrides: Partial = {}): CoreCon /** * Creates a concrete HttpServer with a mocked context. */ -export const createHttpServer = (overrides: Partial = {}): HttpService => { - return new HttpService(createCoreContext(overrides)); +export const createHttpServer = ({ + buildNum, + ...overrides +}: Partial = {}): HttpService => { + const ctx = createCoreContext(overrides); + if (buildNum !== undefined) { + ctx.env = { + ...ctx.env, + packageInfo: { + ...ctx.env.packageInfo, + buildNum, + }, + }; + } + return new HttpService(ctx); }; diff --git a/packages/core/saved-objects/core-saved-objects-server-internal/src/saved_objects_service.test.ts b/packages/core/saved-objects/core-saved-objects-server-internal/src/saved_objects_service.test.ts index 4369a85184262..5f53633b79c22 100644 --- a/packages/core/saved-objects/core-saved-objects-server-internal/src/saved_objects_service.test.ts +++ b/packages/core/saved-objects/core-saved-objects-server-internal/src/saved_objects_service.test.ts @@ -18,7 +18,7 @@ import { typeRegistryInstanceMock, applyTypeDefaultsMock, } from './saved_objects_service.test.mocks'; -import { BehaviorSubject, firstValueFrom } from 'rxjs'; +import { BehaviorSubject, firstValueFrom, EMPTY } from 'rxjs'; import { skip } from 'rxjs/operators'; import { type RawPackageInfo, Env } from '@kbn/config'; import { ByteSizeValue } from '@kbn/config-schema'; @@ -549,6 +549,24 @@ describe('SavedObjectsService', () => { expect(migratorInstanceMock.runMigrations).toHaveBeenCalledTimes(1); }); + it('does not start the migration if esNodesCompatibility$ is closed before calling `start`', async () => { + expect.assertions(2); + const coreContext = createCoreContext({ skipMigration: false }); + const soService = new SavedObjectsService(coreContext); + const setupDeps = createSetupDeps(); + // Create an new subject so that we can control when isCompatible=true + // is emitted. + setupDeps.elasticsearch.esNodesCompatibility$ = EMPTY; + await soService.setup(setupDeps); + await expect(() => + soService.start(createStartDeps()) + ).rejects.toThrowErrorMatchingInlineSnapshot( + `"esNodesCompatibility$ was closed before emitting"` + ); + + expect(migratorInstanceMock.runMigrations).not.toHaveBeenCalled(); + }); + it('resolves with KibanaMigrator after waiting for migrations to complete', async () => { const coreContext = createCoreContext({ skipMigration: false }); const soService = new SavedObjectsService(coreContext); 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 0efda4a5bce9b..f334603007b61 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 @@ -7,7 +7,7 @@ */ import { Subject, Observable, firstValueFrom, of } from 'rxjs'; -import { filter, take, switchMap } from 'rxjs/operators'; +import { filter, switchMap } from 'rxjs/operators'; import type { Logger } from '@kbn/logging'; import { stripVersionQualifier } from '@kbn/std'; import type { ServiceStatus } from '@kbn/core-status-common'; @@ -262,20 +262,25 @@ export class SavedObjectsService 'Waiting until all Elasticsearch nodes are compatible with Kibana before starting saved objects migrations...' ); - // The Elasticsearch service should already ensure that, but let's double check just in case. - // Should it be replaced with elasticsearch.status$ API instead? - const compatibleNodes = await this.setupDeps!.elasticsearch.esNodesCompatibility$.pipe( - filter((nodes) => nodes.isCompatible), - take(1) - ).toPromise(); - - // Running migrations only if we got compatible nodes. - // It may happen that the observable completes due to Kibana shutting down - // and the promise above fulfils as undefined. We shouldn't trigger migrations at that point. - if (compatibleNodes) { - this.logger.info('Starting saved objects migrations'); - await migrator.runMigrations(); + try { + // The Elasticsearch service should already ensure that, but let's double check just in case. + // Should it be replaced with elasticsearch.status$ API instead? + await firstValueFrom( + this.setupDeps!.elasticsearch.esNodesCompatibility$.pipe( + filter((nodes) => nodes.isCompatible) + ) + ); + } catch (e) { + // EmptyError means esNodesCompatibility$ was closed before emitting + // which should only occur if the server is shutdown before being fully started. + if (e.name === 'EmptyError') { + throw new Error('esNodesCompatibility$ was closed before emitting'); + } + throw e; } + + this.logger.info('Starting saved objects migrations'); + await migrator.runMigrations(); } const createRepository = ( diff --git a/packages/core/saved-objects/core-saved-objects-utils-server/src/saved_objects_utils.test.mock.ts b/packages/core/saved-objects/core-saved-objects-utils-server/src/saved_objects_utils.test.mock.ts index 34b6d5e7d7070..7f275e659e7b5 100644 --- a/packages/core/saved-objects/core-saved-objects-utils-server/src/saved_objects_utils.test.mock.ts +++ b/packages/core/saved-objects/core-saved-objects-utils-server/src/saved_objects_utils.test.mock.ts @@ -6,13 +6,13 @@ * Side Public License, v 1. */ -const mockUuidv1 = jest.fn().mockReturnValue('uuidv1'); +const mockUuidv4 = jest.fn().mockReturnValue('uuidv4'); const mockUuidv5 = jest.fn().mockReturnValue('uuidv5'); Object.defineProperty(mockUuidv5, 'DNS', { value: 'DNSUUID', writable: false }); jest.mock('uuid', () => ({ - v1: mockUuidv1, + v4: mockUuidv4, v5: mockUuidv5, })); -export { mockUuidv1, mockUuidv5 }; +export { mockUuidv4, mockUuidv5 }; diff --git a/packages/core/saved-objects/core-saved-objects-utils-server/src/saved_objects_utils.test.ts b/packages/core/saved-objects/core-saved-objects-utils-server/src/saved_objects_utils.test.ts index d2454abaac4fa..abe4fbba8e7b4 100644 --- a/packages/core/saved-objects/core-saved-objects-utils-server/src/saved_objects_utils.test.ts +++ b/packages/core/saved-objects/core-saved-objects-utils-server/src/saved_objects_utils.test.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { mockUuidv1, mockUuidv5 } from './saved_objects_utils.test.mock'; +import { mockUuidv4, mockUuidv5 } from './saved_objects_utils.test.mock'; import type { SavedObjectsFindOptions } from '@kbn/core-saved-objects-api-server'; import { SavedObjectsUtils } from './saved_objects_utils'; @@ -78,8 +78,8 @@ describe('SavedObjectsUtils', () => { describe('#generateId', () => { it('returns a valid uuid', () => { - expect(generateId()).toBe('uuidv1'); // default return value for mockUuidv1 - expect(mockUuidv1).toHaveBeenCalled(); + expect(generateId()).toBe('uuidv4'); // default return value for mockUuidv4 + expect(mockUuidv4).toHaveBeenCalled(); }); }); diff --git a/packages/core/saved-objects/core-saved-objects-utils-server/src/saved_objects_utils.ts b/packages/core/saved-objects/core-saved-objects-utils-server/src/saved_objects_utils.ts index badfb797292cc..c9213a1198ee3 100644 --- a/packages/core/saved-objects/core-saved-objects-utils-server/src/saved_objects_utils.ts +++ b/packages/core/saved-objects/core-saved-objects-utils-server/src/saved_objects_utils.ts @@ -7,7 +7,7 @@ */ import { isFunction } from 'lodash'; -import { v1 as uuidv1, v5 as uuidv5 } from 'uuid'; +import { v4 as uuidv4, v5 as uuidv5 } from 'uuid'; import type { SavedObjectsFindOptions, SavedObjectsFindResponse, @@ -70,7 +70,7 @@ export class SavedObjectsUtils { * Generates a random ID for a saved objects. */ public static generateId() { - return uuidv1(); + return uuidv4(); } /** diff --git a/packages/core/saved-objects/docs/openapi/bundled.json b/packages/core/saved-objects/docs/openapi/bundled.json index fcf9f7bf4d36e..dd6b95fa959b2 100644 --- a/packages/core/saved-objects/docs/openapi/bundled.json +++ b/packages/core/saved-objects/docs/openapi/bundled.json @@ -36,7 +36,7 @@ "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", + "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 work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features.\n", "tags": [ "saved objects" ], @@ -386,7 +386,7 @@ "post": { "summary": "Retrieve sets of saved objects that you want to import into Kibana.", "operationId": "exportSavedObjects", - "description": "\nYou must include `type` or `objects` in the request body.\n\nNOTE: The `savedObjects.maxImportExportSize` configuration setting limits the number of saved objects which may be exported.\n\nThis functionality is in technical preview and may be changed or removed in a future release. Elastic will apply best effort to fix any issues, but features in technical preview are not subject to the support SLA of official GA features.\n", + "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 work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features.\n", "tags": [ "saved objects" ], @@ -644,7 +644,7 @@ "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", + "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 work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features.\n", "tags": [ "saved objects" ], @@ -757,7 +757,7 @@ "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", + "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 work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features.\n", "tags": [ "saved objects" ], diff --git a/packages/core/saved-objects/docs/openapi/bundled.yaml b/packages/core/saved-objects/docs/openapi/bundled.yaml index a381f044954db..3e07633a5107b 100644 --- a/packages/core/saved-objects/docs/openapi/bundled.yaml +++ b/packages/core/saved-objects/docs/openapi/bundled.yaml @@ -26,7 +26,7 @@ paths: 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. + This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. tags: - saved objects parameters: @@ -208,7 +208,7 @@ paths: 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. + 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: @@ -239,7 +239,7 @@ paths: 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. + 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: @@ -260,7 +260,7 @@ paths: 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. + This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. tags: - saved objects parameters: @@ -419,7 +419,7 @@ paths: 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. + This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. tags: - saved objects parameters: @@ -503,13 +503,13 @@ paths: summary: Resolve errors from the Import objects API. operationId: resolveImportErrors description: | - To resolve errors, you can: + 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. + This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. tags: - saved objects parameters: diff --git a/packages/core/saved-objects/docs/openapi/paths/api@encrypted_saved_objects@_rotate_key.yaml b/packages/core/saved-objects/docs/openapi/paths/api@encrypted_saved_objects@_rotate_key.yaml index 91b75b8ba0a05..a863358622e3e 100644 --- a/packages/core/saved-objects/docs/openapi/paths/api@encrypted_saved_objects@_rotate_key.yaml +++ b/packages/core/saved-objects/docs/openapi/paths/api@encrypted_saved_objects@_rotate_key.yaml @@ -6,7 +6,7 @@ post: 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. + This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. tags: - saved objects parameters: 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 3a4b78b91acf5..ad6817b5e2ebf 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,13 +1,13 @@ post: summary: Retrieve sets of saved objects that you want to import into Kibana. operationId: exportSavedObjects - description: | + 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. + This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. tags: - saved objects parameters: 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 1f7b78c95b784..c1df23e8d11e0 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 @@ -3,8 +3,8 @@ post: 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. - - 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. + + This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. tags: - saved objects parameters: @@ -64,7 +64,7 @@ post: 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 @@ -72,7 +72,7 @@ post: 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: diff --git a/packages/core/saved-objects/docs/openapi/paths/api@saved_objects@_resolve_import_errors.yaml b/packages/core/saved-objects/docs/openapi/paths/api@saved_objects@_resolve_import_errors.yaml index 09046320804c4..aa64b0f3b08af 100644 --- a/packages/core/saved-objects/docs/openapi/paths/api@saved_objects@_resolve_import_errors.yaml +++ b/packages/core/saved-objects/docs/openapi/paths/api@saved_objects@_resolve_import_errors.yaml @@ -2,13 +2,13 @@ post: summary: Resolve errors from the Import objects API. operationId: resolveImportErrors description: | - To resolve errors, you can: - + 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. + + This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. tags: - saved objects parameters: @@ -34,7 +34,7 @@ post: schema: type: object required: - - retries + - retries properties: file: description: The same file given to the import API. @@ -47,7 +47,7 @@ post: type: object required: - type - - id + - id properties: type: description: The saved object type. diff --git a/packages/kbn-check-mappings-update-cli/current_mappings.json b/packages/kbn-check-mappings-update-cli/current_mappings.json index 37e8e2fec4115..d2fde2f5a10a8 100644 --- a/packages/kbn-check-mappings-update-cli/current_mappings.json +++ b/packages/kbn-check-mappings-update-cli/current_mappings.json @@ -1680,6 +1680,10 @@ "type": "keyword", "index": false }, + "service_token": { + "type": "keyword", + "index": false + }, "config": { "type": "flattened" }, diff --git a/packages/kbn-config-schema/src/types/string_type.test.ts b/packages/kbn-config-schema/src/types/string_type.test.ts index 8fa1dcfc1944a..d07b52983d88c 100644 --- a/packages/kbn-config-schema/src/types/string_type.test.ts +++ b/packages/kbn-config-schema/src/types/string_type.test.ts @@ -22,6 +22,16 @@ test('is required by default', () => { ); }); +test('reject numeric values if `coerceFromNumber` is unspecified', () => { + expect(() => schema.string({}).validate(1234)).toThrowErrorMatchingInlineSnapshot( + `"expected value of type [string] but got [number]"` + ); +}); + +test('coerce numeric values if `coerceFromNumber` is `true`', () => { + expect(schema.string({ coerceFromNumber: true }).validate(1234)).toBe('1234'); +}); + test('includes namespace in failure', () => { expect(() => schema.string().validate(undefined, {}, 'foo-namespace') diff --git a/packages/kbn-config-schema/src/types/string_type.ts b/packages/kbn-config-schema/src/types/string_type.ts index f2792e4031e0a..e5251013e3a7e 100644 --- a/packages/kbn-config-schema/src/types/string_type.ts +++ b/packages/kbn-config-schema/src/types/string_type.ts @@ -14,6 +14,7 @@ export type StringOptions = TypeOptions & { minLength?: number; maxLength?: number; hostname?: boolean; + coerceFromNumber?: boolean; }; export class StringType extends Type { @@ -25,14 +26,17 @@ export class StringType extends Type { let schema = options.hostname === true ? internals.string().hostname() - : internals.any().custom( - convertValidationFunction((value) => { - if (typeof value !== 'string') { - return `expected value of type [string] but got [${typeDetect(value)}]`; + : internals.any().custom((value, { error }) => { + if (typeof value !== 'string') { + if (options.coerceFromNumber && typeof value === 'number') { + return value.toString(10); } - }) - ); - + return error('any.custom', { + message: `expected value of type [string] but got [${typeDetect(value)}]`, + }); + } + return value; + }); if (options.minLength !== undefined) { schema = schema.custom( convertValidationFunction((value) => { diff --git a/packages/kbn-es/src/serverless_resources/roles.yml b/packages/kbn-es/src/serverless_resources/roles.yml index 5777f282ff7a4..5f968ece56e3a 100644 --- a/packages/kbn-es/src/serverless_resources/roles.yml +++ b/packages/kbn-es/src/serverless_resources/roles.yml @@ -117,7 +117,7 @@ t1_analyst: - metrics-endpoint.metadata_current_* - ".fleet-agents*" - ".fleet-actions*" - - "risk-score.risk-score-*" + - risk-score.risk-score-* privileges: - read applications: @@ -128,10 +128,17 @@ t1_analyst: - feature_siem.read_alerts - feature_siem.endpoint_list_read - feature_securitySolutionCases.read + - feature_securitySolutionAssistant.all - feature_actions.read - feature_builtInAlerts.read - feature_osquery.read - feature_osquery.run_saved_queries + - feature_discover.all + - feature_dashboard.all + - feature_canvas.all + - feature_graph.all + - feature_maps.all + - feature_visualize.all resources: "*" t2_analyst: @@ -158,7 +165,7 @@ t2_analyst: - metrics-endpoint.metadata_current_* - .fleet-agents* - .fleet-actions* - - "risk-score.risk-score-*" + - risk-score.risk-score-* privileges: - read applications: @@ -169,10 +176,17 @@ t2_analyst: - feature_siem.read_alerts - feature_siem.endpoint_list_read - feature_securitySolutionCases.all + - feature_securitySolutionAssistant.all - feature_actions.read - feature_builtInAlerts.read - feature_osquery.read - feature_osquery.run_saved_queries + - feature_discover.all + - feature_dashboard.all + - feature_canvas.all + - feature_graph.all + - feature_maps.all + - feature_visualize.all resources: "*" t3_analyst: @@ -206,7 +220,7 @@ t3_analyst: - metrics-endpoint.metadata_current_* - .fleet-agents* - .fleet-actions* - - "risk-score.risk-score-*" + - risk-score.risk-score-* privileges: - read applications: @@ -227,9 +241,16 @@ t3_analyst: - feature_siem.actions_log_management_all # Response actions history - feature_siem.file_operations_all - feature_securitySolutionCases.all + - feature_securitySolutionAssistant.all - feature_actions.read - feature_builtInAlerts.all - feature_osquery.all + - feature_discover.all + - feature_dashboard.all + - feature_canvas.all + - feature_graph.all + - feature_maps.all + - feature_visualize.all resources: "*" threat_intelligence_analyst: @@ -259,7 +280,7 @@ threat_intelligence_analyst: - metrics-endpoint.metadata_current_* - .fleet-agents* - .fleet-actions* - - "risk-score.risk-score-*" + - risk-score.risk-score-* privileges: - read applications: @@ -271,9 +292,16 @@ threat_intelligence_analyst: - feature_siem.endpoint_list_read - feature_siem.blocklist_all - feature_securitySolutionCases.all + - feature_securitySolutionAssistant.all - feature_actions.read - feature_builtInAlerts.read - feature_osquery.all + - feature_discover.all + - feature_dashboard.all + - feature_canvas.all + - feature_graph.all + - feature_maps.all + - feature_visualize.all resources: "*" rule_author: @@ -311,7 +339,7 @@ rule_author: - metrics-endpoint.metadata_current_* - .fleet-agents* - .fleet-actions* - - "risk-score.risk-score-*" + - risk-score.risk-score-* privileges: - read applications: @@ -329,9 +357,16 @@ rule_author: - feature_siem.blocklist_all # Elastic Defend Policy Management - feature_siem.actions_log_management_read - feature_securitySolutionCases.all + - feature_securitySolutionAssistant.all - feature_actions.read - feature_builtInAlerts.all - feature_osquery.all + - feature_discover.all + - feature_dashboard.all + - feature_canvas.all + - feature_graph.all + - feature_maps.all + - feature_visualize.all resources: "*" soc_manager: @@ -390,10 +425,17 @@ soc_manager: - feature_siem.file_operations_all - feature_siem.execute_operations_all - feature_securitySolutionCases.all + - feature_securitySolutionAssistant.all - feature_actions.all - feature_builtInAlerts.all - feature_osquery.all - - feature_indexPatterns.all # Detections Data Views + - feature_indexPatterns.all + - feature_discover.all + - feature_dashboard.all + - feature_canvas.all + - feature_graph.all + - feature_maps.all + - feature_visualize.all resources: "*" detections_admin: @@ -436,9 +478,16 @@ detections_admin: - feature_siem.read_alerts - feature_siem.crud_alerts - feature_securitySolutionCases.all + - feature_securitySolutionAssistant.all - feature_actions.all - feature_builtInAlerts.all - feature_dev_tools.all + - feature_discover.all + - feature_dashboard.all + - feature_canvas.all + - feature_graph.all + - feature_maps.all + - feature_visualize.all resources: "*" platform_engineer: @@ -478,12 +527,19 @@ platform_engineer: - feature_siem.blocklist_all # Elastic Defend Policy Management - feature_siem.actions_log_management_read - feature_securitySolutionCases.all + - feature_securitySolutionAssistant.all - feature_actions.all - feature_builtInAlerts.all - feature_fleet.all - feature_fleetv2.all - feature_osquery.all - - feature_indexPatterns.all # Detections Data Views + - feature_indexPatterns.all + - feature_discover.all + - feature_dashboard.all + - feature_canvas.all + - feature_graph.all + - feature_maps.all + - feature_visualize.all resources: "*" endpoint_operations_analyst: @@ -493,7 +549,6 @@ endpoint_operations_analyst: - metrics-endpoint.metadata_current_* - .fleet-agents* - .fleet-actions* - - risk-score.risk-score-* privileges: - read - names: @@ -507,6 +562,7 @@ endpoint_operations_analyst: - winlogbeat-* - .lists* - .items* + - risk-score.risk-score-* privileges: - read - names: @@ -535,11 +591,18 @@ endpoint_operations_analyst: - feature_siem.file_operations_all - feature_siem.execute_operations_all # Execute - feature_securitySolutionCases.all + - feature_securitySolutionAssistant.all - feature_actions.all - feature_builtInAlerts.all - feature_osquery.all - feature_fleet.all - feature_fleetv2.all + - feature_discover.all + - feature_dashboard.all + - feature_canvas.all + - feature_graph.all + - feature_maps.all + - feature_visualize.all resources: "*" endpoint_policy_manager: @@ -549,7 +612,6 @@ endpoint_policy_manager: - metrics-endpoint.metadata_current_* - .fleet-agents* - .fleet-actions* - - risk-score.risk-score-* privileges: - read - names: @@ -563,6 +625,7 @@ endpoint_policy_manager: - winlogbeat-* - .lists* - .items* + - risk-score.risk-score-* privileges: - read - names: @@ -588,9 +651,16 @@ endpoint_policy_manager: - feature_siem.host_isolation_exceptions_all - feature_siem.blocklist_all # Elastic Defend Policy Management - feature_securitySolutionCases.all + - feature_securitySolutionAssistant.all - feature_actions.all - feature_builtInAlerts.all - feature_osquery.all - feature_fleet.all - feature_fleetv2.all + - feature_discover.all + - feature_dashboard.all + - feature_canvas.all + - feature_graph.all + - feature_maps.all + - feature_visualize.all resources: "*" diff --git a/packages/kbn-management/settings/setting_ids/index.ts b/packages/kbn-management/settings/setting_ids/index.ts index 1ef2c6b223df4..31db42d321d2d 100644 --- a/packages/kbn-management/settings/setting_ids/index.ts +++ b/packages/kbn-management/settings/setting_ids/index.ts @@ -163,6 +163,10 @@ export const SECURITY_SOLUTION_IP_REPUTATION_LINKS_ID = 'securitySolution:ipRepu export const SECURITY_SOLUTION_ENABLE_CCS_WARNING_ID = 'securitySolution:enableCcsWarning'; export const SECURITY_SOLUTION_SHOW_RELATED_INTEGRATIONS_ID = 'securitySolution:showRelatedIntegrations'; +export const SECURITY_SOLUTION_DEFAULT_ALERT_TAGS_KEY = 'securitySolution:alertTags' as const; +/** This Kibana Advanced Setting allows users to enable/disable the Expandable Flyout */ +export const SECURITY_SOLUTION_ENABLE_EXPANDABLE_FLYOUT_SETTING = + 'securitySolution:enableExpandableFlyout' as const; // Timelion settings export const TIMELION_ES_DEFAULT_INDEX_ID = 'timelion:es.default_index'; diff --git a/packages/kbn-optimizer/limits.yml b/packages/kbn-optimizer/limits.yml index 02a7b89621f58..de07bccf8bbcb 100644 --- a/packages/kbn-optimizer/limits.yml +++ b/packages/kbn-optimizer/limits.yml @@ -94,6 +94,7 @@ pageLoadAssetSize: management: 46112 maps: 90000 mapsEms: 26072 + metricsDataAccess: 60000 ml: 82187 monitoring: 80000 navigation: 37269 diff --git a/packages/kbn-optimizer/src/worker/webpack.config.ts b/packages/kbn-optimizer/src/worker/webpack.config.ts index 986ec051637e4..189ca29072afe 100644 --- a/packages/kbn-optimizer/src/worker/webpack.config.ts +++ b/packages/kbn-optimizer/src/worker/webpack.config.ts @@ -15,7 +15,6 @@ import webpack from 'webpack'; import TerserPlugin from 'terser-webpack-plugin'; import webpackMerge from 'webpack-merge'; import { CleanWebpackPlugin } from 'clean-webpack-plugin'; -import CompressionPlugin from 'compression-webpack-plugin'; import UiSharedDepsNpm from '@kbn/ui-shared-deps-npm'; import * as UiSharedDepsSrc from '@kbn/ui-shared-deps-src'; @@ -271,15 +270,6 @@ export function getWebpackConfig( IS_KIBANA_DISTRIBUTABLE: `"true"`, }, }), - new CompressionPlugin({ - algorithm: 'brotliCompress', - filename: '[path].br', - test: /\.(js|css)$/, - cache: false, - compressionOptions: { - level: 11, - }, - }), ], optimization: { diff --git a/packages/kbn-plugin-helpers/src/cli.ts b/packages/kbn-plugin-helpers/src/cli.ts index 96da79f75d6c8..21f183dea5e4a 100644 --- a/packages/kbn-plugin-helpers/src/cli.ts +++ b/packages/kbn-plugin-helpers/src/cli.ts @@ -87,6 +87,7 @@ export function runCli() { await Tasks.initTargets(context); await Tasks.buildBazelPackages(context); await Tasks.optimize(context); + await Tasks.brotliCompressBundles(context); await Tasks.writePublicAssets(context); await Tasks.writeServerFiles(context); await Tasks.yarnInstall(context); 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 7a3cf7f85ddf2..e7a5db404c5ca 100644 --- a/packages/kbn-plugin-helpers/src/integration_tests/build.test.ts +++ b/packages/kbn-plugin-helpers/src/integration_tests/build.test.ts @@ -81,6 +81,7 @@ it('builds a generated plugin into a viable archive', async () => { info running @kbn/optimizer │ succ browser bundle created at plugins/foo_test_plugin/build/kibana/fooTestPlugin/target/public │ info stopping @kbn/optimizer + info compressing js and css bundles found at plugins/foo_test_plugin/build/kibana/fooTestPlugin/target/public to brotli info copying assets from \`public/assets\` to build info copying server source into the build and converting with babel info running yarn to install dependencies diff --git a/packages/kbn-plugin-helpers/src/tasks/brotli_compress_bundles.ts b/packages/kbn-plugin-helpers/src/tasks/brotli_compress_bundles.ts new file mode 100644 index 0000000000000..f04d707b279e9 --- /dev/null +++ b/packages/kbn-plugin-helpers/src/tasks/brotli_compress_bundles.ts @@ -0,0 +1,44 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import Path from 'path'; +import { pipeline } from 'stream'; +import { promisify } from 'util'; + +import vfs from 'vinyl-fs'; +import del from 'del'; +import gulpBrotli from 'gulp-brotli'; +import zlib from 'zlib'; +import { REPO_ROOT } from '@kbn/repo-info'; + +import { TaskContext } from '../task_context'; + +const asyncPipeline = promisify(pipeline); + +export async function brotliCompressBundles({ buildDir, log }: TaskContext) { + const compressDir = Path.resolve(buildDir, 'target/public'); + + log.info( + `compressing js and css bundles found at ${Path.relative(REPO_ROOT, compressDir)} to brotli` + ); + + try { + await del(['**/*.br'], { cwd: compressDir }); + await asyncPipeline( + vfs.src(['**/*.{js,css}'], { cwd: compressDir }), + gulpBrotli({ + params: { + [zlib.constants.BROTLI_PARAM_QUALITY]: zlib.constants.BROTLI_MAX_QUALITY, + }, + }), + vfs.dest(compressDir) + ); + } catch (e) { + log.error(e); + } +} diff --git a/packages/kbn-plugin-helpers/src/tasks/create_archive.ts b/packages/kbn-plugin-helpers/src/tasks/create_archive.ts index 5f2339d2a4ce1..999bb559c6dbe 100644 --- a/packages/kbn-plugin-helpers/src/tasks/create_archive.ts +++ b/packages/kbn-plugin-helpers/src/tasks/create_archive.ts @@ -7,17 +7,13 @@ */ import Path from 'path'; -import { pipeline } from 'stream'; -import { promisify } from 'util'; +import Fs from 'fs'; +import archiver from 'archiver'; import del from 'del'; -import vfs from 'vinyl-fs'; -import zip from 'gulp-zip'; import { TaskContext } from '../task_context'; -const asyncPipeline = promisify(pipeline); - export async function createArchive({ kibanaVersion, plugin, log }: TaskContext) { const { manifest: { id }, @@ -30,15 +26,14 @@ export async function createArchive({ kibanaVersion, plugin, log }: TaskContext) const buildDir = Path.resolve(directory, 'build'); // zip up the build files - await asyncPipeline( - vfs.src([`kibana/${id}/**/*`], { - cwd: buildDir, - base: buildDir, - dot: true, - }), - zip(zipName), - vfs.dest(buildDir) - ); + const output = Fs.createWriteStream(Path.resolve(buildDir, zipName)); + const archive = archiver('zip', { zlib: { level: 9 } }); + archive.pipe(output); + + const directoryToAdd = Path.resolve(buildDir, 'kibana'); + const directoryNameOnZip = Path.basename(directoryToAdd); + + await archive.directory(directoryToAdd, directoryNameOnZip).finalize(); // delete the files that were zipped await del(Path.resolve(buildDir, 'kibana')); diff --git a/packages/kbn-plugin-helpers/src/tasks/index.ts b/packages/kbn-plugin-helpers/src/tasks/index.ts index ab23a501ca14c..cc788a4ccfa35 100644 --- a/packages/kbn-plugin-helpers/src/tasks/index.ts +++ b/packages/kbn-plugin-helpers/src/tasks/index.ts @@ -7,6 +7,7 @@ */ export * from './bazel_packages'; +export * from './brotli_compress_bundles'; export * from './clean'; export * from './create_archive'; export * from './optimize'; diff --git a/packages/kbn-profiling-utils/common/callee.ts b/packages/kbn-profiling-utils/common/callee.ts index 9315548b81ef3..63152d91de3f1 100644 --- a/packages/kbn-profiling-utils/common/callee.ts +++ b/packages/kbn-profiling-utils/common/callee.ts @@ -6,6 +6,7 @@ * Side Public License, v 1. */ +import { sum } from 'lodash'; import { createFrameGroupID, FrameGroupID } from './frame_group'; import { emptyExecutable, @@ -51,6 +52,9 @@ export interface CalleeTree { CountInclusive: number[]; /** self cpu */ CountExclusive: number[]; + TotalSamples: number; + TotalCPU: number; + SelfCPU: number; } /** @@ -83,14 +87,17 @@ export function createCalleeTree( FunctionOffset: new Array(totalFrames), SourceFilename: new Array(totalFrames), SourceLine: new Array(totalFrames), - CountInclusive: new Array(totalFrames), CountExclusive: new Array(totalFrames), + TotalSamples: 0, + SelfCPU: 0, + TotalCPU: 0, }; // The inverse of the sampling rate is the number with which to multiply the number of // samples to get an estimate of the actual number of samples the backend received. const scalingFactor = 1.0 / samplingRate; + let totalSamples = 0; tree.Edges[0] = new Map(); tree.FileID[0] = ''; @@ -127,7 +134,7 @@ export function createCalleeTree( const stackTrace = stackTraces.get(stackTraceID) ?? emptyStackTrace; const lenStackTrace = stackTrace.FrameIDs.length; const samples = Math.floor((events.get(stackTraceID) ?? 0) * scalingFactor); - + totalSamples += samples; let currentNode = 0; // Increment the count by the number of samples observed, multiplied with the inverse of the @@ -182,6 +189,13 @@ export function createCalleeTree( currentNode = node; } } - - return tree; + const sumSelfCPU = sum(tree.CountExclusive); + const sumTotalCPU = sum(tree.CountInclusive); + + return { + ...tree, + TotalSamples: totalSamples, + SelfCPU: sumSelfCPU, + TotalCPU: sumTotalCPU, + }; } diff --git a/packages/kbn-profiling-utils/common/flamegraph.ts b/packages/kbn-profiling-utils/common/flamegraph.ts index 20dc5419d6230..0961e02bfd1ab 100644 --- a/packages/kbn-profiling-utils/common/flamegraph.ts +++ b/packages/kbn-profiling-utils/common/flamegraph.ts @@ -45,6 +45,9 @@ export interface BaseFlameGraph { TotalSeconds: number; /** sampling rate */ SamplingRate: number; + TotalSamples: number; + TotalCPU: number; + SelfCPU: number; } /** @@ -78,6 +81,9 @@ export function createBaseFlameGraph( CountExclusive: tree.CountExclusive.slice(0, tree.Size), TotalSeconds: totalSeconds, + TotalSamples: tree.TotalSamples, + SelfCPU: tree.SelfCPU, + TotalCPU: tree.TotalCPU, }; for (let i = 0; i < tree.Size; i++) { @@ -132,6 +138,9 @@ export function createFlameGraph(base: BaseFlameGraph): ElasticFlameGraph { Label: new Array(base.Size), TotalSeconds: base.TotalSeconds, + TotalSamples: base.TotalSamples, + SelfCPU: base.SelfCPU, + TotalCPU: base.TotalCPU, }; const rootFrameGroupID = createFrameGroupID( diff --git a/packages/kbn-rule-data-utils/src/rule_types/o11y_rules.ts b/packages/kbn-rule-data-utils/src/rule_types/o11y_rules.ts index 86c5ef3f2e646..b88e0f708a980 100644 --- a/packages/kbn-rule-data-utils/src/rule_types/o11y_rules.ts +++ b/packages/kbn-rule-data-utils/src/rule_types/o11y_rules.ts @@ -7,3 +7,10 @@ */ export const OBSERVABILITY_THRESHOLD_RULE_TYPE_ID = 'observability.rules.custom_threshold'; + +export enum ApmRuleType { + ErrorCount = 'apm.error_rate', // ErrorRate was renamed to ErrorCount but the key is kept as `error_rate` for backwards-compat. + TransactionErrorRate = 'apm.transaction_error_rate', + TransactionDuration = 'apm.transaction_duration', + Anomaly = 'apm.anomaly', +} diff --git a/packages/kbn-search-connectors/types/native_connectors.ts b/packages/kbn-search-connectors/types/native_connectors.ts index 4c7648e43f5b0..d815c40eb435b 100644 --- a/packages/kbn-search-connectors/types/native_connectors.ts +++ b/packages/kbn-search-connectors/types/native_connectors.ts @@ -450,7 +450,12 @@ export const NATIVE_CONNECTOR_DEFINITIONS: Record void; + inspect?: boolean; }) { const { config, procs } = options; const runOptions = options.config.get('kbnTestServer.runOptions'); @@ -51,6 +52,10 @@ export async function runKibanaServer(options: { ? [Path.relative(procRunnerOpts.cwd, Path.resolve(REPO_ROOT, 'scripts/kibana'))] : []; + if (options.inspect) { + prefixArgs.unshift('--inspect'); + } + const buildArgs: string[] = config.get('kbnTestServer.buildArgs') || []; const sourceArgs: string[] = config.get('kbnTestServer.sourceArgs') || []; const serverArgs: string[] = config.get('kbnTestServer.serverArgs') || []; diff --git a/packages/kbn-unified-data-table/src/hooks/use_row_heights_options.ts b/packages/kbn-unified-data-table/src/hooks/use_row_heights_options.ts index 55eaa17c2c2ea..3df1a31aaa9d3 100644 --- a/packages/kbn-unified-data-table/src/hooks/use_row_heights_options.ts +++ b/packages/kbn-unified-data-table/src/hooks/use_row_heights_options.ts @@ -34,6 +34,8 @@ const serializeRowHeight = (rowHeight?: EuiDataGridRowHeightOption): number => { return ROWS_HEIGHT_OPTIONS.auto; } else if (typeof rowHeight === 'object' && rowHeight.lineCount) { return rowHeight.lineCount; // custom + } else if (typeof rowHeight === 'number') { + return rowHeight; } return ROWS_HEIGHT_OPTIONS.single; diff --git a/packages/serverless/settings/security_project/index.ts b/packages/serverless/settings/security_project/index.ts index 3a3ed2addf9f4..276a1e87e4b7e 100644 --- a/packages/serverless/settings/security_project/index.ts +++ b/packages/serverless/settings/security_project/index.ts @@ -22,4 +22,6 @@ export const SECURITY_PROJECT_SETTINGS = [ settings.SECURITY_SOLUTION_SHOW_RELATED_INTEGRATIONS_ID, settings.SECURITY_SOLUTION_NEWS_FEED_URL_ID, settings.SECURITY_SOLUTION_ENABLE_NEWS_FEED_ID, + settings.SECURITY_SOLUTION_DEFAULT_ALERT_TAGS_KEY, + settings.SECURITY_SOLUTION_ENABLE_EXPANDABLE_FLYOUT_SETTING, ]; diff --git a/packages/shared-ux/button/exit_full_screen/impl/README.mdx b/packages/shared-ux/button/exit_full_screen/README.mdx similarity index 100% rename from packages/shared-ux/button/exit_full_screen/impl/README.mdx rename to packages/shared-ux/button/exit_full_screen/README.mdx diff --git a/packages/shared-ux/button/exit_full_screen/impl/index.tsx b/packages/shared-ux/button/exit_full_screen/index.tsx similarity index 66% rename from packages/shared-ux/button/exit_full_screen/impl/index.tsx rename to packages/shared-ux/button/exit_full_screen/index.tsx index a003b3b240f67..dcbd0b7285cf8 100644 --- a/packages/shared-ux/button/exit_full_screen/impl/index.tsx +++ b/packages/shared-ux/button/exit_full_screen/index.tsx @@ -6,6 +6,6 @@ * Side Public License, v 1. */ -export { ExitFullScreenButtonKibanaProvider, ExitFullScreenButtonProvider } from './src/services'; -export { ExitFullScreenButton as ExitFullScreenButtonComponent } from './src/exit_full_screen_button.component'; +export { ExitFullScreenButtonKibanaProvider } from './src/services'; export { ExitFullScreenButton } from './src/exit_full_screen_button'; +export type { ExitFullScreenButtonProps, ExitFullScreenButtonKibanaDependencies } from './types'; diff --git a/packages/shared-ux/button/exit_full_screen/impl/jest.config.js b/packages/shared-ux/button/exit_full_screen/jest.config.js similarity index 79% rename from packages/shared-ux/button/exit_full_screen/impl/jest.config.js rename to packages/shared-ux/button/exit_full_screen/jest.config.js index 11baf1e4ebc6d..a9c3d2e1afb48 100644 --- a/packages/shared-ux/button/exit_full_screen/impl/jest.config.js +++ b/packages/shared-ux/button/exit_full_screen/jest.config.js @@ -8,6 +8,6 @@ module.exports = { preset: '@kbn/test', - rootDir: '../../../../..', - roots: ['/packages/shared-ux/button/exit_full_screen/impl'], + rootDir: '../../../..', + roots: ['/packages/shared-ux/button/exit_full_screen'], }; diff --git a/packages/shared-ux/button/exit_full_screen/impl/kibana.jsonc b/packages/shared-ux/button/exit_full_screen/kibana.jsonc similarity index 100% rename from packages/shared-ux/button/exit_full_screen/impl/kibana.jsonc rename to packages/shared-ux/button/exit_full_screen/kibana.jsonc diff --git a/packages/shared-ux/button/exit_full_screen/mocks/README.md b/packages/shared-ux/button/exit_full_screen/mocks/README.md deleted file mode 100644 index a868c7d146ed1..0000000000000 --- a/packages/shared-ux/button/exit_full_screen/mocks/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# @kbn/shared-ux-button-exit-full-screen-mocks - -TODO: clintandrewhall diff --git a/packages/shared-ux/button/exit_full_screen/mocks/index.ts b/packages/shared-ux/button/exit_full_screen/mocks/index.ts index 458c17f1b9eab..76a0892f7fd2e 100644 --- a/packages/shared-ux/button/exit_full_screen/mocks/index.ts +++ b/packages/shared-ux/button/exit_full_screen/mocks/index.ts @@ -9,7 +9,7 @@ export { getKibanaDependenciesMock as getExitFullScreenButtonKibanaDependenciesMock, getServicesMock as getExitFullScreenButtonServicesMock, -} from './src/jest'; +} from './jest'; -export { StorybookMock as ExitFullScreenButtonStorybookMock } from './src/storybook'; -export type { Params as ExitFullScreenButtonStorybookParams } from './src/storybook'; +export { StorybookMock as ExitFullScreenButtonStorybookMock } from './storybook'; +export type { Params as ExitFullScreenButtonStorybookParams } from './storybook'; diff --git a/packages/shared-ux/button/exit_full_screen/mocks/src/jest.ts b/packages/shared-ux/button/exit_full_screen/mocks/jest.ts similarity index 94% rename from packages/shared-ux/button/exit_full_screen/mocks/src/jest.ts rename to packages/shared-ux/button/exit_full_screen/mocks/jest.ts index 917595d441d6e..4e92c0ad1a7a2 100644 --- a/packages/shared-ux/button/exit_full_screen/mocks/src/jest.ts +++ b/packages/shared-ux/button/exit_full_screen/mocks/jest.ts @@ -6,11 +6,11 @@ * Side Public License, v 1. */ -import { +import { of } from 'rxjs'; +import type { ExitFullScreenButtonKibanaDependencies, ExitFullScreenButtonServices, -} from '@kbn/shared-ux-button-exit-full-screen-types'; -import { of } from 'rxjs'; +} from '../types'; /** * Return a Jest mock of the services for the `ExitFullScreenButton` component. diff --git a/packages/shared-ux/button/exit_full_screen/mocks/kibana.jsonc b/packages/shared-ux/button/exit_full_screen/mocks/kibana.jsonc deleted file mode 100644 index 1c21ffbc91c7c..0000000000000 --- a/packages/shared-ux/button/exit_full_screen/mocks/kibana.jsonc +++ /dev/null @@ -1,5 +0,0 @@ -{ - "type": "shared-common", - "id": "@kbn/shared-ux-button-exit-full-screen-mocks", - "owner": "@elastic/appex-sharedux" -} diff --git a/packages/shared-ux/button/exit_full_screen/mocks/package.json b/packages/shared-ux/button/exit_full_screen/mocks/package.json deleted file mode 100644 index bcda1669c6f1d..0000000000000 --- a/packages/shared-ux/button/exit_full_screen/mocks/package.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "name": "@kbn/shared-ux-button-exit-full-screen-mocks", - "private": true, - "version": "1.0.0", - "license": "SSPL-1.0 OR Elastic License 2.0" -} \ No newline at end of file diff --git a/packages/shared-ux/button/exit_full_screen/mocks/src/storybook.ts b/packages/shared-ux/button/exit_full_screen/mocks/storybook.ts similarity index 91% rename from packages/shared-ux/button/exit_full_screen/mocks/src/storybook.ts rename to packages/shared-ux/button/exit_full_screen/mocks/storybook.ts index 5393b333a5f81..c892b3dc9f939 100644 --- a/packages/shared-ux/button/exit_full_screen/mocks/src/storybook.ts +++ b/packages/shared-ux/button/exit_full_screen/mocks/storybook.ts @@ -8,11 +8,8 @@ import { action } from '@storybook/addon-actions'; import { AbstractStorybookMock, ArgumentParams } from '@kbn/shared-ux-storybook-mock'; -import type { - ExitFullScreenButtonProps as Props, - ExitFullScreenButtonServices, -} from '@kbn/shared-ux-button-exit-full-screen-types'; import { of } from 'rxjs'; +import type { ExitFullScreenButtonProps as Props, ExitFullScreenButtonServices } from '../types'; type PropArguments = Pick; diff --git a/packages/shared-ux/button/exit_full_screen/mocks/tsconfig.json b/packages/shared-ux/button/exit_full_screen/mocks/tsconfig.json deleted file mode 100644 index fbc11adc95523..0000000000000 --- a/packages/shared-ux/button/exit_full_screen/mocks/tsconfig.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "extends": "../../../../../tsconfig.base.json", - "compilerOptions": { - "outDir": "target/types", - "types": [ - "jest", - "node", - "react" - ] - }, - "include": [ - "**/*.ts" - ], - "kbn_references": [ - "@kbn/shared-ux-button-exit-full-screen-types", - "@kbn/shared-ux-storybook-mock" - ], - "exclude": [ - "target/**/*", - ] -} diff --git a/packages/shared-ux/button/exit_full_screen/impl/package.json b/packages/shared-ux/button/exit_full_screen/package.json similarity index 100% rename from packages/shared-ux/button/exit_full_screen/impl/package.json rename to packages/shared-ux/button/exit_full_screen/package.json diff --git a/packages/shared-ux/button/exit_full_screen/impl/src/__snapshots__/exit_full_screen_button.test.tsx.snap b/packages/shared-ux/button/exit_full_screen/src/__snapshots__/exit_full_screen_button.test.tsx.snap similarity index 100% rename from packages/shared-ux/button/exit_full_screen/impl/src/__snapshots__/exit_full_screen_button.test.tsx.snap rename to packages/shared-ux/button/exit_full_screen/src/__snapshots__/exit_full_screen_button.test.tsx.snap diff --git a/packages/shared-ux/button/exit_full_screen/impl/src/exit_full_screen_button.component.tsx b/packages/shared-ux/button/exit_full_screen/src/exit_full_screen_button.component.tsx similarity index 98% rename from packages/shared-ux/button/exit_full_screen/impl/src/exit_full_screen_button.component.tsx rename to packages/shared-ux/button/exit_full_screen/src/exit_full_screen_button.component.tsx index 645426d64eda4..f880d5761f3eb 100644 --- a/packages/shared-ux/button/exit_full_screen/impl/src/exit_full_screen_button.component.tsx +++ b/packages/shared-ux/button/exit_full_screen/src/exit_full_screen_button.component.tsx @@ -20,7 +20,7 @@ import { i18n } from '@kbn/i18n'; import { css } from '@emotion/react'; import cx from 'classnames'; -import type { ExitFullScreenButtonComponentProps as Props } from '@kbn/shared-ux-button-exit-full-screen-types'; +import type { ExitFullScreenButtonComponentProps as Props } from '../types'; import './exit_full_screen_button.scss'; diff --git a/packages/shared-ux/button/exit_full_screen/impl/src/exit_full_screen_button.scss b/packages/shared-ux/button/exit_full_screen/src/exit_full_screen_button.scss similarity index 100% rename from packages/shared-ux/button/exit_full_screen/impl/src/exit_full_screen_button.scss rename to packages/shared-ux/button/exit_full_screen/src/exit_full_screen_button.scss diff --git a/packages/shared-ux/button/exit_full_screen/impl/src/exit_full_screen_button.stories.tsx b/packages/shared-ux/button/exit_full_screen/src/exit_full_screen_button.stories.tsx similarity index 84% rename from packages/shared-ux/button/exit_full_screen/impl/src/exit_full_screen_button.stories.tsx rename to packages/shared-ux/button/exit_full_screen/src/exit_full_screen_button.stories.tsx index 59a37c3c726e6..b126b7e0d5ab2 100644 --- a/packages/shared-ux/button/exit_full_screen/impl/src/exit_full_screen_button.stories.tsx +++ b/packages/shared-ux/button/exit_full_screen/src/exit_full_screen_button.stories.tsx @@ -7,8 +7,10 @@ */ import React from 'react'; -import { ExitFullScreenButtonStorybookMock } from '@kbn/shared-ux-button-exit-full-screen-mocks'; -import type { ExitFullScreenButtonStorybookParams } from '@kbn/shared-ux-button-exit-full-screen-mocks'; +import { + ExitFullScreenButtonStorybookMock, + type ExitFullScreenButtonStorybookParams, +} from '../mocks'; import { ExitFullScreenButtonProvider } from './services'; import { ExitFullScreenButton as Component } from './exit_full_screen_button'; diff --git a/packages/shared-ux/button/exit_full_screen/impl/src/exit_full_screen_button.test.tsx b/packages/shared-ux/button/exit_full_screen/src/exit_full_screen_button.test.tsx similarity index 98% rename from packages/shared-ux/button/exit_full_screen/impl/src/exit_full_screen_button.test.tsx rename to packages/shared-ux/button/exit_full_screen/src/exit_full_screen_button.test.tsx index 016762e470f97..b63a87019e387 100644 --- a/packages/shared-ux/button/exit_full_screen/impl/src/exit_full_screen_button.test.tsx +++ b/packages/shared-ux/button/exit_full_screen/src/exit_full_screen_button.test.tsx @@ -13,7 +13,7 @@ import { keys } from '@elastic/eui'; import { getExitFullScreenButtonServicesMock, getExitFullScreenButtonKibanaDependenciesMock, -} from '@kbn/shared-ux-button-exit-full-screen-mocks'; +} from '../mocks'; import { ExitFullScreenButton } from './exit_full_screen_button'; import { ExitFullScreenButtonKibanaProvider, ExitFullScreenButtonProvider } from './services'; diff --git a/packages/shared-ux/button/exit_full_screen/impl/src/exit_full_screen_button.tsx b/packages/shared-ux/button/exit_full_screen/src/exit_full_screen_button.tsx similarity index 95% rename from packages/shared-ux/button/exit_full_screen/impl/src/exit_full_screen_button.tsx rename to packages/shared-ux/button/exit_full_screen/src/exit_full_screen_button.tsx index dc70d1de3e453..563fe9c2f9c3c 100644 --- a/packages/shared-ux/button/exit_full_screen/impl/src/exit_full_screen_button.tsx +++ b/packages/shared-ux/button/exit_full_screen/src/exit_full_screen_button.tsx @@ -10,10 +10,10 @@ import React, { useCallback, useEffect } from 'react'; import { useEuiTheme, keys } from '@elastic/eui'; import { css } from '@emotion/react'; import useMountedState from 'react-use/lib/useMountedState'; +import useObservable from 'react-use/lib/useObservable'; -import type { ExitFullScreenButtonProps as Props } from '@kbn/shared-ux-button-exit-full-screen-types'; +import type { ExitFullScreenButtonProps as Props } from '../types'; -import useObservable from 'react-use/lib/useObservable'; import { ExitFullScreenButton as Component } from './exit_full_screen_button.component'; import { useServices } from './services'; diff --git a/packages/shared-ux/button/exit_full_screen/impl/src/services.tsx b/packages/shared-ux/button/exit_full_screen/src/services.tsx similarity index 97% rename from packages/shared-ux/button/exit_full_screen/impl/src/services.tsx rename to packages/shared-ux/button/exit_full_screen/src/services.tsx index 909b63e77ed68..5a4111e4627df 100644 --- a/packages/shared-ux/button/exit_full_screen/impl/src/services.tsx +++ b/packages/shared-ux/button/exit_full_screen/src/services.tsx @@ -12,7 +12,7 @@ import type { Services, ExitFullScreenButtonServices, ExitFullScreenButtonKibanaDependencies, -} from '@kbn/shared-ux-button-exit-full-screen-types'; +} from '../types'; const ExitFullScreenButtonContext = React.createContext(null); diff --git a/packages/shared-ux/button/exit_full_screen/impl/tsconfig.json b/packages/shared-ux/button/exit_full_screen/tsconfig.json similarity index 67% rename from packages/shared-ux/button/exit_full_screen/impl/tsconfig.json rename to packages/shared-ux/button/exit_full_screen/tsconfig.json index 7dfac85744189..0590172c5b3f1 100644 --- a/packages/shared-ux/button/exit_full_screen/impl/tsconfig.json +++ b/packages/shared-ux/button/exit_full_screen/tsconfig.json @@ -1,5 +1,5 @@ { - "extends": "../../../../../tsconfig.base.json", + "extends": "../../../../tsconfig.base.json", "compilerOptions": { "outDir": "target/types", "types": [ @@ -15,8 +15,8 @@ ], "kbn_references": [ "@kbn/i18n", - "@kbn/shared-ux-button-exit-full-screen-types", - "@kbn/shared-ux-button-exit-full-screen-mocks", + "@kbn/shared-ux-storybook-mock", + "@kbn/core-custom-branding-common" ], "exclude": [ "target/**/*", diff --git a/packages/shared-ux/button/exit_full_screen/types/index.d.ts b/packages/shared-ux/button/exit_full_screen/types.ts similarity index 100% rename from packages/shared-ux/button/exit_full_screen/types/index.d.ts rename to packages/shared-ux/button/exit_full_screen/types.ts diff --git a/packages/shared-ux/button/exit_full_screen/types/README.md b/packages/shared-ux/button/exit_full_screen/types/README.md deleted file mode 100644 index 95956057ddc1a..0000000000000 --- a/packages/shared-ux/button/exit_full_screen/types/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# @kbn/shared-ux-button-exit-full-screen-types - -TODO: clintandrewhall diff --git a/packages/shared-ux/button/exit_full_screen/types/kibana.jsonc b/packages/shared-ux/button/exit_full_screen/types/kibana.jsonc deleted file mode 100644 index 9c8448d02a2b1..0000000000000 --- a/packages/shared-ux/button/exit_full_screen/types/kibana.jsonc +++ /dev/null @@ -1,5 +0,0 @@ -{ - "type": "shared-common", - "id": "@kbn/shared-ux-button-exit-full-screen-types", - "owner": "@elastic/appex-sharedux" -} diff --git a/packages/shared-ux/button/exit_full_screen/types/package.json b/packages/shared-ux/button/exit_full_screen/types/package.json deleted file mode 100644 index d5ff454e0a2c6..0000000000000 --- a/packages/shared-ux/button/exit_full_screen/types/package.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "name": "@kbn/shared-ux-button-exit-full-screen-types", - "private": true, - "version": "1.0.0", - "license": "SSPL-1.0 OR Elastic License 2.0" -} \ No newline at end of file diff --git a/packages/shared-ux/button/exit_full_screen/types/tsconfig.json b/packages/shared-ux/button/exit_full_screen/types/tsconfig.json deleted file mode 100644 index 9909bbb0564ca..0000000000000 --- a/packages/shared-ux/button/exit_full_screen/types/tsconfig.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "extends": "../../../../../tsconfig.base.json", - "compilerOptions": { - "outDir": "target/types", - "types": [] - }, - "include": [ - "*.d.ts" - ], - "exclude": [ - "target/**/*", - ], - "kbn_references": [ - "@kbn/core-custom-branding-common", - ] -} diff --git a/packages/shared-ux/chrome/serverless_projects_documentation.mdx b/packages/shared-ux/chrome/serverless_project_navigation.mdx similarity index 91% rename from packages/shared-ux/chrome/serverless_projects_documentation.mdx rename to packages/shared-ux/chrome/serverless_project_navigation.mdx index 25727791e0380..3bb59cdd1e6fb 100644 --- a/packages/shared-ux/chrome/serverless_projects_documentation.mdx +++ b/packages/shared-ux/chrome/serverless_project_navigation.mdx @@ -240,8 +240,6 @@ The `GroupDefinition` interface represents a group of items in the side navigati | `appendHorizontalRule` | `boolean` | Optional flag to indicate if a horizontal rule should be rendered after the node.
Note: this property is currently only available for group nodes in the navigation **panel** opening on the right of the side nav. | | `isCollapsible` | `boolean` | Optional flag to indicate if the accordion is collapsible (when `renderAs` is set to `'accordion'`.| - - ##### `RecentlyAccessedDefinition` | Property | Type | Description | @@ -261,7 +259,7 @@ The `PresetDefinition` interface represents a group of items which are prepopula ##### `ItemDefinition` -The `GroupDefinition` interface represents a group of items in the side navigation. It extends the `NodeDefinition` interface and has the following additional properties: +The `ItemDefinition` interface represents a top level item in the side navigation. It extends the `NodeDefinition` interface and has the following additional properties: | Property | Type | Description| @@ -545,26 +543,96 @@ Breadcrumbs is a list of links that represent the current navigation path. Proje Project breadcrumbs are built from 3 sections: -1. **Home link:** 🏠 -2. **Platform navigation:** is automatically controlled by SharedUX services -3. **Deeper context:** is manually controlled by projects +1. **Project name** +2. **Project navigation:** automatically set based on the project's navigation tree and the currently active navigation path +3. **Deeper context:** manually set by currently active application ### Project breadcrumbs sections -#### 🏠 Home breadcrumb +#### Project name breadcrumb -Home breadcrumb is always displayed as the first breadcrumb and leads to what project specifies as home page in `kibana.yml`. +Project name breadcrumb is always displayed as the first breadcrumb. It displays the project name and opens a popup with links to manage the project and view all projects. -#### Navigation breadcrumbs +#### Project navigation breadcrumbs -Navigation breadcrumbs are automatically generated based on the navigation tree set for the [side navigation](#left-side-navigation) and the currently active navigation path. +Project navigation breadcrumbs are automatically generated based on the project's navigation tree set for the [side navigation](#left-side-navigation) and the currently active navigation path. + +> **Note** +> If you have static pages that are accessible from an app and should display breadcrumbs but shouldn't be visible in the sidenav, you can add such pages to the navigation tree with `sideNavStatus: 'hidden'`. #### Deeper context breadcrumbs -Deeper context breadcrumbs are manually controlled by projects. They are added to the breadcrumbs using the `pluginsStart.serverless.setBreadcrumbs` method. +Most of the applications are already setting the complete breadcrumb path for stateful Kibana navigation using the `chrome.setBreadcrumbs` API. It is possible to reuse the existing breadcrumbs for deeper context breadcrumbs in the serverless project navigation. For this, apps need to add a deepLinkId to the breadcrumb object. This `deepLinkId` will be used to match and merge the project navigation breadcrumbs with the deeper context breadcrumbs set in `chrome.setBreadcrumbs`. + +For example, consider the navigation tree: + +````tsx + + + + + +``` + +When on `ml:anomalyexplorer` page, the project navigation breadcrumbs will be: + +```ts +[ + { + text: 'AI Ops' + }, + { + text: 'Anomaly Explorer', + link: 'ml:anomalyexplorer', + }, +]; +``` + +The ml app sets the stateless Kibana breadcrumbs using `chrome.setBreadcrumbs`: + +```ts +chrome.setBreadcrumbs([ + { + text: 'Kibana', + }, + { + text: 'Machine Learning', + href: '/app/ml', + deepLinkId: 'ml', + }, + { + text: 'Anomaly Explorer', + link: 'ml:anomalyexplorer', + deepLinkId: 'ml:anomalyexplorer', + }, + { + text: 'Jobs' + } +]) +``` + +The resulting project breadcrumbs list will be: + +```ts +[ + {}, // project name breadcrumb + { + text: 'AI Ops' + }, + { + text: 'Anomaly Explorer', + link: 'ml:anomalyexplorer', + }, + { + text: 'Jobs' + } +] +``` + +Alternatively, the deeper context breadcrumbs can be manually set using the `serverless.setBreadcrumbs` API. ```ts -pluginsStart.serverless.setBreadcrumbs([ +serverless.setBreadcrumbs([ { text: 'Deeper Context', href: '/some/deeper/context', @@ -576,7 +644,7 @@ These breadcrumbs are removed when the active navigation path changes. ### Overriding breadcrumbs -Projects can override navigation breadcrumbs. This will override navigation breadcrumbs, but will keep the Home breadcrumb: +Apps can override navigation breadcrumbs. This will override navigation breadcrumbs keeping the root "project name" breadcrumb: ```ts pluginsStart.serverless.setBreadcrumbs([b1, b2, b3], { absolute: true }); diff --git a/src/core/server/docs/kib_core_logging.mdx b/src/core/server/docs/kib_core_logging.mdx index 9b3cf8f77e24e..f117f0d54f718 100644 --- a/src/core/server/docs/kib_core_logging.mdx +++ b/src/core/server/docs/kib_core_logging.mdx @@ -61,16 +61,61 @@ ancestor chain including `root`. ## Log level -Currently we support the following log levels: _all_, _fatal_, _error_, _warn_, _info_, _debug_, _trace_, _off_. +There are two general categories of log levels: failures and informational. Within each category, there are 3 ranked log +levels which should be used in different situations. A log record is being logged by the logger if its level is higher than +or equal to the level of its logger. Otherwise, the log record is ignored. Generally, the lower the log level, the more frequently +it should be used, and the higher the log level, the less frequently it should be used. -Levels are ordered, so _all_ > _fatal_ > _error_ > _warn_ > _info_ > _debug_ > _trace_ > _off_. +By default, Kibana's server logs will include messages at the following levels: `fatal`, `error`, `warn` and `info`. In Kibana, we +expect the majority of logging statements to be at the debug level and developers are encouraged to turn on debug logging +for the subsystems that they are responsible for and working on. -A log record is being logged by the logger if its level is higher than or equal to the level of its logger. Otherwise, -the log record is ignored. - -The _all_ and _off_ levels can be used only in configuration and are just handy shortcuts that allow developer to log every +The `all` and `off` levels can be used only in configuration and are just handy shortcuts that allow developer to log every log record or disable logging entirely for the specific context name. +### Categories + +#### Failures + +**fatal:** Catastrophic failures that will cause the Kibana process to exit immediately. +**error:** Important operation failed unexpectedly, unable to recover. +**warn:** Something failed unexpectedly; however, the important operation was able to complete, was retried, or was actually +unimportant. + +#### Informational + +**info:** A major event happened that an operator (someone running our software in a production environment, not a Kibana developer) +should be aware of and act on. +**debug:** Information necessary for debugging. +**trace:** Very low-level information that is needed for debugging exceptional situations. + +### Examples + +#### Your plugin successfully completed a very important operation on startup +**Level:** `debug` +**Justification:** It's very tempting to use the `info` level here, but it's wrong. It's great that the very important operation was +completed, and all successes are worth celebrating; however, it does not require operators to "act", so it should be logged at the +`debug` level. If seeing that this operation completed successfully during development is important, turn on debug logging for the plugin. + +#### An Elasticsearch HTTP request failed because another Kibana node already did the same thing +**Level:** `debug` +**Justification:** It is expected that multiple Kibana nodes are running at the same time and it is expected that some Elasticsearch operations +will fail if multiple Kibana nodes try to do the same thing. Therefore, nothing unexpected happened and neither the `error` or the `warn` levels +should be used. Additionally, the `info` level should not be used because there is nothing that the operator should "act on". This information +is only pertinent when debugging, so the `debug` level should be used. + +#### An Elasticsearch HTTP request timed out +**Level**: `error` or `warn` +**Justification**: If the Elasticsearch HTTP request included no user input and can't be retried, then the `error` level should be used. However, +if the Elasticsearch HTTP request included user input in such a way that timeouts are possible (for example, by searching a very large amount of data) +or a retry will be performed, then the `warn` level should be used. Both of these failures can result in the "operator" needing to scale up/out Elasticsearch +or adjust the network configuration. + +#### Kibana reloaded configuration from kibana.yml file +**Level:** `info` +**Justification:** It's important for the operator to know that Kibana successfully reloaded configuration from the kibana.yml file. This lets them know it +is safe to proceed with verifying that the change in configuration had the desired effect. + ## Layouts Every appender should know exactly how to format log messages before they are written to the console or file on the disk. diff --git a/src/core/server/integration_tests/ci_checks/saved_objects/check_registered_types.test.ts b/src/core/server/integration_tests/ci_checks/saved_objects/check_registered_types.test.ts index 4d0dc79b74612..66fbd33d1568a 100644 --- a/src/core/server/integration_tests/ci_checks/saved_objects/check_registered_types.test.ts +++ b/src/core/server/integration_tests/ci_checks/saved_objects/check_registered_types.test.ts @@ -106,7 +106,7 @@ describe('checking migration metadata changes on all registered SO types', () => "infrastructure-ui-source": "113182d6895764378dfe7fa9fa027244f3a457c4", "ingest-agent-policies": "7633e578f60c074f8267bc50ec4763845e431437", "ingest-download-sources": "279a68147e62e4d8858c09ad1cf03bd5551ce58d", - "ingest-outputs": "3982d6296373111467e839a0768d3e1c4d0ebc61", + "ingest-outputs": "8546f1123ec30dcbd6f238f72729c5f1656a4d9b", "ingest-package-policies": "a0c9fb48e04dcd638e593db55f1c6451523f90ea", "ingest_manager_settings": "64955ef1b7a9ffa894d4bb9cf863b5602bfa6885", "inventory-view": "b8683c8e352a286b4aca1ab21003115a4800af83", diff --git a/src/core/server/integration_tests/http/lifecycle_handlers.test.ts b/src/core/server/integration_tests/http/lifecycle_handlers.test.ts index 96d9c06e80776..7e6b6906e1d1e 100644 --- a/src/core/server/integration_tests/http/lifecycle_handlers.test.ts +++ b/src/core/server/integration_tests/http/lifecycle_handlers.test.ts @@ -14,6 +14,10 @@ import { createConfigService, createHttpServer } from '@kbn/core-http-server-moc import { HttpService, HttpServerSetup } from '@kbn/core-http-server-internal'; import { executionContextServiceMock } from '@kbn/core-execution-context-server-mocks'; import { schema } from '@kbn/config-schema'; +import { IConfigServiceMock } from '@kbn/config-mocks'; +import { Logger } from '@kbn/logging'; +import { loggerMock } from '@kbn/logging-mocks'; +import { KIBANA_BUILD_NR_HEADER } from '@kbn/core-http-common'; const actualVersion = kibanaPackageJson.version; const versionHeader = 'kbn-version'; @@ -52,10 +56,12 @@ describe('core lifecycle handlers', () => { let server: HttpService; let innerServer: HttpServerSetup['server']; let router: IRouter; + let logger: jest.Mocked; beforeEach(async () => { const configService = createConfigService(testConfig); - server = createHttpServer({ configService }); + logger = loggerMock.create(); + server = createHttpServer({ configService, logger }); await server.preboot({ context: contextServiceMock.createPrebootContract() }); const serverSetup = await server.setup(setupDeps); router = serverSetup.createRouter('/'); @@ -93,6 +99,14 @@ describe('core lifecycle handlers', () => { .set(versionHeader, 'invalid-version') .expect(400, /Browser client is out of date/); }); + + it('does not log a warning message about the build mismatch', async () => { + await supertest(innerServer.listener) + .get(testRoute) + .set(versionHeader, 'invalid-version') + .expect(400, /Browser client is out of date/); + expect(logger.warn).not.toHaveBeenCalled(); + }); }); describe('customHeaders pre-response handler', () => { @@ -349,13 +363,17 @@ describe('core lifecycle handlers with restrict internal routes enforced', () => }); describe('core lifecycle handlers with no strict client version check', () => { - const testRoute = '/version_check/test/route'; + const testRouteGood = '/no_version_check/test/ok'; + const testRouteBad = '/no_version_check/test/nok'; let server: HttpService; let innerServer: HttpServerSetup['server']; let router: IRouter; + let configService: IConfigServiceMock; + let logger: jest.Mocked; beforeEach(async () => { - const configService = createConfigService({ + logger = loggerMock.create(); + configService = createConfigService({ server: { versioned: { strictClientVersionCheck: false, @@ -363,13 +381,16 @@ describe('core lifecycle handlers with no strict client version check', () => { }, }, }); - server = createHttpServer({ configService }); + server = createHttpServer({ configService, logger, buildNum: 1234 }); await server.preboot({ context: contextServiceMock.createPrebootContract() }); const serverSetup = await server.setup(setupDeps); router = serverSetup.createRouter('/'); - router.get({ path: testRoute, validate: false }, (context, req, res) => { + router.get({ path: testRouteGood, validate: false }, (context, req, res) => { return res.ok({ body: 'ok' }); }); + router.get({ path: testRouteBad, validate: false }, (context, req, res) => { + return res.custom({ body: 'nok', statusCode: 500 }); + }); innerServer = serverSetup.server; await server.start(); }); @@ -379,13 +400,38 @@ describe('core lifecycle handlers with no strict client version check', () => { }); it('accepts requests that do not include a version header', async () => { - await supertest(innerServer.listener).get(testRoute).expect(200, 'ok'); + await supertest(innerServer.listener).get(testRouteGood).expect(200, 'ok'); }); it('accepts requests with any version passed in the version header', async () => { await supertest(innerServer.listener) - .get(testRoute) + .get(testRouteGood) .set(versionHeader, 'what-have-you') .expect(200, 'ok'); }); + + it('logs a warning when a client build number is newer', async () => { + await supertest(innerServer.listener) + .get(testRouteBad) + .set(KIBANA_BUILD_NR_HEADER, '12345') + .expect(500, /nok/); + + expect(logger.warn).toHaveBeenCalledTimes(1); + const [[message]] = logger.warn.mock.calls; + expect(message).toMatch( + /^Client build \(12345\) is newer than this Kibana server build \(1234\)/ + ); + }); + it('logs a warning when a client build number is older', async () => { + await supertest(innerServer.listener) + .get(testRouteBad) + .set(KIBANA_BUILD_NR_HEADER, '123') + .expect(500, /nok/); + + expect(logger.warn).toHaveBeenCalledTimes(1); + const [[message]] = logger.warn.mock.calls; + expect(message).toMatch( + /^Client build \(123\) is older than this Kibana server build \(1234\)/ + ); + }); }); diff --git a/src/dev/build/tasks/os_packages/docker_generator/run.ts b/src/dev/build/tasks/os_packages/docker_generator/run.ts index 636096b921b07..f9da19183d866 100644 --- a/src/dev/build/tasks/os_packages/docker_generator/run.ts +++ b/src/dev/build/tasks/os_packages/docker_generator/run.ts @@ -39,7 +39,7 @@ export async function runDockerGenerator( } ) { let baseImageName = ''; - if (flags.baseImage === 'ubuntu') baseImageName = 'ubuntu:22.04'; + if (flags.baseImage === 'ubuntu') baseImageName = 'ubuntu:20.04'; if (flags.baseImage === 'ubi8') baseImageName = 'docker.elastic.co/ubi8/ubi-minimal:latest'; if (flags.baseImage === 'ubi9') baseImageName = 'docker.elastic.co/ubi9/ubi-minimal:latest'; 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 73968d57529f6..8db4b419a184a 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 @@ -189,7 +189,7 @@ ENTRYPOINT ["/bin/tini", "--"] CMD ["/app/kibana.sh"] # Generate a stub command that will be overwritten at runtime RUN mkdir /app && \ - /usr/bin/echo -e '#!/bin/bash\nexec /usr/local/bin/kibana-docker' > /app/kibana.sh && \ + echo -e '#!/bin/bash\nexec /usr/local/bin/kibana-docker' > /app/kibana.sh && \ chmod 0555 /app/kibana.sh {{/cloud}} diff --git a/src/plugins/data/common/search/expressions/esql.ts b/src/plugins/data/common/search/expressions/esql.ts index 30bf10a0f1bb7..cfdbeb39b860e 100644 --- a/src/plugins/data/common/search/expressions/esql.ts +++ b/src/plugins/data/common/search/expressions/esql.ts @@ -71,6 +71,16 @@ function sanitize(value: string) { return value.replace(/[\(\)]/g, '_'); } +function extractTypeAndReason(attributes: any): { type?: string; reason?: string } { + if (['type', 'reason'].every((prop) => prop in attributes)) { + return attributes; + } + if ('error' in attributes) { + return extractTypeAndReason(attributes.error); + } + return {}; +} + interface ESQLSearchParams { time_zone?: string; query: string; @@ -199,7 +209,7 @@ export const getEsqlFn = ({ getStartDependencies }: EsqlFnArguments) => { if (!error.err) { error.message = `Unexpected error from Elasticsearch: ${error.message}`; } else { - const { type, reason } = error.err.attributes; + const { type, reason } = extractTypeAndReason(error.err.attributes); if (type === 'parsing_exception') { error.message = `Couldn't parse Elasticsearch ES|QL query. Check your query and try again. Error: ${reason}`; } else { diff --git a/src/plugins/data_views/docs/openapi/bundled.json b/src/plugins/data_views/docs/openapi/bundled.json index 3f113f9b00d8d..d661e0a7cbaad 100644 --- a/src/plugins/data_views/docs/openapi/bundled.json +++ b/src/plugins/data_views/docs/openapi/bundled.json @@ -36,7 +36,7 @@ "get": { "summary": "Retrieves a list of all data views.", "operationId": "getAllDataViews", - "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", + "description": "This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features.\n", "tags": [ "data views" ], @@ -101,7 +101,7 @@ "post": { "summary": "Creates a data view.", "operationId": "createDataView", - "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", + "description": "This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features.\n", "tags": [ "data views" ], @@ -153,7 +153,7 @@ "get": { "summary": "Retrieves a single data view by identifier.", "operationId": "getDataView", - "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", + "description": "This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features.\n", "tags": [ "data views" ], @@ -193,7 +193,7 @@ "delete": { "summary": "Deletes a data view.", "operationId": "deleteDataView", - "description": "WARNING: When you delete a data view, it cannot be recovered. This functionality is in technical preview and may be changed or removed in a future release. Elastic will apply best effort to fix any issues, but features in technical preview are not subject to the support SLA of official GA features.\n", + "description": "WARNING: When you delete a data view, it cannot be recovered. This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features.\n", "tags": [ "data views" ], @@ -221,7 +221,7 @@ "post": { "summary": "Updates a data view.", "operationId": "updateDataView", - "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", + "description": "This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features.\n", "tags": [ "data views" ], @@ -276,7 +276,7 @@ "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", + "description": "This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. You can update multiple fields in one request. Updates are merged with persisted metadata. To remove existing metadata, specify null as the value.\n", "tags": [ "data views" ], @@ -345,7 +345,7 @@ "post": { "summary": "Creates a runtime field.", "operationId": "createRuntimeField", - "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", + "description": "This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features.\n", "tags": [ "data views" ], @@ -390,7 +390,7 @@ "put": { "summary": "Create or update an existing runtime field.", "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", + "description": "This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features.\n", "tags": [ "data views" ], @@ -478,7 +478,7 @@ "get": { "summary": "Retrieves a runtime field.", "operationId": "getRuntimeField", - "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", + "description": "This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features.\n", "tags": [ "data views" ], @@ -532,7 +532,7 @@ "delete": { "summary": "Delete a runtime field from a data view.", "operationId": "deleteRuntimeField", - "description": "This functionality is in technical preview and may be changed or removed in a future release. Elastic will apply best effort to fix any issues, but features in technical preview are not subject to the support SLA of official GA features.\n", + "description": "This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features.\n", "tags": [ "data views" ], @@ -563,7 +563,7 @@ "post": { "summary": "Update an existing runtime field.", "operationId": "updateRuntimeField", - "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", + "description": "This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features.\n", "tags": [ "data views" ], @@ -620,7 +620,7 @@ "get": { "summary": "Retrieves the default data view identifier.", "operationId": "getDefaultDataView", - "description": "This functionality is in technical preview and may be changed or removed in a future release. Elastic will apply best effort to fix any issues, but features in technical preview are not subject to the support SLA of official GA features.\n", + "description": "This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features.\n", "tags": [ "data views" ], @@ -660,7 +660,7 @@ "post": { "summary": "Sets the default data view identifier.", "operationId": "setDefaultDatailView", - "description": "This functionality is in technical preview and may be changed or removed in a future release. Elastic will apply best effort to fix any issues, but features in technical preview are not subject to the support SLA of official GA features.\n", + "description": "This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features.\n", "tags": [ "data views" ], diff --git a/src/plugins/data_views/docs/openapi/bundled.yaml b/src/plugins/data_views/docs/openapi/bundled.yaml index 1b0b9a2ba7d27..c6e52614b66e9 100644 --- a/src/plugins/data_views/docs/openapi/bundled.yaml +++ b/src/plugins/data_views/docs/openapi/bundled.yaml @@ -22,7 +22,7 @@ paths: summary: Retrieves a list of all data views. operationId: getAllDataViews 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. + This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. tags: - data views responses: @@ -64,7 +64,7 @@ paths: summary: Creates a data view. operationId: createDataView 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. + This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. tags: - data views parameters: @@ -96,7 +96,7 @@ paths: summary: Retrieves a single data view by identifier. operationId: getDataView 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. + This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. tags: - data views parameters: @@ -121,7 +121,7 @@ paths: summary: Deletes a data view. operationId: deleteDataView description: | - WARNING: When you delete a data view, it cannot be recovered. This functionality is in technical preview and may be changed or removed in a future release. Elastic will apply best effort to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. + WARNING: When you delete a data view, it cannot be recovered. This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. tags: - data views parameters: @@ -139,7 +139,7 @@ paths: summary: Updates a data view. operationId: updateDataView 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. + This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. tags: - data views parameters: @@ -172,7 +172,7 @@ paths: 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. + This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. You can update multiple fields in one request. Updates are merged with persisted metadata. To remove existing metadata, specify null as the value. tags: - data views parameters: @@ -214,7 +214,7 @@ paths: summary: Creates a runtime field. operationId: createRuntimeField 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. + This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. tags: - data views parameters: @@ -245,7 +245,7 @@ paths: summary: Create or update an existing runtime field. 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. + This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. tags: - data views parameters: @@ -304,7 +304,7 @@ paths: summary: Retrieves a runtime field. operationId: getRuntimeField 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. + This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. tags: - data views parameters: @@ -337,7 +337,7 @@ paths: summary: Delete a runtime field from a data view. operationId: deleteRuntimeField description: | - This functionality is in technical preview and may be changed or removed in a future release. Elastic will apply best effort to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. + This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. tags: - data views parameters: @@ -356,7 +356,7 @@ paths: summary: Update an existing runtime field. operationId: updateRuntimeField 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. + This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. tags: - data views parameters: @@ -397,7 +397,7 @@ paths: summary: Retrieves the default data view identifier. operationId: getDefaultDataView description: | - This functionality is in technical preview and may be changed or removed in a future release. Elastic will apply best effort to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. + This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. tags: - data views responses: @@ -423,7 +423,7 @@ paths: summary: Sets the default data view identifier. operationId: setDefaultDatailView description: | - This functionality is in technical preview and may be changed or removed in a future release. Elastic will apply best effort to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. + This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. tags: - data views parameters: 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 64ebc3877c4a3..e36f914e55e54 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 @@ -2,7 +2,7 @@ get: summary: Retrieves a list of all data views. operationId: getAllDataViews 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. + This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. tags: - data views responses: diff --git a/src/plugins/data_views/docs/openapi/paths/api@data_views@data_view.yaml b/src/plugins/data_views/docs/openapi/paths/api@data_views@data_view.yaml index a3c457dbdaa93..32a7e0b5c42dc 100644 --- a/src/plugins/data_views/docs/openapi/paths/api@data_views@data_view.yaml +++ b/src/plugins/data_views/docs/openapi/paths/api@data_views@data_view.yaml @@ -2,7 +2,7 @@ post: summary: Creates a data view. operationId: createDataView 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. + This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. tags: - data views parameters: diff --git a/src/plugins/data_views/docs/openapi/paths/api@data_views@data_view@{viewid}.yaml b/src/plugins/data_views/docs/openapi/paths/api@data_views@data_view@{viewid}.yaml index fdb4677849281..73d206a6991f3 100644 --- a/src/plugins/data_views/docs/openapi/paths/api@data_views@data_view@{viewid}.yaml +++ b/src/plugins/data_views/docs/openapi/paths/api@data_views@data_view@{viewid}.yaml @@ -2,7 +2,7 @@ get: summary: Retrieves a single data view by identifier. operationId: getDataView 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. + This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. tags: - data views parameters: @@ -29,7 +29,7 @@ delete: operationId: deleteDataView description: > WARNING: When you delete a data view, it cannot be recovered. - This functionality is in technical preview and may be changed or removed in a future release. Elastic will apply best effort to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. + This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. tags: - data views parameters: @@ -48,7 +48,7 @@ post: summary: Updates a data view. operationId: updateDataView 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. + This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. tags: - data views parameters: 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 index c003ea01256e7..62bce25d96cd9 100644 --- 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 @@ -1,8 +1,8 @@ post: - summary: Update fields presentation metadata such as count, customLabel and format. + 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. + This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. You can update multiple fields in one request. Updates are merged with persisted metadata. To remove existing metadata, specify null as the value. tags: - data views parameters: @@ -22,7 +22,7 @@ post: type: object examples: updateFieldsMetadataRequest: - $ref: '../components/examples/update_field_metadata_request.yaml' + $ref: '../components/examples/update_field_metadata_request.yaml' responses: '200': description: Indicates a successful call. 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 97c4be06df96e..bf8613992f411 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 @@ -1,8 +1,8 @@ post: summary: Creates a runtime field. - operationId: createRuntimeField + operationId: createRuntimeField 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. + This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. tags: - data views parameters: @@ -32,9 +32,9 @@ post: put: summary: Create or update an existing runtime field. - operationId: createUpdateRuntimeField + 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. + This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. tags: - data views parameters: 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 d18cd5e6b26a5..2f6a452d351a4 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 @@ -2,7 +2,7 @@ get: summary: Retrieves a runtime field. operationId: getRuntimeField 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. + This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. tags: - data views parameters: @@ -36,7 +36,7 @@ delete: summary: Delete a runtime field from a data view. operationId: deleteRuntimeField description: > - This functionality is in technical preview and may be changed or removed in a future release. Elastic will apply best effort to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. + This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. tags: - data views parameters: @@ -56,7 +56,7 @@ post: summary: Update an existing runtime field. operationId: updateRuntimeField 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. + This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. tags: - data views parameters: 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 ef47416b63da4..83e616b635973 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 @@ -2,7 +2,7 @@ get: summary: Retrieves the default data view identifier. operationId: getDefaultDataView description: > - This functionality is in technical preview and may be changed or removed in a future release. Elastic will apply best effort to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. + This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. tags: - data views responses: @@ -28,7 +28,7 @@ post: summary: Sets the default data view identifier. operationId: setDefaultDatailView description: > - This functionality is in technical preview and may be changed or removed in a future release. Elastic will apply best effort to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. + This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. tags: - data views parameters: diff --git a/src/plugins/discover/public/customizations/customization_types/flyout_customization.ts b/src/plugins/discover/public/customizations/customization_types/flyout_customization.ts index 08f8f034a00d3..84f3f27715039 100644 --- a/src/plugins/discover/public/customizations/customization_types/flyout_customization.ts +++ b/src/plugins/discover/public/customizations/customization_types/flyout_customization.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 type { DataTableRecord } from '@kbn/discover-utils/types'; import type { DocViewFilterFn } from '@kbn/unified-doc-viewer/types'; import React, { type ComponentType } from 'react'; diff --git a/src/plugins/discover/public/index.ts b/src/plugins/discover/public/index.ts index 42033c2ebfdb5..37a46f30c4ccf 100644 --- a/src/plugins/discover/public/index.ts +++ b/src/plugins/discover/public/index.ts @@ -26,6 +26,8 @@ export type { DiscoverCustomization, DiscoverCustomizationService, FlyoutCustomization, + FlyoutContentActions, + FlyoutContentProps, SearchBarCustomization, UnifiedHistogramCustomization, TopNavCustomization, diff --git a/src/plugins/files/server/blob_storage_service/blob_storage_service.ts b/src/plugins/files/server/blob_storage_service/blob_storage_service.ts index 3667957ba25d8..0404145beb608 100644 --- a/src/plugins/files/server/blob_storage_service/blob_storage_service.ts +++ b/src/plugins/files/server/blob_storage_service/blob_storage_service.ts @@ -20,7 +20,7 @@ export class BlobStorageService { /** * The number of uploads per Kibana instance that can be running simultaneously */ - private readonly concurrentUploadsToES = 20; + private readonly concurrentUploadsToES = 5; /** * The number of downloads per Kibana instance that can be running simultaneously diff --git a/src/plugins/kibana_react/public/exit_full_screen_button/__snapshots__/exit_full_screen_button.test.tsx.snap b/src/plugins/kibana_react/public/exit_full_screen_button/__snapshots__/exit_full_screen_button.test.tsx.snap deleted file mode 100644 index b25b6fdade799..0000000000000 --- a/src/plugins/kibana_react/public/exit_full_screen_button/__snapshots__/exit_full_screen_button.test.tsx.snap +++ /dev/null @@ -1,53 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[` is rendered 1`] = ` -
-

- In full screen mode, press ESC to exit. -

-
- -
-
-`; diff --git a/src/plugins/kibana_react/public/exit_full_screen_button/_exit_full_screen_button.scss b/src/plugins/kibana_react/public/exit_full_screen_button/_exit_full_screen_button.scss deleted file mode 100644 index 7548bd0c0db5f..0000000000000 --- a/src/plugins/kibana_react/public/exit_full_screen_button/_exit_full_screen_button.scss +++ /dev/null @@ -1,37 +0,0 @@ -/** - * 1. override the z-index: 1 applied to all non-eui elements that are in :focus via kui - * - see packages/kbn-ui-framework/src/global_styling/reset/_reset.scss - */ - -.dshExitFullScreenButton { - @include euiBottomShadow; - - left: $euiSizeS; - bottom: $euiSizeS; - position: fixed; - display: block; - padding: $euiSizeXS $euiSizeS; - border: none; - background: none; - z-index: 5; - background: $euiColorFullShade; - border-radius: $euiBorderRadius; - text-align: left; - - &:hover { - background: $euiColorFullShade; - - .dshExitFullScreenButton__icon { - color: $euiColorEmptyShade; - } - } -} - -.dshExitFullScreenButton__text { - line-height: 1.2; - color: makeHighContrastColor($euiColorMediumShade, $euiColorFullShade); -} - -.dshExitFullScreenButton__icon { - color: makeHighContrastColor($euiColorMediumShade, $euiColorFullShade); -} diff --git a/src/plugins/kibana_react/public/exit_full_screen_button/exit_full_screen_button.test.tsx b/src/plugins/kibana_react/public/exit_full_screen_button/exit_full_screen_button.test.tsx deleted file mode 100644 index 8201133b0d2d6..0000000000000 --- a/src/plugins/kibana_react/public/exit_full_screen_button/exit_full_screen_button.test.tsx +++ /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 React from 'react'; -import { mount, ReactWrapper } from 'enzyme'; -import { ExitFullScreenButton } from './exit_full_screen_button'; -import { keys } from '@elastic/eui'; -import type { ChromeStart } from '@kbn/core/public'; - -const MockChrome = { - setIsVisible: jest.fn(), -} as unknown as ChromeStart; - -describe('', () => { - afterEach(() => { - jest.resetAllMocks(); - }); - - test('is rendered', () => { - const component = mount( - - ); - - expect(component.render()).toMatchSnapshot(); - }); - - test('passing `false` to toggleChrome does not toggle chrome', () => { - const component = mount( - - ); - expect(MockChrome.setIsVisible).toHaveBeenCalledTimes(0); - component.unmount(); - expect(MockChrome.setIsVisible).toHaveBeenCalledTimes(0); - }); - - describe('onExitFullScreenMode', () => { - const onExitHandler = jest.fn(); - let component: ReactWrapper; - - beforeEach(() => { - component = mount( - - ); - }); - - test('is called when the button is pressed', () => { - expect(MockChrome.setIsVisible).toHaveBeenLastCalledWith(false); - - component.find('button').simulate('click'); - - expect(onExitHandler).toHaveBeenCalledTimes(1); - component.unmount(); - expect(MockChrome.setIsVisible).toHaveBeenLastCalledWith(true); - }); - - test('is called when the ESC key is pressed', () => { - expect(MockChrome.setIsVisible).toHaveBeenLastCalledWith(false); - - const escapeKeyEvent = new KeyboardEvent('keydown', { key: keys.ESCAPE } as any); - document.dispatchEvent(escapeKeyEvent); - - expect(onExitHandler).toHaveBeenCalledTimes(1); - component.unmount(); - expect(MockChrome.setIsVisible).toHaveBeenLastCalledWith(true); - }); - }); -}); diff --git a/src/plugins/kibana_react/public/exit_full_screen_button/exit_full_screen_button.tsx b/src/plugins/kibana_react/public/exit_full_screen_button/exit_full_screen_button.tsx deleted file mode 100644 index f611c391a20a2..0000000000000 --- a/src/plugins/kibana_react/public/exit_full_screen_button/exit_full_screen_button.tsx +++ /dev/null @@ -1,105 +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 React, { PureComponent } from 'react'; -import { EuiScreenReaderOnly, keys } from '@elastic/eui'; -import { EuiIcon, EuiFlexGroup, EuiFlexItem, EuiText } from '@elastic/eui'; -import type { ChromeStart } from '@kbn/core/public'; - -export interface ExitFullScreenButtonProps { - onExitFullScreenMode: () => void; - chrome: ChromeStart; - /** - * Optional argument that determines whether we toggle the chrome bar - * the button unmounts. - * - * @note The intended use for this prop is that it is either `true` or `false` - * for the lifetime of the button. - * - * @default true - */ - toggleChrome?: boolean; -} - -import './index.scss'; - -class ExitFullScreenButtonUi extends PureComponent { - static defaultProps = { - toggleChrome: true, - }; - - public onKeyDown = (e: KeyboardEvent) => { - if (e.key === keys.ESCAPE) { - this.props.onExitFullScreenMode(); - } - }; - - public componentDidMount() { - if (this.props.toggleChrome) this.props.chrome.setIsVisible(false); - document.addEventListener('keydown', this.onKeyDown, false); - } - - public componentWillUnmount() { - if (this.props.toggleChrome) this.props.chrome.setIsVisible(true); - document.removeEventListener('keydown', this.onKeyDown, false); - } - - public render() { - return ( -
- -

- {i18n.translate('kibana-react.exitFullScreenButton.fullScreenModeDescription', { - defaultMessage: 'In full screen mode, press ESC to exit.', - })} -

-
-
- -
-
- ); - } -} - -/** @deprecated Use `ExitFullScreenButton` from `@kbn/shared-ux-button-exit-full-screen`. */ -export const ExitFullScreenButton = ExitFullScreenButtonUi; diff --git a/src/plugins/kibana_react/public/exit_full_screen_button/index.scss b/src/plugins/kibana_react/public/exit_full_screen_button/index.scss deleted file mode 100644 index 82dd33baeb3e5..0000000000000 --- a/src/plugins/kibana_react/public/exit_full_screen_button/index.scss +++ /dev/null @@ -1 +0,0 @@ -@import './exit_full_screen_button'; diff --git a/src/plugins/kibana_react/public/exit_full_screen_button/index.tsx b/src/plugins/kibana_react/public/exit_full_screen_button/index.tsx deleted file mode 100644 index 16466f5c0f6a2..0000000000000 --- a/src/plugins/kibana_react/public/exit_full_screen_button/index.tsx +++ /dev/null @@ -1,10 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may 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 { ExitFullScreenButtonProps } from './exit_full_screen_button'; -export { ExitFullScreenButton } from './exit_full_screen_button'; diff --git a/src/plugins/kibana_react/public/index.ts b/src/plugins/kibana_react/public/index.ts index 2803c266da0f4..e7244459a5c72 100644 --- a/src/plugins/kibana_react/public/index.ts +++ b/src/plugins/kibana_react/public/index.ts @@ -21,9 +21,6 @@ export { export type { UrlTemplateEditorVariable, UrlTemplateEditorProps } from './url_template_editor'; export { UrlTemplateEditor } from './url_template_editor'; -export type { ExitFullScreenButtonProps } from './exit_full_screen_button'; -export { ExitFullScreenButton } from './exit_full_screen_button'; - export type { KibanaReactContext, KibanaReactContextValue, KibanaServices } from './context'; export { context, diff --git a/src/plugins/links/public/components/links_strings.ts b/src/plugins/links/public/components/links_strings.ts index 4756bc28e3bdd..bc776dfe8f1a0 100644 --- a/src/plugins/links/public/components/links_strings.ts +++ b/src/plugins/links/public/components/links_strings.ts @@ -38,7 +38,7 @@ export const LinksStrings = { getTechnicalPreviewTooltip: () => i18n.translate('links.panelEditor.technicalPreviewTooltip', { defaultMessage: - 'This functionality is in technical preview and may be changed or removed completely in a future release. Elastic will take a best effort approach to fix any issues, but features in technical preview are not subject to the support SLA of official GA features.', + 'This functionality is in technical preview and may be changed or removed completely in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features.', }), getTechnicalPreviewLabel: () => i18n.translate('links.panelEditor.technicalPreviewLabel', { diff --git a/src/plugins/vis_types/timeseries/public/application/components/aggs/percentile_ui.js b/src/plugins/vis_types/timeseries/public/application/components/aggs/percentile_ui.js index ec7101c93e0b0..15dd442639c63 100644 --- a/src/plugins/vis_types/timeseries/public/application/components/aggs/percentile_ui.js +++ b/src/plugins/vis_types/timeseries/public/application/components/aggs/percentile_ui.js @@ -13,7 +13,7 @@ import _ from 'lodash'; import { TSVB_DEFAULT_COLOR } from '../../../../common/constants'; import { collectionActions } from '../lib/collection_actions'; import { AddDeleteButtons } from '../add_delete_buttons'; -import { v1 as uuidv1 } from 'uuid'; +import { v4 as uuidv4 } from 'uuid'; import { htmlIdGenerator, EuiFlexGroup, @@ -28,7 +28,7 @@ import { ColorPicker } from '../color_picker'; import { FormattedMessage } from '@kbn/i18n-react'; export const newPercentile = (opts) => { - return _.assign({ id: uuidv1(), mode: 'line', shade: 0.2, color: TSVB_DEFAULT_COLOR }, opts); + return _.assign({ id: uuidv4(), mode: 'line', shade: 0.2, color: TSVB_DEFAULT_COLOR }, opts); }; export class Percentiles extends Component { diff --git a/src/plugins/vis_types/timeseries/public/application/components/aggs/vars.js b/src/plugins/vis_types/timeseries/public/application/components/aggs/vars.js index 9493684f058e0..20e6c99b73de6 100644 --- a/src/plugins/vis_types/timeseries/public/application/components/aggs/vars.js +++ b/src/plugins/vis_types/timeseries/public/application/components/aggs/vars.js @@ -8,7 +8,7 @@ import PropTypes from 'prop-types'; import React, { Component } from 'react'; -import { v1 as uuidv1 } from 'uuid'; +import { v4 as uuidv4 } from 'uuid'; import { i18n } from '@kbn/i18n'; import _ from 'lodash'; import { AddDeleteButtons } from '../add_delete_buttons'; @@ -17,7 +17,7 @@ import { MetricSelect } from './metric_select'; import { EuiFlexGroup, EuiFlexItem, EuiFieldText } from '@elastic/eui'; import { getIndexPatternKey } from '../../../../common/index_patterns_utils'; -export const newVariable = (opts) => ({ id: uuidv1(), name: '', field: '', ...opts }); +export const newVariable = (opts) => ({ id: uuidv4(), name: '', field: '', ...opts }); export class CalculationVars extends Component { constructor(props) { diff --git a/src/plugins/vis_types/timeseries/public/application/components/annotations_editor.tsx b/src/plugins/vis_types/timeseries/public/application/components/annotations_editor.tsx index e0ee9adb08a90..b1c4adae3859b 100644 --- a/src/plugins/vis_types/timeseries/public/application/components/annotations_editor.tsx +++ b/src/plugins/vis_types/timeseries/public/application/components/annotations_editor.tsx @@ -7,7 +7,7 @@ */ import React, { useCallback } from 'react'; -import { v1 as uuidv1 } from 'uuid'; +import { v4 as uuidv4 } from 'uuid'; import { EuiSpacer, EuiTitle, EuiButton, EuiText } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; import type { DataView } from '@kbn/data-views-plugin/public'; @@ -28,7 +28,7 @@ interface AnnotationsEditorProps { } export const newAnnotation = (defaultIndexPattern?: DataView) => () => ({ - id: uuidv1(), + id: uuidv4(), color: '#F00', index_pattern: defaultIndexPattern && defaultIndexPattern.id ? { id: defaultIndexPattern.id } : '', diff --git a/src/plugins/vis_types/timeseries/public/application/components/lib/collection_actions.ts b/src/plugins/vis_types/timeseries/public/application/components/lib/collection_actions.ts index 8d12c2a5f96cb..0cae168d73864 100644 --- a/src/plugins/vis_types/timeseries/public/application/components/lib/collection_actions.ts +++ b/src/plugins/vis_types/timeseries/public/application/components/lib/collection_actions.ts @@ -6,14 +6,14 @@ * Side Public License, v 1. */ -import { v1 as uuidv1 } from 'uuid'; +import { v4 as uuidv4 } from 'uuid'; interface DocType { id: string; type?: string; } -const newFn = (): DocType => ({ id: uuidv1() }); +const newFn = (): DocType => ({ id: uuidv4() }); export interface CollectionActionsProps { model: T; diff --git a/src/plugins/vis_types/timeseries/public/application/components/lib/new_metric_agg_fn.ts b/src/plugins/vis_types/timeseries/public/application/components/lib/new_metric_agg_fn.ts index f78aa3638d002..65887977e2644 100644 --- a/src/plugins/vis_types/timeseries/public/application/components/lib/new_metric_agg_fn.ts +++ b/src/plugins/vis_types/timeseries/public/application/components/lib/new_metric_agg_fn.ts @@ -6,13 +6,13 @@ * Side Public License, v 1. */ -import { v1 as uuidv1 } from 'uuid'; +import { v4 as uuidv4 } from 'uuid'; import { METRIC_TYPES } from '@kbn/data-plugin/common'; import type { Metric } from '../../../../common/types'; export const newMetricAggFn = (): Metric => { return { - id: uuidv1(), + id: uuidv4(), type: METRIC_TYPES.COUNT, }; }; diff --git a/src/plugins/vis_types/timeseries/public/application/components/lib/new_series_fn.js b/src/plugins/vis_types/timeseries/public/application/components/lib/new_series_fn.js index 92458f0858245..899cbeeda1e83 100644 --- a/src/plugins/vis_types/timeseries/public/application/components/lib/new_series_fn.js +++ b/src/plugins/vis_types/timeseries/public/application/components/lib/new_series_fn.js @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { v1 as uuidv1 } from 'uuid'; +import { v4 as uuidv4 } from 'uuid'; import _ from 'lodash'; import { newMetricAggFn } from './new_metric_agg_fn'; import { STACKED_OPTIONS } from '../../visualizations/constants'; @@ -14,7 +14,7 @@ import { STACKED_OPTIONS } from '../../visualizations/constants'; export const newSeriesFn = (obj = {}) => { return _.assign( { - id: uuidv1(), + id: uuidv4(), color: '#68BC00', split_mode: 'everything', palette: { diff --git a/src/plugins/vis_types/timeseries/public/application/components/lib/re_id_series.js b/src/plugins/vis_types/timeseries/public/application/components/lib/re_id_series.js index b24899bf2c52b..4769eb2c9f209 100644 --- a/src/plugins/vis_types/timeseries/public/application/components/lib/re_id_series.js +++ b/src/plugins/vis_types/timeseries/public/application/components/lib/re_id_series.js @@ -6,14 +6,14 @@ * Side Public License, v 1. */ -import { v1 as uuidv1 } from 'uuid'; +import { v4 as uuidv4 } from 'uuid'; import _ from 'lodash'; export const reIdSeries = (source) => { const series = _.cloneDeep(source); - series.id = uuidv1(); + series.id = uuidv4(); series.metrics.forEach((metric) => { - const id = uuidv1(); + const id = uuidv4(); const metricId = metric.id; metric.id = id; if (series.terms_order_by === metricId) series.terms_order_by = id; @@ -24,7 +24,7 @@ export const reIdSeries = (source) => { r.variables .filter((v) => v.field === metricId) .forEach((v) => { - v.id = uuidv1(); + v.id = uuidv4(); v.field = id; }); }); diff --git a/src/plugins/vis_types/timeseries/public/application/components/lib/re_id_series.test.js b/src/plugins/vis_types/timeseries/public/application/components/lib/re_id_series.test.js index 47ea383ad3b1c..af2c017720a3a 100644 --- a/src/plugins/vis_types/timeseries/public/application/components/lib/re_id_series.test.js +++ b/src/plugins/vis_types/timeseries/public/application/components/lib/re_id_series.test.js @@ -6,15 +6,15 @@ * Side Public License, v 1. */ -import { v1 as uuidv1 } from 'uuid'; +import { v4 as uuidv4 } from 'uuid'; import { reIdSeries } from './re_id_series'; describe('reIdSeries()', () => { test('reassign ids for series with just basic metrics', () => { const series = { - id: uuidv1(), - metrics: [{ id: uuidv1() }, { id: uuidv1() }], + id: uuidv4(), + metrics: [{ id: uuidv4() }, { id: uuidv4() }], }; const newSeries = reIdSeries(series); expect(newSeries).not.toEqual(series); @@ -25,10 +25,10 @@ describe('reIdSeries()', () => { }); test('reassign ids for series with just basic metrics and group by', () => { - const firstMetricId = uuidv1(); + const firstMetricId = uuidv4(); const series = { - id: uuidv1(), - metrics: [{ id: firstMetricId }, { id: uuidv1() }], + id: uuidv4(), + metrics: [{ id: firstMetricId }, { id: uuidv4() }], terms_order_by: firstMetricId, }; const newSeries = reIdSeries(series); @@ -41,10 +41,10 @@ describe('reIdSeries()', () => { }); test('reassign ids for series with pipeline metrics', () => { - const firstMetricId = uuidv1(); + const firstMetricId = uuidv4(); const series = { - id: uuidv1(), - metrics: [{ id: firstMetricId }, { id: uuidv1(), field: firstMetricId }], + id: uuidv4(), + metrics: [{ id: firstMetricId }, { id: uuidv4(), field: firstMetricId }], }; const newSeries = reIdSeries(series); expect(newSeries).not.toEqual(series); @@ -53,15 +53,15 @@ describe('reIdSeries()', () => { }); test('reassign ids for series with calculation vars', () => { - const firstMetricId = uuidv1(); + const firstMetricId = uuidv4(); const series = { - id: uuidv1(), + id: uuidv4(), metrics: [ { id: firstMetricId }, { - id: uuidv1(), + id: uuidv4(), type: 'calculation', - variables: [{ id: uuidv1(), field: firstMetricId }], + variables: [{ id: uuidv4(), field: firstMetricId }], }, ], }; diff --git a/src/plugins/vis_types/timeseries/public/application/components/panel_config/gauge.tsx b/src/plugins/vis_types/timeseries/public/application/components/panel_config/gauge.tsx index 7f36d18725ce0..ce8566038f3a2 100644 --- a/src/plugins/vis_types/timeseries/public/application/components/panel_config/gauge.tsx +++ b/src/plugins/vis_types/timeseries/public/application/components/panel_config/gauge.tsx @@ -8,7 +8,7 @@ import { FormattedMessage } from '@kbn/i18n-react'; import { i18n } from '@kbn/i18n'; import React, { Component } from 'react'; -import { v1 as uuidv1 } from 'uuid'; +import { v4 as uuidv4 } from 'uuid'; import { htmlIdGenerator, EuiComboBox, @@ -55,7 +55,7 @@ export class GaugePanelConfig extends Component< const { model } = this.props; const parts: Writable> = {}; if (!model.gauge_color_rules || !model.gauge_color_rules.length) { - parts.gauge_color_rules = [{ id: uuidv1() }]; + parts.gauge_color_rules = [{ id: uuidv4() }]; } if (model.gauge_width == null) parts.gauge_width = 10; if (model.gauge_inner_width == null) parts.gauge_inner_width = 10; diff --git a/src/plugins/vis_types/timeseries/public/application/components/panel_config/metric.tsx b/src/plugins/vis_types/timeseries/public/application/components/panel_config/metric.tsx index 24dec4c94364c..2d1c80ad9e4f2 100644 --- a/src/plugins/vis_types/timeseries/public/application/components/panel_config/metric.tsx +++ b/src/plugins/vis_types/timeseries/public/application/components/panel_config/metric.tsx @@ -8,7 +8,7 @@ import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; import React, { Component } from 'react'; -import { v1 as uuidv1 } from 'uuid'; +import { v4 as uuidv4 } from 'uuid'; import { htmlIdGenerator, EuiTabs, @@ -48,7 +48,7 @@ export class MetricPanelConfig extends Component< (model.background_color_rules && model.background_color_rules.length === 0) ) { this.props.onChange({ - background_color_rules: [{ id: uuidv1() }], + background_color_rules: [{ id: uuidv4() }], }); } } diff --git a/src/plugins/vis_types/timeseries/public/application/components/panel_config/table.tsx b/src/plugins/vis_types/timeseries/public/application/components/panel_config/table.tsx index ce05bb514bef8..56916bc2e1585 100644 --- a/src/plugins/vis_types/timeseries/public/application/components/panel_config/table.tsx +++ b/src/plugins/vis_types/timeseries/public/application/components/panel_config/table.tsx @@ -8,7 +8,7 @@ import React, { Component } from 'react'; import { get } from 'lodash'; -import { v1 as uuidv1 } from 'uuid'; +import { v4 as uuidv4 } from 'uuid'; import { htmlIdGenerator, EuiTabs, @@ -55,7 +55,7 @@ export class TablePanelConfig extends Component< UNSAFE_componentWillMount() { const { model } = this.props; if (!model.bar_color_rules || !model.bar_color_rules.length) { - this.props.onChange({ bar_color_rules: [{ id: uuidv1() }] }); + this.props.onChange({ bar_color_rules: [{ id: uuidv4() }] }); } } diff --git a/src/plugins/vis_types/timeseries/public/application/components/panel_config/top_n.tsx b/src/plugins/vis_types/timeseries/public/application/components/panel_config/top_n.tsx index 8d2273cc54496..422ccb2f455a7 100644 --- a/src/plugins/vis_types/timeseries/public/application/components/panel_config/top_n.tsx +++ b/src/plugins/vis_types/timeseries/public/application/components/panel_config/top_n.tsx @@ -8,7 +8,7 @@ import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; import React, { Component } from 'react'; -import { v1 as uuidv1 } from 'uuid'; +import { v4 as uuidv4 } from 'uuid'; import { htmlIdGenerator, EuiTabs, @@ -48,7 +48,7 @@ export class TopNPanelConfig extends Component< UNSAFE_componentWillMount() { const { model } = this.props; if (!model.bar_color_rules || !model.bar_color_rules.length) { - this.props.onChange({ bar_color_rules: [{ id: uuidv1() }] }); + this.props.onChange({ bar_color_rules: [{ id: uuidv4() }] }); } } diff --git a/src/plugins/vis_types/timeseries/public/application/components/split.js b/src/plugins/vis_types/timeseries/public/application/components/split.js index 9033e570b6943..0eb1d606d6f37 100644 --- a/src/plugins/vis_types/timeseries/public/application/components/split.js +++ b/src/plugins/vis_types/timeseries/public/application/components/split.js @@ -8,7 +8,7 @@ import PropTypes from 'prop-types'; import React, { Component } from 'react'; -import { v1 as uuidv1 } from 'uuid'; +import { v4 as uuidv4 } from 'uuid'; import { get } from 'lodash'; import { SplitByTerms } from './splits/terms'; import { SplitByFilter } from './splits/filter'; @@ -33,7 +33,7 @@ export class Split extends Component { split_filters: [ { color: model.color, - id: uuidv1(), + id: uuidv4(), filter: { query: '', language: getDefaultQueryLanguage(), diff --git a/src/plugins/vis_types/timeseries/public/application/components/splits/filter_items.js b/src/plugins/vis_types/timeseries/public/application/components/splits/filter_items.js index 6a59f85d6180a..680b261c8c89e 100644 --- a/src/plugins/vis_types/timeseries/public/application/components/splits/filter_items.js +++ b/src/plugins/vis_types/timeseries/public/application/components/splits/filter_items.js @@ -12,7 +12,7 @@ import _ from 'lodash'; import { collectionActions } from '../lib/collection_actions'; import { AddDeleteButtons } from '../add_delete_buttons'; import { ColorPicker } from '../color_picker'; -import { v1 as uuidv1 } from 'uuid'; +import { v4 as uuidv4 } from 'uuid'; import { EuiFieldText, EuiFlexGroup, EuiFlexItem, withEuiTheme } from '@elastic/eui'; import { injectI18n } from '@kbn/i18n-react'; import { getDefaultQueryLanguage } from '../lib/get_default_query_language'; @@ -50,7 +50,7 @@ class FilterItemsUi extends Component { const newFilter = () => ({ color: this.props.model.color, - id: uuidv1(), + id: uuidv4(), filter: { language: model.filter.language || getDefaultQueryLanguage(), query: '' }, }); const handleAdd = collectionActions.handleAdd.bind(null, this.props, newFilter); diff --git a/src/plugins/vis_types/timeseries/public/application/components/vis_types/table/config.js b/src/plugins/vis_types/timeseries/public/application/components/vis_types/table/config.js index 99edee5cfefe7..bf9354bfee984 100644 --- a/src/plugins/vis_types/timeseries/public/application/components/vis_types/table/config.js +++ b/src/plugins/vis_types/timeseries/public/application/components/vis_types/table/config.js @@ -8,7 +8,7 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; -import { v1 as uuidv1 } from 'uuid'; +import { v4 as uuidv4 } from 'uuid'; import { i18n } from '@kbn/i18n'; import { last } from 'lodash'; import { KBN_FIELD_TYPES } from '@kbn/data-plugin/public'; @@ -45,7 +45,7 @@ class TableSeriesConfigUi extends Component { const { model } = this.props; if (!model.color_rules || (model.color_rules && model.color_rules.length === 0)) { this.props.onChange({ - color_rules: [{ id: uuidv1() }], + color_rules: [{ id: uuidv4() }], }); } } diff --git a/src/plugins/vis_types/vega/public/components/experimental_map_vis_info.tsx b/src/plugins/vis_types/vega/public/components/experimental_map_vis_info.tsx index e98e0d65bd796..d30c05c33b37b 100644 --- a/src/plugins/vis_types/vega/public/components/experimental_map_vis_info.tsx +++ b/src/plugins/vis_types/vega/public/components/experimental_map_vis_info.tsx @@ -21,7 +21,7 @@ export const ExperimentalMapLayerInfo = () => ( { { })} tooltipContent={i18n.translate('visualizations.listing.experimentalTooltip', { defaultMessage: - 'This functionality is in technical preview and may be changed or removed completely in a future release. Elastic will take a best effort approach to fix any issues, but features in technical preview are not subject to the support SLA of official GA features.', + 'This functionality is in technical preview and may be changed or removed completely in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features.', })} /> ); diff --git a/src/plugins/visualizations/public/wizard/group_selection/group_selection.tsx b/src/plugins/visualizations/public/wizard/group_selection/group_selection.tsx index 911a6fcd70fe7..dc8aaa03161b8 100644 --- a/src/plugins/visualizations/public/wizard/group_selection/group_selection.tsx +++ b/src/plugins/visualizations/public/wizard/group_selection/group_selection.tsx @@ -248,7 +248,7 @@ const ToolsGroup = ({ visType, onVisTypeSelected, showExperimental }: VisCardPro iconType="beaker" tooltipContent={i18n.translate('visualizations.newVisWizard.experimentalTooltip', { defaultMessage: - 'This functionality is in technical preview and may be changed or removed completely in a future release. Elastic will take a best effort approach to fix any issues, but features in technical preview are not subject to the support SLA of official GA features.', + 'This functionality is in technical preview and may be changed or removed completely in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features.', })} label={i18n.translate('visualizations.newVisWizard.experimentalTitle', { defaultMessage: 'Technical preview', diff --git a/test/functional/apps/discover/group4/_esql_view.ts b/test/functional/apps/discover/group4/_esql_view.ts index 212420b56317d..773af0d512309 100644 --- a/test/functional/apps/discover/group4/_esql_view.ts +++ b/test/functional/apps/discover/group4/_esql_view.ts @@ -134,5 +134,32 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { expect(await cell.getVisibleText()).to.be('1'); }); }); + describe('errors', () => { + it('should error messages for syntax errors in query', async function () { + await PageObjects.discover.selectTextBaseLang(); + const brokenQueries = [ + 'from logstash-* | limit 10*', + 'from logstash-* | limit A', + 'from logstash-* | where a*', + 'limit 10', + ]; + for (const testQuery of brokenQueries) { + await monacoEditor.setCodeEditorValue(testQuery); + await testSubjects.click('querySubmitButton'); + await PageObjects.header.waitUntilLoadingHasFinished(); + await PageObjects.discover.waitUntilSearchingHasFinished(); + // error in fetching documents because of the invalid query + await testSubjects.existOrFail('discoverNoResultsError'); + const message = await testSubjects.getVisibleText('discoverErrorCalloutMessage'); + expect(message).to.contain( + "[esql] > Couldn't parse Elasticsearch ES|QL query. Check your query and try again." + ); + expect(message).to.not.contain('undefined'); + if (message.includes('line')) { + expect((await monacoEditor.getCurrentMarkers('kibanaCodeEditor')).length).to.eql(1); + } + } + }); + }); }); } diff --git a/test/functional/services/monaco_editor.ts b/test/functional/services/monaco_editor.ts index 821c334b01c09..a2c4bef456ea7 100644 --- a/test/functional/services/monaco_editor.ts +++ b/test/functional/services/monaco_editor.ts @@ -12,6 +12,7 @@ export class MonacoEditorService extends FtrService { private readonly retry = this.ctx.getService('retry'); private readonly browser = this.ctx.getService('browser'); private readonly testSubjects = this.ctx.getService('testSubjects'); + private readonly findService = this.ctx.getService('find'); public async waitCodeEditorReady(containerTestSubjId: string) { const editorContainer = await this.testSubjects.find(containerTestSubjId); @@ -52,4 +53,10 @@ export class MonacoEditorService extends FtrService { ); }); } + + public async getCurrentMarkers(testSubjId: string) { + return this.findService.allByCssSelector( + `[data-test-subj="${testSubjId}"] .cdr.squiggly-error` + ); + } } diff --git a/test/plugin_functional/test_suites/core_plugins/application_deep_links.ts b/test/plugin_functional/test_suites/core_plugins/application_deep_links.ts index 5b7b561ea1ef2..e4973b05bd955 100644 --- a/test/plugin_functional/test_suites/core_plugins/application_deep_links.ts +++ b/test/plugin_functional/test_suites/core_plugins/application_deep_links.ts @@ -8,11 +8,10 @@ import url from 'url'; import expect from '@kbn/expect'; -import { PluginFunctionalProviderContext } from '../../services'; +import type { PluginFunctionalProviderContext } from '../../services'; export default function ({ getService, getPageObjects }: PluginFunctionalProviderContext) { const PageObjects = getPageObjects(['common']); - const browser = getService('browser'); const appsMenu = getService('appsMenu'); const testSubjects = getService('testSubjects'); @@ -20,8 +19,13 @@ export default function ({ getService, getPageObjects }: PluginFunctionalProvide const esArchiver = getService('esArchiver'); const log = getService('log'); - const loadingScreenNotShown = async () => - expect(await testSubjects.exists('kbnLoadingMessage')).to.be(false); + const clickAppLink = async (app: string) => { + const appLink = `dlNav${app}`; + if (!(await testSubjects.exists(appLink))) { + log.debug(`App ${app} not found on side nav`); + } + await testSubjects.click(appLink); + }; const getKibanaUrl = (pathname?: string, search?: string) => url.format({ @@ -42,65 +46,64 @@ export default function ({ getService, getPageObjects }: PluginFunctionalProvide }); }; - const navigateToAppLinks = async (subject: string) => { - if (!(await testSubjects.exists(subject))) { - log.debug(`side nav in app not in DOM`); - } - await testSubjects.click(subject); + const loadingScreenNotShown = async () => + expect(await testSubjects.exists('kbnLoadingMessage')).to.be(false); + + const checkAppVisible = async (app: string) => { + const appContainer = `dlApp${app}`; + await testSubjects.existOrFail(appContainer); }; - // FLAKY: https://github.com/elastic/kibana/issues/166893 - describe.skip('application deep links navigation', function describeDeepLinksTests() { + describe('application deep links navigation', function describeDeepLinksTests() { before(async () => { await esArchiver.emptyKibanaIndex(); await PageObjects.common.navigateToApp('dl'); }); it('should start on home page', async () => { - await testSubjects.existOrFail('dlAppHome'); + await checkAppVisible('Home'); }); it('should navigate to page A when navlink is clicked', async () => { - await navigateToAppLinks('dlNavPageA'); + await clickAppLink('PageA'); await waitForUrlToBe('/app/dl/page-a'); await loadingScreenNotShown(); - await testSubjects.existOrFail('dlNavPageA'); + await checkAppVisible('PageA'); }); it('should be able to use the back button to navigate back to previous deep link', async () => { await browser.goBack(); await waitForUrlToBe('/app/dl/home'); await loadingScreenNotShown(); - await testSubjects.existOrFail('dlNavHome'); + await checkAppVisible('Home'); }); it('should navigate to nested page B when navlink is clicked', async () => { - await navigateToAppLinks('dlNavDeepPageB'); + await clickAppLink('DeepPageB'); await waitForUrlToBe('/app/dl/page-b'); await loadingScreenNotShown(); - await testSubjects.existOrFail('dlNavDeepPageB'); + await checkAppVisible('PageB'); }); it('should navigate to Home when navlink is clicked inside the defined category group', async () => { - await appsMenu.clickLink('DL Home', { category: 'securitySolution' }); - await navigateToAppLinks('dlAppHome'); + await clickAppLink('Home'); await waitForUrlToBe('/app/dl/home'); await loadingScreenNotShown(); - await testSubjects.existOrFail('dlAppHome'); + await checkAppVisible('Home'); }); it('should navigate to nested page B using navigateToApp path', async () => { - await testSubjects.click('dlNavDeepPageB'); + await clickAppLink('DeepPageB'); await waitForUrlToBe('/app/dl/page-b'); await loadingScreenNotShown(); - await testSubjects.existOrFail('dlNavDeepPageB'); + await checkAppVisible('PageB'); }); it('should navigate to nested page A using navigateToApp deepLinkId', async () => { - await testSubjects.click('dlNavDeepPageAById'); + await clickAppLink('DeepPageAById'); await waitForUrlToBe('/app/dl/page-a'); await loadingScreenNotShown(); - await testSubjects.existOrFail('dlNavPageA'); + await checkAppVisible('PageA'); }); it('should not display hidden deep links', async () => { diff --git a/tsconfig.base.json b/tsconfig.base.json index b9711f0bc5bdc..428307c5d9894 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -1346,12 +1346,8 @@ "@kbn/shared-svg/*": ["packages/kbn-shared-svg/*"], "@kbn/shared-ux-avatar-solution": ["packages/shared-ux/avatar/solution"], "@kbn/shared-ux-avatar-solution/*": ["packages/shared-ux/avatar/solution/*"], - "@kbn/shared-ux-button-exit-full-screen": ["packages/shared-ux/button/exit_full_screen/impl"], - "@kbn/shared-ux-button-exit-full-screen/*": ["packages/shared-ux/button/exit_full_screen/impl/*"], - "@kbn/shared-ux-button-exit-full-screen-mocks": ["packages/shared-ux/button/exit_full_screen/mocks"], - "@kbn/shared-ux-button-exit-full-screen-mocks/*": ["packages/shared-ux/button/exit_full_screen/mocks/*"], - "@kbn/shared-ux-button-exit-full-screen-types": ["packages/shared-ux/button/exit_full_screen/types"], - "@kbn/shared-ux-button-exit-full-screen-types/*": ["packages/shared-ux/button/exit_full_screen/types/*"], + "@kbn/shared-ux-button-exit-full-screen": ["packages/shared-ux/button/exit_full_screen"], + "@kbn/shared-ux-button-exit-full-screen/*": ["packages/shared-ux/button/exit_full_screen/*"], "@kbn/shared-ux-button-toolbar": ["packages/shared-ux/button_toolbar"], "@kbn/shared-ux-button-toolbar/*": ["packages/shared-ux/button_toolbar/*"], "@kbn/shared-ux-card-no-data": ["packages/shared-ux/card/no_data/impl"], @@ -1729,4 +1725,4 @@ "@kbn/ambient-storybook-types" ], } -} \ No newline at end of file +} diff --git a/x-pack/.i18nrc.json b/x-pack/.i18nrc.json index bcca0b5e14318..923d0cce0759d 100644 --- a/x-pack/.i18nrc.json +++ b/x-pack/.i18nrc.json @@ -51,6 +51,7 @@ "xpack.logstash": ["plugins/logstash"], "xpack.main": "legacy/plugins/xpack_main", "xpack.maps": ["plugins/maps"], + "xpack.metricsData": "plugins/metrics_data_access", "xpack.ml": [ "packages/ml/anomaly_utils", "packages/ml/data_grid", diff --git a/x-pack/plugins/actions/docs/openapi/bundled.json b/x-pack/plugins/actions/docs/openapi/bundled.json index 06ef16a71f200..1508ff2c1e077 100644 --- a/x-pack/plugins/actions/docs/openapi/bundled.json +++ b/x-pack/plugins/actions/docs/openapi/bundled.json @@ -14,8 +14,7 @@ }, "servers": [ { - "url": "http://localhost:5601", - "description": "local" + "url": "/" } ], "security": [ @@ -97,18 +96,8 @@ "401": { "$ref": "#/components/responses/401" } - }, - "servers": [ - { - "url": "https://localhost:5601" - } - ] - }, - "servers": [ - { - "url": "https://localhost:5601" } - ] + } }, "/api/actions/connector/{connectorId}": { "get": { @@ -144,12 +133,7 @@ "404": { "$ref": "#/components/responses/404" } - }, - "servers": [ - { - "url": "https://localhost:5601" - } - ] + } }, "delete": { "summary": "Deletes a connector.", @@ -175,12 +159,7 @@ "404": { "$ref": "#/components/responses/404" } - }, - "servers": [ - { - "url": "https://localhost:5601" - } - ] + } }, "post": { "summary": "Creates a connector.", @@ -237,12 +216,7 @@ "401": { "$ref": "#/components/responses/401" } - }, - "servers": [ - { - "url": "https://localhost:5601" - } - ] + } }, "put": { "summary": "Updates the attributes for a connector.", @@ -293,18 +267,8 @@ "404": { "$ref": "#/components/responses/404" } - }, - "servers": [ - { - "url": "https://localhost:5601" - } - ] - }, - "servers": [ - { - "url": "https://localhost:5601" } - ] + } }, "/api/actions/connector/{connectorId}/_execute": { "post": { @@ -414,18 +378,8 @@ "401": { "$ref": "#/components/responses/401" } - }, - "servers": [ - { - "url": "https://localhost:5601" - } - ] - }, - "servers": [ - { - "url": "https://localhost:5601" } - ] + } }, "/api/actions/connectors": { "get": { @@ -456,18 +410,8 @@ "401": { "$ref": "#/components/responses/401" } - }, - "servers": [ - { - "url": "https://localhost:5601" - } - ] - }, - "servers": [ - { - "url": "https://localhost:5601" } - ] + } }, "/api/actions/connector_types": { "get": { @@ -556,18 +500,8 @@ "401": { "$ref": "#/components/responses/401" } - }, - "servers": [ - { - "url": "https://localhost:5601" - } - ] - }, - "servers": [ - { - "url": "https://localhost:5601" } - ] + } }, "/s/{spaceId}/api/actions/connector": { "post": { @@ -637,18 +571,8 @@ "401": { "$ref": "#/components/responses/401" } - }, - "servers": [ - { - "url": "https://localhost:5601" - } - ] - }, - "servers": [ - { - "url": "https://localhost:5601" } - ] + } }, "/s/{spaceId}/api/actions/connector/{connectorId}": { "get": { @@ -688,12 +612,7 @@ "404": { "$ref": "#/components/responses/404" } - }, - "servers": [ - { - "url": "https://localhost:5601" - } - ] + } }, "delete": { "summary": "Deletes a connector.", @@ -723,12 +642,7 @@ "404": { "$ref": "#/components/responses/404" } - }, - "servers": [ - { - "url": "https://localhost:5601" - } - ] + } }, "post": { "summary": "Creates a connector.", @@ -789,12 +703,7 @@ "401": { "$ref": "#/components/responses/401" } - }, - "servers": [ - { - "url": "https://localhost:5601" - } - ] + } }, "put": { "summary": "Updates the attributes for a connector.", @@ -849,18 +758,8 @@ "404": { "$ref": "#/components/responses/404" } - }, - "servers": [ - { - "url": "https://localhost:5601" - } - ] - }, - "servers": [ - { - "url": "https://localhost:5601" } - ] + } }, "/s/{spaceId}/api/actions/connectors": { "get": { @@ -897,18 +796,8 @@ "401": { "$ref": "#/components/responses/401" } - }, - "servers": [ - { - "url": "https://localhost:5601" - } - ] - }, - "servers": [ - { - "url": "https://localhost:5601" } - ] + } }, "/s/{spaceId}/api/actions/connector_types": { "get": { @@ -997,18 +886,8 @@ "401": { "$ref": "#/components/responses/401" } - }, - "servers": [ - { - "url": "https://localhost:5601" - } - ] - }, - "servers": [ - { - "url": "https://localhost:5601" } - ] + } }, "/s/{spaceId}/api/actions/connector/{connectorId}/_execute": { "post": { @@ -1121,18 +1000,8 @@ "401": { "$ref": "#/components/responses/401" } - }, - "servers": [ - { - "url": "https://localhost:5601" - } - ] - }, - "servers": [ - { - "url": "https://localhost:5601" } - ] + } }, "/s/{spaceId}/api/actions/action/{actionId}": { "delete": { @@ -1161,12 +1030,7 @@ "401": { "$ref": "#/components/responses/401" } - }, - "servers": [ - { - "url": "https://localhost:5601" - } - ] + } }, "get": { "summary": "Retrieves a connector by ID.", @@ -1191,12 +1055,7 @@ "401": { "$ref": "#/components/responses/401" } - }, - "servers": [ - { - "url": "https://localhost:5601" - } - ] + } }, "put": { "summary": "Updates the attributes for a connector.", @@ -1250,18 +1109,8 @@ "404": { "$ref": "#/components/responses/404" } - }, - "servers": [ - { - "url": "https://localhost:5601" - } - ] - }, - "servers": [ - { - "url": "https://localhost:5601" } - ] + } }, "/s/{spaceId}/api/actions": { "get": { @@ -1294,12 +1143,7 @@ "401": { "$ref": "#/components/responses/401" } - }, - "servers": [ - { - "url": "https://localhost:5601" - } - ] + } }, "post": { "summary": "Creates a connector.", @@ -1353,18 +1197,8 @@ "401": { "$ref": "#/components/responses/401" } - }, - "servers": [ - { - "url": "https://localhost:5601" - } - ] - }, - "servers": [ - { - "url": "https://localhost:5601" } - ] + } }, "/s/{spaceId}/api/actions/list_action_types": { "get": { @@ -1426,18 +1260,8 @@ "401": { "$ref": "#/components/responses/401" } - }, - "servers": [ - { - "url": "https://localhost:5601" - } - ] - }, - "servers": [ - { - "url": "https://localhost:5601" } - ] + } }, "/s/{spaceId}/api/actions/action/{actionId}/_execute": { "post": { @@ -1519,18 +1343,8 @@ "401": { "$ref": "#/components/responses/401" } - }, - "servers": [ - { - "url": "https://localhost:5601" - } - ] - }, - "servers": [ - { - "url": "https://localhost:5601" } - ] + } } }, "components": { diff --git a/x-pack/plugins/actions/docs/openapi/bundled.yaml b/x-pack/plugins/actions/docs/openapi/bundled.yaml index 099757a354f9e..9f5dd7e1107e2 100644 --- a/x-pack/plugins/actions/docs/openapi/bundled.yaml +++ b/x-pack/plugins/actions/docs/openapi/bundled.yaml @@ -9,8 +9,7 @@ info: name: Elastic License 2.0 url: https://www.elastic.co/licensing/elastic-license servers: - - url: http://localhost:5601 - description: local + - url: / security: - basicAuth: [] - apiKeyAuth: [] @@ -59,10 +58,6 @@ paths: $ref: '#/components/examples/create_xmatters_connector_response' '401': $ref: '#/components/responses/401' - servers: - - url: https://localhost:5601 - servers: - - url: https://localhost:5601 /api/actions/connector/{connectorId}: get: summary: Retrieves a connector by ID. @@ -85,8 +80,6 @@ paths: $ref: '#/components/responses/401' '404': $ref: '#/components/responses/404' - servers: - - url: https://localhost:5601 delete: summary: Deletes a connector. operationId: deleteConnector @@ -102,8 +95,6 @@ paths: $ref: '#/components/responses/401' '404': $ref: '#/components/responses/404' - servers: - - url: https://localhost:5601 post: summary: Creates a connector. operationId: createConnectorId @@ -140,8 +131,6 @@ paths: $ref: '#/components/examples/create_index_connector_response' '401': $ref: '#/components/responses/401' - servers: - - url: https://localhost:5601 put: summary: Updates the attributes for a connector. operationId: updateConnector @@ -172,10 +161,6 @@ paths: $ref: '#/components/responses/401' '404': $ref: '#/components/responses/404' - servers: - - url: https://localhost:5601 - servers: - - url: https://localhost:5601 /api/actions/connector/{connectorId}/_execute: post: summary: Runs a connector. @@ -246,10 +231,6 @@ paths: $ref: '#/components/examples/run_swimlane_connector_response' '401': $ref: '#/components/responses/401' - servers: - - url: https://localhost:5601 - servers: - - url: https://localhost:5601 /api/actions/connectors: get: summary: Retrieves all connectors. @@ -270,10 +251,6 @@ paths: $ref: '#/components/examples/get_connectors_response' '401': $ref: '#/components/responses/401' - servers: - - url: https://localhost:5601 - servers: - - url: https://localhost:5601 /api/actions/connector_types: get: summary: Retrieves a list of all connector types. @@ -337,10 +314,6 @@ paths: $ref: '#/components/examples/get_connector_types_generativeai_response' '401': $ref: '#/components/responses/401' - servers: - - url: https://localhost:5601 - servers: - - url: https://localhost:5601 /s/{spaceId}/api/actions/connector: post: summary: Creates a connector. @@ -385,10 +358,6 @@ paths: $ref: '#/components/examples/create_xmatters_connector_response' '401': $ref: '#/components/responses/401' - servers: - - url: https://localhost:5601 - servers: - - url: https://localhost:5601 /s/{spaceId}/api/actions/connector/{connectorId}: get: summary: Retrieves a connector by ID. @@ -414,8 +383,6 @@ paths: $ref: '#/components/responses/401' '404': $ref: '#/components/responses/404' - servers: - - url: https://localhost:5601 delete: summary: Deletes a connector. operationId: deleteConnectorWithSpaceId @@ -434,8 +401,6 @@ paths: $ref: '#/components/responses/401' '404': $ref: '#/components/responses/404' - servers: - - url: https://localhost:5601 post: summary: Creates a connector. operationId: createConnectorIdWithSpaceId @@ -474,8 +439,6 @@ paths: $ref: '#/components/examples/create_index_connector_response' '401': $ref: '#/components/responses/401' - servers: - - url: https://localhost:5601 put: summary: Updates the attributes for a connector. operationId: updateConnectorWithSpaceId @@ -509,10 +472,6 @@ paths: $ref: '#/components/responses/401' '404': $ref: '#/components/responses/404' - servers: - - url: https://localhost:5601 - servers: - - url: https://localhost:5601 /s/{spaceId}/api/actions/connectors: get: summary: Retrieves all connectors. @@ -537,10 +496,6 @@ paths: $ref: '#/components/examples/get_connectors_response' '401': $ref: '#/components/responses/401' - servers: - - url: https://localhost:5601 - servers: - - url: https://localhost:5601 /s/{spaceId}/api/actions/connector_types: get: summary: Retrieves a list of all connector types. @@ -604,10 +559,6 @@ paths: $ref: '#/components/examples/get_connector_types_response' '401': $ref: '#/components/responses/401' - servers: - - url: https://localhost:5601 - servers: - - url: https://localhost:5601 /s/{spaceId}/api/actions/connector/{connectorId}/_execute: post: summary: Runs a connector. @@ -679,10 +630,6 @@ paths: $ref: '#/components/examples/run_swimlane_connector_response' '401': $ref: '#/components/responses/401' - servers: - - url: https://localhost:5601 - servers: - - url: https://localhost:5601 /s/{spaceId}/api/actions/action/{actionId}: delete: summary: Deletes a connector. @@ -701,8 +648,6 @@ paths: description: Indicates a successful call. '401': $ref: '#/components/responses/401' - servers: - - url: https://localhost:5601 get: summary: Retrieves a connector by ID. operationId: legacyGetConnector @@ -718,8 +663,6 @@ paths: $ref: '#/components/responses/200_actions' '401': $ref: '#/components/responses/401' - servers: - - url: https://localhost:5601 put: summary: Updates the attributes for a connector. operationId: legacyUpdateConnector @@ -754,10 +697,6 @@ paths: $ref: '#/components/responses/200_actions' '404': $ref: '#/components/responses/404' - servers: - - url: https://localhost:5601 - servers: - - url: https://localhost:5601 /s/{spaceId}/api/actions: get: summary: Retrieves all connectors. @@ -779,8 +718,6 @@ paths: $ref: '#/components/schemas/action_response_properties' '401': $ref: '#/components/responses/401' - servers: - - url: https://localhost:5601 post: summary: Creates a connector. operationId: legacyCreateConnector @@ -817,10 +754,6 @@ paths: $ref: '#/components/responses/200_actions' '401': $ref: '#/components/responses/401' - servers: - - url: https://localhost:5601 - servers: - - url: https://localhost:5601 /s/{spaceId}/api/actions/list_action_types: get: summary: Retrieves a list of all connector types. @@ -864,10 +797,6 @@ paths: description: The name of the connector type. '401': $ref: '#/components/responses/401' - servers: - - url: https://localhost:5601 - servers: - - url: https://localhost:5601 /s/{spaceId}/api/actions/action/{actionId}/_execute: post: summary: Runs a connector. @@ -918,10 +847,6 @@ paths: description: The status of the action. '401': $ref: '#/components/responses/401' - servers: - - url: https://localhost:5601 - servers: - - url: https://localhost:5601 components: securitySchemes: basicAuth: diff --git a/x-pack/plugins/actions/docs/openapi/bundled_serverless.json b/x-pack/plugins/actions/docs/openapi/bundled_serverless.json index 25d7b7484ae8d..dadcc4cc08767 100644 --- a/x-pack/plugins/actions/docs/openapi/bundled_serverless.json +++ b/x-pack/plugins/actions/docs/openapi/bundled_serverless.json @@ -14,8 +14,12 @@ }, "servers": [ { - "url": "http://localhost:5601", - "description": "local" + "url": "https://{kibanaUrl}", + "variables": { + "kibanaUrl": { + "default": "localhost:5601" + } + } } ], "security": [ @@ -94,18 +98,8 @@ "401": { "$ref": "#/components/responses/401" } - }, - "servers": [ - { - "url": "https://localhost:5601" - } - ] - }, - "servers": [ - { - "url": "https://localhost:5601" } - ] + } }, "/api/actions/connector/{connectorId}": { "get": { @@ -141,12 +135,7 @@ "404": { "$ref": "#/components/responses/404" } - }, - "servers": [ - { - "url": "https://localhost:5601" - } - ] + } }, "delete": { "summary": "Deletes a connector.", @@ -172,12 +161,7 @@ "404": { "$ref": "#/components/responses/404" } - }, - "servers": [ - { - "url": "https://localhost:5601" - } - ] + } }, "post": { "summary": "Creates a connector.", @@ -234,12 +218,7 @@ "401": { "$ref": "#/components/responses/401" } - }, - "servers": [ - { - "url": "https://localhost:5601" - } - ] + } }, "put": { "summary": "Updates the attributes for a connector.", @@ -290,18 +269,8 @@ "404": { "$ref": "#/components/responses/404" } - }, - "servers": [ - { - "url": "https://localhost:5601" - } - ] - }, - "servers": [ - { - "url": "https://localhost:5601" } - ] + } }, "/api/actions/connectors": { "get": { @@ -332,18 +301,8 @@ "401": { "$ref": "#/components/responses/401" } - }, - "servers": [ - { - "url": "https://localhost:5601" - } - ] - }, - "servers": [ - { - "url": "https://localhost:5601" } - ] + } }, "/api/actions/connector_types": { "get": { @@ -432,18 +391,8 @@ "401": { "$ref": "#/components/responses/401" } - }, - "servers": [ - { - "url": "https://localhost:5601" - } - ] - }, - "servers": [ - { - "url": "https://localhost:5601" } - ] + } } }, "components": { diff --git a/x-pack/plugins/actions/docs/openapi/bundled_serverless.yaml b/x-pack/plugins/actions/docs/openapi/bundled_serverless.yaml index b66a820c1b77d..fbe684c35fe48 100644 --- a/x-pack/plugins/actions/docs/openapi/bundled_serverless.yaml +++ b/x-pack/plugins/actions/docs/openapi/bundled_serverless.yaml @@ -9,8 +9,10 @@ info: name: Elastic License 2.0 url: https://www.elastic.co/licensing/elastic-license servers: - - url: http://localhost:5601 - description: local + - url: https://{kibanaUrl} + variables: + kibanaUrl: + default: localhost:5601 security: - apiKeyAuth: [] tags: @@ -58,10 +60,6 @@ paths: $ref: '#/components/examples/create_xmatters_connector_response' '401': $ref: '#/components/responses/401' - servers: - - url: https://localhost:5601 - servers: - - url: https://localhost:5601 /api/actions/connector/{connectorId}: get: summary: Retrieves a connector by ID. @@ -84,8 +82,6 @@ paths: $ref: '#/components/responses/401' '404': $ref: '#/components/responses/404' - servers: - - url: https://localhost:5601 delete: summary: Deletes a connector. operationId: deleteConnector @@ -101,8 +97,6 @@ paths: $ref: '#/components/responses/401' '404': $ref: '#/components/responses/404' - servers: - - url: https://localhost:5601 post: summary: Creates a connector. operationId: createConnectorId @@ -139,8 +133,6 @@ paths: $ref: '#/components/examples/create_index_connector_response' '401': $ref: '#/components/responses/401' - servers: - - url: https://localhost:5601 put: summary: Updates the attributes for a connector. operationId: updateConnector @@ -171,10 +163,6 @@ paths: $ref: '#/components/responses/401' '404': $ref: '#/components/responses/404' - servers: - - url: https://localhost:5601 - servers: - - url: https://localhost:5601 /api/actions/connectors: get: summary: Retrieves all connectors. @@ -195,10 +183,6 @@ paths: $ref: '#/components/examples/get_connectors_response' '401': $ref: '#/components/responses/401' - servers: - - url: https://localhost:5601 - servers: - - url: https://localhost:5601 /api/actions/connector_types: get: summary: Retrieves a list of all connector types. @@ -262,10 +246,6 @@ paths: $ref: '#/components/examples/get_connector_types_generativeai_response' '401': $ref: '#/components/responses/401' - servers: - - url: https://localhost:5601 - servers: - - url: https://localhost:5601 components: securitySchemes: apiKeyAuth: diff --git a/x-pack/plugins/actions/docs/openapi/entrypoint.yaml b/x-pack/plugins/actions/docs/openapi/entrypoint.yaml index 1f85d4a44c37b..bdbf408de3e1a 100644 --- a/x-pack/plugins/actions/docs/openapi/entrypoint.yaml +++ b/x-pack/plugins/actions/docs/openapi/entrypoint.yaml @@ -12,8 +12,7 @@ tags: - name: connectors description: Connector APIs enable you to create and manage connectors. servers: - - url: 'http://localhost:5601' - description: local + - url: / paths: '/api/actions/connector': $ref: 'paths/api@actions@connector.yaml' diff --git a/x-pack/plugins/actions/docs/openapi/entrypoint_serverless.yaml b/x-pack/plugins/actions/docs/openapi/entrypoint_serverless.yaml index 1cfccf790903a..3503221c4e306 100644 --- a/x-pack/plugins/actions/docs/openapi/entrypoint_serverless.yaml +++ b/x-pack/plugins/actions/docs/openapi/entrypoint_serverless.yaml @@ -12,8 +12,10 @@ tags: - name: connectors description: Connector APIs enable you to create and manage connectors. servers: - - url: 'http://localhost:5601' - description: local + - url: https://{kibanaUrl} + variables: + kibanaUrl: + default: localhost:5601 paths: '/api/actions/connector': $ref: 'paths/api@actions@connector.yaml' diff --git a/x-pack/plugins/actions/docs/openapi/paths/api@actions@connector.yaml b/x-pack/plugins/actions/docs/openapi/paths/api@actions@connector.yaml index 9c5e69a53e24f..c6634bb6ea532 100644 --- a/x-pack/plugins/actions/docs/openapi/paths/api@actions@connector.yaml +++ b/x-pack/plugins/actions/docs/openapi/paths/api@actions@connector.yaml @@ -38,7 +38,3 @@ post: $ref: '../components/examples/create_xmatters_connector_response.yaml' '401': $ref: '../components/responses/401.yaml' - servers: - - url: https://localhost:5601 -servers: - - url: https://localhost:5601 diff --git a/x-pack/plugins/actions/docs/openapi/paths/api@actions@connector@{connectorid}.yaml b/x-pack/plugins/actions/docs/openapi/paths/api@actions@connector@{connectorid}.yaml index f9f483f747635..e4b8e1c468643 100644 --- a/x-pack/plugins/actions/docs/openapi/paths/api@actions@connector@{connectorid}.yaml +++ b/x-pack/plugins/actions/docs/openapi/paths/api@actions@connector@{connectorid}.yaml @@ -19,8 +19,6 @@ get: $ref: '../components/responses/401.yaml' '404': $ref: '../components/responses/404.yaml' - servers: - - url: https://localhost:5601 delete: summary: Deletes a connector. @@ -37,8 +35,6 @@ delete: $ref: '../components/responses/401.yaml' '404': $ref: '../components/responses/404.yaml' - servers: - - url: https://localhost:5601 post: summary: Creates a connector. @@ -77,8 +73,6 @@ post: $ref: '../components/examples/create_index_connector_response.yaml' '401': $ref: '../components/responses/401.yaml' - servers: - - url: https://localhost:5601 put: summary: Updates the attributes for a connector. @@ -110,7 +104,3 @@ put: $ref: '../components/responses/401.yaml' '404': $ref: '../components/responses/404.yaml' - servers: - - url: https://localhost:5601 -servers: - - url: https://localhost:5601 diff --git a/x-pack/plugins/actions/docs/openapi/paths/api@actions@connector@{connectorid}@_execute.yaml b/x-pack/plugins/actions/docs/openapi/paths/api@actions@connector@{connectorid}@_execute.yaml index a876584ca4e8e..7e7d0b8956853 100644 --- a/x-pack/plugins/actions/docs/openapi/paths/api@actions@connector@{connectorid}@_execute.yaml +++ b/x-pack/plugins/actions/docs/openapi/paths/api@actions@connector@{connectorid}@_execute.yaml @@ -69,7 +69,3 @@ post: $ref: '../components/examples/run_swimlane_connector_response.yaml' '401': $ref: '../components/responses/401.yaml' - servers: - - url: https://localhost:5601 -servers: - - url: https://localhost:5601 diff --git a/x-pack/plugins/actions/docs/openapi/paths/api@actions@connector_types.yaml b/x-pack/plugins/actions/docs/openapi/paths/api@actions@connector_types.yaml index 30247d47b24c9..530fed05e3046 100644 --- a/x-pack/plugins/actions/docs/openapi/paths/api@actions@connector_types.yaml +++ b/x-pack/plugins/actions/docs/openapi/paths/api@actions@connector_types.yaml @@ -59,8 +59,4 @@ get: getConnectorTypesServerlessResponse: $ref: '../components/examples/get_connector_types_generativeai_response.yaml' '401': - $ref: '../components/responses/401.yaml' - servers: - - url: https://localhost:5601 -servers: - - url: https://localhost:5601 + $ref: '../components/responses/401.yaml' \ No newline at end of file diff --git a/x-pack/plugins/actions/docs/openapi/paths/api@actions@connectors.yaml b/x-pack/plugins/actions/docs/openapi/paths/api@actions@connectors.yaml index b350251dde206..82b83651644e7 100644 --- a/x-pack/plugins/actions/docs/openapi/paths/api@actions@connectors.yaml +++ b/x-pack/plugins/actions/docs/openapi/paths/api@actions@connectors.yaml @@ -16,8 +16,4 @@ get: getConnectorsResponse: $ref: '../components/examples/get_connectors_response.yaml' '401': - $ref: '../components/responses/401.yaml' - servers: - - url: https://localhost:5601 -servers: - - url: https://localhost:5601 + $ref: '../components/responses/401.yaml' \ No newline at end of file diff --git a/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions.yaml b/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions.yaml index 90fa92580794c..aad5ca61ac3be 100644 --- a/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions.yaml +++ b/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions.yaml @@ -18,8 +18,6 @@ get: $ref: '../components/schemas/action_response_properties.yaml' '401': $ref: '../components/responses/401.yaml' - servers: - - url: https://localhost:5601 post: summary: Creates a connector. @@ -58,9 +56,4 @@ post: '200': $ref: '../components/responses/200_actions.yaml' '401': - $ref: '../components/responses/401.yaml' - servers: - - url: https://localhost:5601 -servers: - - url: https://localhost:5601 - + $ref: '../components/responses/401.yaml' \ No newline at end of file diff --git a/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions@action@{actionid}.yaml b/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions@action@{actionid}.yaml index 635a4046cb862..dcf7a2759a35a 100644 --- a/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions@action@{actionid}.yaml +++ b/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions@action@{actionid}.yaml @@ -16,8 +16,6 @@ delete: description: Indicates a successful call. '401': $ref: '../components/responses/401.yaml' - servers: - - url: https://localhost:5601 get: summary: Retrieves a connector by ID. @@ -34,8 +32,6 @@ get: $ref: '../components/responses/200_actions.yaml' '401': $ref: '../components/responses/401.yaml' - servers: - - url: https://localhost:5601 put: summary: Updates the attributes for a connector. @@ -71,8 +67,3 @@ put: $ref: '../components/responses/200_actions.yaml' '404': $ref: '../components/responses/404.yaml' - servers: - - url: https://localhost:5601 - -servers: - - url: https://localhost:5601 diff --git a/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions@action@{actionid}@_execute.yaml b/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions@action@{actionid}@_execute.yaml index ddda64ddec11e..9fe5cedda84de 100644 --- a/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions@action@{actionid}@_execute.yaml +++ b/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions@action@{actionid}@_execute.yaml @@ -46,8 +46,4 @@ post: type: string description: The status of the action. '401': - $ref: '../components/responses/401.yaml' - servers: - - url: https://localhost:5601 -servers: - - url: https://localhost:5601 + $ref: '../components/responses/401.yaml' \ 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 86e8cc1d0bfe0..f116a699ed868 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,8 +40,4 @@ post: createXmattersConnectorResponse: $ref: '../components/examples/create_xmatters_connector_response.yaml' '401': - $ref: '../components/responses/401.yaml' - servers: - - url: https://localhost:5601 -servers: - - url: https://localhost:5601 + $ref: '../components/responses/401.yaml' \ No newline at end of file diff --git a/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions@connector@{connectorid}.yaml b/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions@connector@{connectorid}.yaml index 0edbd0a0ed2d1..1d014404a643a 100644 --- a/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions@connector@{connectorid}.yaml +++ b/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions@connector@{connectorid}.yaml @@ -22,8 +22,6 @@ get: $ref: '../components/responses/401.yaml' '404': $ref: '../components/responses/404.yaml' - servers: - - url: https://localhost:5601 delete: summary: Deletes a connector. @@ -44,8 +42,6 @@ delete: $ref: '../components/responses/401.yaml' '404': $ref: '../components/responses/404.yaml' - servers: - - url: https://localhost:5601 post: summary: Creates a connector. @@ -85,8 +81,6 @@ post: $ref: '../components/examples/create_index_connector_response.yaml' '401': $ref: '../components/responses/401.yaml' - servers: - - url: https://localhost:5601 put: summary: Updates the attributes for a connector. @@ -120,8 +114,4 @@ put: '401': $ref: '../components/responses/401.yaml' '404': - $ref: '../components/responses/404.yaml' - servers: - - url: https://localhost:5601 -servers: - - url: https://localhost:5601 + $ref: '../components/responses/404.yaml' \ No newline at end of file diff --git a/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions@connector@{connectorid}@_execute.yaml b/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions@connector@{connectorid}@_execute.yaml index f94419bcae81d..be5fbd42e588a 100644 --- a/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions@connector@{connectorid}@_execute.yaml +++ b/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions@connector@{connectorid}@_execute.yaml @@ -69,8 +69,4 @@ post: runSwimlaneConnectorResponse: $ref: '../components/examples/run_swimlane_connector_response.yaml' '401': - $ref: '../components/responses/401.yaml' - servers: - - url: https://localhost:5601 -servers: - - url: https://localhost:5601 + $ref: '../components/responses/401.yaml' \ No newline at end of file diff --git a/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions@connector_types.yaml b/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions@connector_types.yaml index 1dfdfe775a292..86ef1cd5460f1 100644 --- a/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions@connector_types.yaml +++ b/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions@connector_types.yaml @@ -59,8 +59,4 @@ get: getConnectorTypesResponse: $ref: '../components/examples/get_connector_types_response.yaml' '401': - $ref: '../components/responses/401.yaml' - servers: - - url: https://localhost:5601 -servers: - - url: https://localhost:5601 + $ref: '../components/responses/401.yaml' \ No newline at end of file diff --git a/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions@connectors.yaml b/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions@connectors.yaml index 7f5d5944ba520..7670187845710 100644 --- a/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions@connectors.yaml +++ b/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions@connectors.yaml @@ -20,8 +20,4 @@ get: getConnectorsResponse: $ref: '../components/examples/get_connectors_response.yaml' '401': - $ref: '../components/responses/401.yaml' - servers: - - url: https://localhost:5601 -servers: - - url: https://localhost:5601 + $ref: '../components/responses/401.yaml' \ No newline at end of file diff --git a/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions@list_action_types.yaml b/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions@list_action_types.yaml index f4118e8d83230..edda7d4aca310 100644 --- a/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions@list_action_types.yaml +++ b/x-pack/plugins/actions/docs/openapi/paths/s@{spaceid}@api@actions@list_action_types.yaml @@ -39,8 +39,4 @@ get: type: string description: The name of the connector type. '401': - $ref: '../components/responses/401.yaml' - servers: - - url: https://localhost:5601 -servers: - - url: https://localhost:5601 + $ref: '../components/responses/401.yaml' \ No newline at end of file diff --git a/x-pack/plugins/aiops/public/components/log_categorization/technical_preview_badge/technical_preview_badge.tsx b/x-pack/plugins/aiops/public/components/log_categorization/technical_preview_badge/technical_preview_badge.tsx index 1d077eb636c5a..8467b1e8e5080 100644 --- a/x-pack/plugins/aiops/public/components/log_categorization/technical_preview_badge/technical_preview_badge.tsx +++ b/x-pack/plugins/aiops/public/components/log_categorization/technical_preview_badge/technical_preview_badge.tsx @@ -21,7 +21,7 @@ export const TechnicalPreviewBadge: FC = () => { color="hollow" tooltipContent={i18n.translate('xpack.aiops.techPreviewBadge.tooltip', { defaultMessage: - 'This functionality is in technical preview and may be changed or removed completely in a future release. Elastic will take a best effort approach to fix any issues, but features in technical preview are not subject to the support SLA of official GA features.', + 'This functionality is in technical preview and may be changed or removed completely in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features.', })} tooltipPosition={'right'} /> diff --git a/x-pack/plugins/alerting/common/routes/r_rule/response/schemas/v1.ts b/x-pack/plugins/alerting/common/routes/r_rule/response/schemas/v1.ts index 0b32b61746ec9..13cb7cb3824f4 100644 --- a/x-pack/plugins/alerting/common/routes/r_rule/response/schemas/v1.ts +++ b/x-pack/plugins/alerting/common/routes/r_rule/response/schemas/v1.ts @@ -38,10 +38,10 @@ export const rRuleResponseSchema = schema.object({ byweekday: schema.maybe(schema.arrayOf(schema.oneOf([schema.string(), schema.number()]))), bymonth: schema.maybe(schema.arrayOf(schema.number())), bysetpos: schema.maybe(schema.arrayOf(schema.number())), - bymonthday: schema.arrayOf(schema.number()), - byyearday: schema.arrayOf(schema.number()), - byweekno: schema.arrayOf(schema.number()), - byhour: schema.arrayOf(schema.number()), - byminute: schema.arrayOf(schema.number()), - bysecond: schema.arrayOf(schema.number()), + bymonthday: schema.maybe(schema.arrayOf(schema.number())), + byyearday: schema.maybe(schema.arrayOf(schema.number())), + byweekno: schema.maybe(schema.arrayOf(schema.number())), + byhour: schema.maybe(schema.arrayOf(schema.number())), + byminute: schema.maybe(schema.arrayOf(schema.number())), + bysecond: schema.maybe(schema.arrayOf(schema.number())), }); diff --git a/x-pack/plugins/alerting/common/routes/rule/apis/bulk_edit/index.ts b/x-pack/plugins/alerting/common/routes/rule/apis/bulk_edit/index.ts index 1ae4a238cbf21..801e13088fab6 100644 --- a/x-pack/plugins/alerting/common/routes/rule/apis/bulk_edit/index.ts +++ b/x-pack/plugins/alerting/common/routes/rule/apis/bulk_edit/index.ts @@ -5,24 +5,14 @@ * 2.0. */ -export { - ruleSnoozeScheduleSchema, - bulkEditOperationsSchema, - bulkEditRulesRequestBodySchema, -} from './schemas/latest'; -export type { - RuleSnoozeSchedule, - BulkEditRulesRequestBody, - BulkEditRulesResponse, -} from './types/latest'; +export { bulkEditOperationsSchema, bulkEditRulesRequestBodySchema } from './schemas/latest'; +export type { BulkEditRulesRequestBody, BulkEditRulesResponse } from './types/latest'; export { - ruleSnoozeScheduleSchema as ruleSnoozeScheduleSchemaV1, bulkEditOperationsSchema as bulkEditOperationsSchemaV1, bulkEditRulesRequestBodySchema as bulkEditRulesRequestBodySchemaV1, } from './schemas/v1'; export type { - RuleSnoozeSchedule as RuleSnoozeScheduleV1, BulkEditRulesRequestBody as BulkEditRulesRequestBodyV1, BulkEditRulesResponse as BulkEditRulesResponseV1, } from './types/v1'; diff --git a/x-pack/plugins/alerting/common/routes/rule/apis/bulk_edit/schemas/v1.ts b/x-pack/plugins/alerting/common/routes/rule/apis/bulk_edit/schemas/v1.ts index 54e70cde689ac..3a17eaee30974 100644 --- a/x-pack/plugins/alerting/common/routes/rule/apis/bulk_edit/schemas/v1.ts +++ b/x-pack/plugins/alerting/common/routes/rule/apis/bulk_edit/schemas/v1.ts @@ -6,19 +6,10 @@ */ import { schema } from '@kbn/config-schema'; -import { validateDurationV1, validateNotifyWhenV1 } from '../../../validation'; -import { validateSnoozeScheduleV1 } from '../validation'; +import { validateDurationV1 } from '../../../validation'; import { rRuleRequestSchemaV1 } from '../../../../r_rule'; -import { ruleNotifyWhenV1 } from '../../../response'; - -const notifyWhenSchema = schema.oneOf( - [ - schema.literal(ruleNotifyWhenV1.CHANGE), - schema.literal(ruleNotifyWhenV1.ACTIVE), - schema.literal(ruleNotifyWhenV1.THROTTLE), - ], - { validate: validateNotifyWhenV1 } -); +import { notifyWhenSchemaV1, scheduleIdsSchemaV1 } from '../../../response'; +import { ruleSnoozeScheduleSchemaV1 } from '../../../request'; export const scheduleIdsSchema = schema.maybe(schema.arrayOf(schema.string())); @@ -28,15 +19,6 @@ export const ruleSnoozeScheduleSchema = schema.object({ rRule: rRuleRequestSchemaV1, }); -const ruleSnoozeScheduleSchemaWithValidation = schema.object( - { - id: schema.maybe(schema.string()), - duration: schema.number(), - rRule: rRuleRequestSchemaV1, - }, - { validate: validateSnoozeScheduleV1 } -); - const ruleActionSchema = schema.object({ group: schema.string(), id: schema.string(), @@ -46,7 +28,7 @@ const ruleActionSchema = schema.object({ schema.object({ summary: schema.boolean(), throttle: schema.nullable(schema.string()), - notifyWhen: notifyWhenSchema, + notifyWhen: notifyWhenSchemaV1, }) ), }); @@ -80,17 +62,17 @@ export const bulkEditOperationsSchema = schema.arrayOf( schema.object({ operation: schema.literal('set'), field: schema.literal('notifyWhen'), - value: notifyWhenSchema, + value: notifyWhenSchemaV1, }), schema.object({ operation: schema.oneOf([schema.literal('set')]), field: schema.literal('snoozeSchedule'), - value: ruleSnoozeScheduleSchemaWithValidation, + value: ruleSnoozeScheduleSchemaV1, }), schema.object({ operation: schema.oneOf([schema.literal('delete')]), field: schema.literal('snoozeSchedule'), - value: schema.maybe(scheduleIdsSchema), + value: schema.maybe(scheduleIdsSchemaV1), }), schema.object({ operation: schema.literal('set'), diff --git a/x-pack/plugins/alerting/common/routes/rule/apis/bulk_edit/types/v1.ts b/x-pack/plugins/alerting/common/routes/rule/apis/bulk_edit/types/v1.ts index 8f98d1c140746..3070f09964c3c 100644 --- a/x-pack/plugins/alerting/common/routes/rule/apis/bulk_edit/types/v1.ts +++ b/x-pack/plugins/alerting/common/routes/rule/apis/bulk_edit/types/v1.ts @@ -6,9 +6,8 @@ */ import type { TypeOf } from '@kbn/config-schema'; import { RuleParamsV1, RuleResponseV1 } from '../../../response'; -import { ruleSnoozeScheduleSchemaV1, bulkEditRulesRequestBodySchemaV1 } from '..'; +import { bulkEditRulesRequestBodySchemaV1 } from '..'; -export type RuleSnoozeSchedule = TypeOf; export type BulkEditRulesRequestBody = TypeOf; interface BulkEditActionSkippedResult { diff --git a/x-pack/plugins/alerting/common/routes/rule/apis/create/index.ts b/x-pack/plugins/alerting/common/routes/rule/apis/create/index.ts index 92ac6d67aece7..b7d96ceed715c 100644 --- a/x-pack/plugins/alerting/common/routes/rule/apis/create/index.ts +++ b/x-pack/plugins/alerting/common/routes/rule/apis/create/index.ts @@ -6,7 +6,6 @@ */ export { - notifyWhenSchema, actionFrequencySchema, actionAlertsFilterSchema, actionSchema, @@ -23,7 +22,6 @@ export type { } from './types/latest'; export { - notifyWhenSchema as notifyWhenSchemaV1, actionFrequencySchema as actionFrequencySchemaV1, actionAlertsFilterSchema as actionAlertsFilterSchemaV1, actionSchema as actionSchemaV1, diff --git a/x-pack/plugins/alerting/common/routes/rule/apis/create/schemas/v1.ts b/x-pack/plugins/alerting/common/routes/rule/apis/create/schemas/v1.ts index 98d82abf62be4..e471dd3cea530 100644 --- a/x-pack/plugins/alerting/common/routes/rule/apis/create/schemas/v1.ts +++ b/x-pack/plugins/alerting/common/routes/rule/apis/create/schemas/v1.ts @@ -6,26 +6,12 @@ */ import { schema } from '@kbn/config-schema'; -import { ruleNotifyWhenV1 } from '../../../response'; -import { - validateNotifyWhenV1, - validateDurationV1, - validateHoursV1, - validateTimezoneV1, -} from '../../../validation'; - -export const notifyWhenSchema = schema.oneOf( - [ - schema.literal(ruleNotifyWhenV1.CHANGE), - schema.literal(ruleNotifyWhenV1.ACTIVE), - schema.literal(ruleNotifyWhenV1.THROTTLE), - ], - { validate: validateNotifyWhenV1 } -); +import { validateDurationV1, validateHoursV1, validateTimezoneV1 } from '../../../validation'; +import { notifyWhenSchemaV1 } from '../../../response'; export const actionFrequencySchema = schema.object({ summary: schema.boolean(), - notify_when: notifyWhenSchema, + notify_when: notifyWhenSchemaV1, throttle: schema.nullable(schema.string({ validate: validateDurationV1 })), }); @@ -91,7 +77,7 @@ export const createBodySchema = schema.object({ interval: schema.string({ validate: validateDurationV1 }), }), actions: schema.arrayOf(actionSchema, { defaultValue: [] }), - notify_when: schema.maybe(schema.nullable(notifyWhenSchema)), + notify_when: schema.maybe(schema.nullable(notifyWhenSchemaV1)), }); export const createParamsSchema = schema.object({ diff --git a/x-pack/plugins/alerting/common/routes/rule/apis/resolve/index.ts b/x-pack/plugins/alerting/common/routes/rule/apis/resolve/index.ts new file mode 100644 index 0000000000000..140ec00701414 --- /dev/null +++ b/x-pack/plugins/alerting/common/routes/rule/apis/resolve/index.ts @@ -0,0 +1,14 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export { resolveParamsSchema } from './schemas/latest'; + +export { resolveParamsSchema as resolveParamsSchemaV1 } from './schemas/v1'; + +export type { ResolveRuleResponse } from './types/latest'; + +export type { ResolveRuleResponse as ResolveRuleResponseV1 } from './types/v1'; diff --git a/x-pack/plugins/alerting/common/routes/rule/apis/bulk_edit/validation/validate_snooze_schedule/latest.ts b/x-pack/plugins/alerting/common/routes/rule/apis/resolve/schemas/latest.ts similarity index 100% rename from x-pack/plugins/alerting/common/routes/rule/apis/bulk_edit/validation/validate_snooze_schedule/latest.ts rename to x-pack/plugins/alerting/common/routes/rule/apis/resolve/schemas/latest.ts diff --git a/x-pack/plugins/alerting/common/routes/rule/apis/resolve/schemas/v1.ts b/x-pack/plugins/alerting/common/routes/rule/apis/resolve/schemas/v1.ts new file mode 100644 index 0000000000000..26f23e23af6dc --- /dev/null +++ b/x-pack/plugins/alerting/common/routes/rule/apis/resolve/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 resolveParamsSchema = schema.object({ + id: schema.string(), +}); diff --git a/x-pack/plugins/alerting/common/routes/rule/response/constants/latest.ts b/x-pack/plugins/alerting/common/routes/rule/apis/resolve/types/latest.ts similarity index 100% rename from x-pack/plugins/alerting/common/routes/rule/response/constants/latest.ts rename to x-pack/plugins/alerting/common/routes/rule/apis/resolve/types/latest.ts diff --git a/x-pack/plugins/alerting/common/routes/rule/apis/resolve/types/v1.ts b/x-pack/plugins/alerting/common/routes/rule/apis/resolve/types/v1.ts new file mode 100644 index 0000000000000..eb86327c07712 --- /dev/null +++ b/x-pack/plugins/alerting/common/routes/rule/apis/resolve/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 { RuleParamsV1, RuleResponseV1 } from '../../../response'; + +export interface ResolveRuleResponse { + body: RuleResponseV1; +} diff --git a/x-pack/plugins/alerting/common/routes/rule/apis/snooze/index.ts b/x-pack/plugins/alerting/common/routes/rule/apis/snooze/index.ts new file mode 100644 index 0000000000000..cfd7ad0cbce05 --- /dev/null +++ b/x-pack/plugins/alerting/common/routes/rule/apis/snooze/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 { snoozeParamsSchema, snoozeBodySchema } from './schemas/latest'; + +export { + snoozeParamsSchema as snoozeParamsSchemaV1, + snoozeBodySchema as snoozeBodySchemaV1, +} from './schemas/v1'; diff --git a/x-pack/plugins/alerting/common/routes/rule/apis/snooze/schemas/latest.ts b/x-pack/plugins/alerting/common/routes/rule/apis/snooze/schemas/latest.ts new file mode 100644 index 0000000000000..25300c97a6d2e --- /dev/null +++ b/x-pack/plugins/alerting/common/routes/rule/apis/snooze/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/alerting/common/routes/rule/apis/snooze/schemas/v1.ts b/x-pack/plugins/alerting/common/routes/rule/apis/snooze/schemas/v1.ts new file mode 100644 index 0000000000000..9b12ab9767512 --- /dev/null +++ b/x-pack/plugins/alerting/common/routes/rule/apis/snooze/schemas/v1.ts @@ -0,0 +1,17 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { schema } from '@kbn/config-schema'; +import { ruleSnoozeScheduleSchemaV1 } from '../../../request'; + +export const snoozeParamsSchema = schema.object({ + id: schema.string(), +}); + +export const snoozeBodySchema = schema.object({ + snooze_schedule: ruleSnoozeScheduleSchemaV1, +}); diff --git a/x-pack/plugins/alerting/common/routes/rule/apis/unsnooze/index.ts b/x-pack/plugins/alerting/common/routes/rule/apis/unsnooze/index.ts new file mode 100644 index 0000000000000..1fb769c46d345 --- /dev/null +++ b/x-pack/plugins/alerting/common/routes/rule/apis/unsnooze/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 { unsnoozeParamsSchema, unsnoozeBodySchema } from './schemas/latest'; + +export { + unsnoozeParamsSchema as unsnoozeParamsSchemaV1, + unsnoozeBodySchema as unsnoozeBodySchemaV1, +} from './schemas/v1'; diff --git a/x-pack/plugins/alerting/common/routes/rule/apis/unsnooze/schemas/latest.ts b/x-pack/plugins/alerting/common/routes/rule/apis/unsnooze/schemas/latest.ts new file mode 100644 index 0000000000000..25300c97a6d2e --- /dev/null +++ b/x-pack/plugins/alerting/common/routes/rule/apis/unsnooze/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/alerting/common/routes/rule/apis/unsnooze/schemas/v1.ts b/x-pack/plugins/alerting/common/routes/rule/apis/unsnooze/schemas/v1.ts new file mode 100644 index 0000000000000..0da0e1b4ecd0b --- /dev/null +++ b/x-pack/plugins/alerting/common/routes/rule/apis/unsnooze/schemas/v1.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 { schema } from '@kbn/config-schema'; + +export const unsnoozeParamsSchema = schema.object({ + id: schema.string(), +}); + +const scheduleIdsSchema = schema.maybe(schema.arrayOf(schema.string())); + +export const unsnoozeBodySchema = schema.object({ + schedule_ids: scheduleIdsSchema, +}); diff --git a/x-pack/plugins/alerting/common/routes/rule/common/constants/latest.ts b/x-pack/plugins/alerting/common/routes/rule/common/constants/latest.ts new file mode 100644 index 0000000000000..25300c97a6d2e --- /dev/null +++ b/x-pack/plugins/alerting/common/routes/rule/common/constants/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/alerting/common/routes/rule/response/constants/v1.ts b/x-pack/plugins/alerting/common/routes/rule/common/constants/v1.ts similarity index 100% rename from x-pack/plugins/alerting/common/routes/rule/response/constants/v1.ts rename to x-pack/plugins/alerting/common/routes/rule/common/constants/v1.ts diff --git a/x-pack/plugins/alerting/common/routes/rule/common/index.ts b/x-pack/plugins/alerting/common/routes/rule/common/index.ts new file mode 100644 index 0000000000000..5989a3a993e7a --- /dev/null +++ b/x-pack/plugins/alerting/common/routes/rule/common/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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export { + ruleNotifyWhen, + ruleLastRunOutcomeValues, + ruleExecutionStatusValues, + ruleExecutionStatusErrorReason, + ruleExecutionStatusWarningReason, +} from './constants/latest'; + +export type { + RuleNotifyWhen, + RuleLastRunOutcomeValues, + RuleExecutionStatusValues, + RuleExecutionStatusErrorReason, + RuleExecutionStatusWarningReason, +} from './constants/latest'; + +export { + ruleNotifyWhen as ruleNotifyWhenV1, + ruleLastRunOutcomeValues as ruleLastRunOutcomeValuesV1, + ruleExecutionStatusValues as ruleExecutionStatusValuesV1, + ruleExecutionStatusErrorReason as ruleExecutionStatusErrorReasonV1, + ruleExecutionStatusWarningReason as ruleExecutionStatusWarningReasonV1, +} from './constants/v1'; + +export type { + RuleNotifyWhen as RuleNotifyWhenV1, + RuleLastRunOutcomeValues as RuleLastRunOutcomeValuesV1, + RuleExecutionStatusValues as RuleExecutionStatusValuesV1, + RuleExecutionStatusErrorReason as RuleExecutionStatusErrorReasonV1, + RuleExecutionStatusWarningReason as RuleExecutionStatusWarningReasonV1, +} from './constants/v1'; diff --git a/x-pack/plugins/alerting/common/routes/rule/apis/bulk_edit/validation/index.ts b/x-pack/plugins/alerting/common/routes/rule/request/index.ts similarity index 59% rename from x-pack/plugins/alerting/common/routes/rule/apis/bulk_edit/validation/index.ts rename to x-pack/plugins/alerting/common/routes/rule/request/index.ts index c11ce4f73f42c..bf500b636e7d9 100644 --- a/x-pack/plugins/alerting/common/routes/rule/apis/bulk_edit/validation/index.ts +++ b/x-pack/plugins/alerting/common/routes/rule/request/index.ts @@ -5,6 +5,6 @@ * 2.0. */ -export { validateSnoozeSchedule } from './validate_snooze_schedule/latest'; +export { ruleSnoozeScheduleSchema } from './schemas/latest'; -export { validateSnoozeSchedule as validateSnoozeScheduleV1 } from './validate_snooze_schedule/v1'; +export { ruleSnoozeScheduleSchema as ruleSnoozeScheduleSchemaV1 } from './schemas/v1'; diff --git a/x-pack/plugins/alerting/common/routes/rule/request/schemas/latest.ts b/x-pack/plugins/alerting/common/routes/rule/request/schemas/latest.ts new file mode 100644 index 0000000000000..25300c97a6d2e --- /dev/null +++ b/x-pack/plugins/alerting/common/routes/rule/request/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/alerting/common/routes/rule/request/schemas/v1.ts b/x-pack/plugins/alerting/common/routes/rule/request/schemas/v1.ts new file mode 100644 index 0000000000000..af9cf6a3ad3a6 --- /dev/null +++ b/x-pack/plugins/alerting/common/routes/rule/request/schemas/v1.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'; +import { rRuleRequestSchemaV1 } from '../../../r_rule'; +import { validateSnoozeScheduleV1 } from '../../validation'; + +export const ruleSnoozeScheduleSchema = schema.object( + { + id: schema.maybe(schema.string()), + duration: schema.number(), + rRule: rRuleRequestSchemaV1, + }, + { validate: validateSnoozeScheduleV1 } +); diff --git a/x-pack/plugins/alerting/common/routes/rule/response/index.ts b/x-pack/plugins/alerting/common/routes/rule/response/index.ts index cdf693c7867eb..ec8734240cc2b 100644 --- a/x-pack/plugins/alerting/common/routes/rule/response/index.ts +++ b/x-pack/plugins/alerting/common/routes/rule/response/index.ts @@ -14,6 +14,8 @@ export { monitoringSchema, ruleResponseSchema, ruleSnoozeScheduleSchema, + notifyWhenSchema, + scheduleIdsSchema, } from './schemas/latest'; export type { @@ -24,22 +26,6 @@ export type { Monitoring, } from './types/latest'; -export { - ruleNotifyWhen, - ruleLastRunOutcomeValues, - ruleExecutionStatusValues, - ruleExecutionStatusErrorReason, - ruleExecutionStatusWarningReason, -} from './constants/latest'; - -export type { - RuleNotifyWhen, - RuleLastRunOutcomeValues, - RuleExecutionStatusValues, - RuleExecutionStatusErrorReason, - RuleExecutionStatusWarningReason, -} from './constants/latest'; - export { ruleParamsSchema as ruleParamsSchemaV1, actionParamsSchema as actionParamsSchemaV1, @@ -49,24 +35,10 @@ export { monitoringSchema as monitoringSchemaV1, ruleResponseSchema as ruleResponseSchemaV1, ruleSnoozeScheduleSchema as ruleSnoozeScheduleSchemaV1, + notifyWhenSchema as notifyWhenSchemaV1, + scheduleIdsSchema as scheduleIdsSchemaV1, } from './schemas/v1'; -export { - ruleNotifyWhen as ruleNotifyWhenV1, - ruleLastRunOutcomeValues as ruleLastRunOutcomeValuesV1, - ruleExecutionStatusValues as ruleExecutionStatusValuesV1, - ruleExecutionStatusErrorReason as ruleExecutionStatusErrorReasonV1, - ruleExecutionStatusWarningReason as ruleExecutionStatusWarningReasonV1, -} from './constants/v1'; - -export type { - RuleNotifyWhen as RuleNotifyWhenV1, - RuleLastRunOutcomeValues as RuleLastRunOutcomeValuesV1, - RuleExecutionStatusValues as RuleExecutionStatusValuesV1, - RuleExecutionStatusErrorReason as RuleExecutionStatusErrorReasonV1, - RuleExecutionStatusWarningReason as RuleExecutionStatusWarningReasonV1, -} from './constants/v1'; - export type { RuleParams as RuleParamsV1, RuleResponse as RuleResponseV1, diff --git a/x-pack/plugins/alerting/common/routes/rule/response/schemas/v1.ts b/x-pack/plugins/alerting/common/routes/rule/response/schemas/v1.ts index 1c093314f7a47..fe02146c5ef62 100644 --- a/x-pack/plugins/alerting/common/routes/rule/response/schemas/v1.ts +++ b/x-pack/plugins/alerting/common/routes/rule/response/schemas/v1.ts @@ -13,17 +13,21 @@ import { ruleExecutionStatusErrorReason as ruleExecutionStatusErrorReasonV1, ruleExecutionStatusWarningReason as ruleExecutionStatusWarningReasonV1, ruleLastRunOutcomeValues as ruleLastRunOutcomeValuesV1, -} from '../constants/v1'; +} from '../../common/constants/v1'; +import { validateNotifyWhenV1 } from '../../validation'; export const ruleParamsSchema = schema.recordOf(schema.string(), schema.maybe(schema.any())); export const actionParamsSchema = schema.recordOf(schema.string(), schema.maybe(schema.any())); export const mappedParamsSchema = schema.recordOf(schema.string(), schema.maybe(schema.any())); -const notifyWhenSchema = schema.oneOf([ - schema.literal(ruleNotifyWhenV1.CHANGE), - schema.literal(ruleNotifyWhenV1.ACTIVE), - schema.literal(ruleNotifyWhenV1.THROTTLE), -]); +export const notifyWhenSchema = schema.oneOf( + [ + schema.literal(ruleNotifyWhenV1.CHANGE), + schema.literal(ruleNotifyWhenV1.ACTIVE), + schema.literal(ruleNotifyWhenV1.THROTTLE), + ], + { validate: validateNotifyWhenV1 } +); const intervalScheduleSchema = schema.object({ interval: schema.string(), @@ -182,9 +186,9 @@ export const monitoringSchema = schema.object({ }); export const ruleSnoozeScheduleSchema = schema.object({ + id: schema.maybe(schema.string()), duration: schema.number(), rRule: rRuleResponseSchemaV1, - id: schema.maybe(schema.string()), skipRecurrences: schema.maybe(schema.arrayOf(schema.string())), }); @@ -221,3 +225,5 @@ export const ruleResponseSchema = schema.object({ running: schema.maybe(schema.nullable(schema.boolean())), view_in_app_relative_url: schema.maybe(schema.nullable(schema.string())), }); + +export const scheduleIdsSchema = schema.maybe(schema.arrayOf(schema.string())); diff --git a/x-pack/plugins/alerting/common/routes/rule/validation/index.ts b/x-pack/plugins/alerting/common/routes/rule/validation/index.ts index a0322c2256e74..710f15f0d4c9d 100644 --- a/x-pack/plugins/alerting/common/routes/rule/validation/index.ts +++ b/x-pack/plugins/alerting/common/routes/rule/validation/index.ts @@ -7,10 +7,11 @@ export { validateDuration } from './validate_duration/latest'; export { validateHours } from './validate_hours/latest'; -export { validateNotifyWhen } from './validate_notify_when/latest'; export { validateTimezone } from './validate_timezone/latest'; +export { validateSnoozeSchedule } from './validate_snooze_schedule/latest'; export { validateDuration as validateDurationV1 } from './validate_duration/v1'; export { validateHours as validateHoursV1 } from './validate_hours/v1'; export { validateNotifyWhen as validateNotifyWhenV1 } from './validate_notify_when/v1'; export { validateTimezone as validateTimezoneV1 } from './validate_timezone/v1'; +export { validateSnoozeSchedule as validateSnoozeScheduleV1 } from './validate_snooze_schedule/v1'; diff --git a/x-pack/plugins/alerting/common/routes/rule/validation/validate_notify_when/v1.ts b/x-pack/plugins/alerting/common/routes/rule/validation/validate_notify_when/v1.ts index e58e5f5ef7cfd..38ccd877c49ae 100644 --- a/x-pack/plugins/alerting/common/routes/rule/validation/validate_notify_when/v1.ts +++ b/x-pack/plugins/alerting/common/routes/rule/validation/validate_notify_when/v1.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { ruleNotifyWhenV1, RuleNotifyWhenV1 } from '../../response'; +import { ruleNotifyWhenV1, RuleNotifyWhenV1 } from '../../common'; export function validateNotifyWhen(notifyWhen: string) { if (Object.values(ruleNotifyWhenV1).includes(notifyWhen as RuleNotifyWhenV1)) { diff --git a/x-pack/plugins/alerting/common/routes/rule/validation/validate_snooze_schedule/latest.ts b/x-pack/plugins/alerting/common/routes/rule/validation/validate_snooze_schedule/latest.ts new file mode 100644 index 0000000000000..25300c97a6d2e --- /dev/null +++ b/x-pack/plugins/alerting/common/routes/rule/validation/validate_snooze_schedule/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/alerting/common/routes/rule/apis/bulk_edit/validation/validate_snooze_schedule/v1.ts b/x-pack/plugins/alerting/common/routes/rule/validation/validate_snooze_schedule/v1.ts similarity index 74% rename from x-pack/plugins/alerting/common/routes/rule/apis/bulk_edit/validation/validate_snooze_schedule/v1.ts rename to x-pack/plugins/alerting/common/routes/rule/validation/validate_snooze_schedule/v1.ts index 65460110cd107..4a93f130e8248 100644 --- a/x-pack/plugins/alerting/common/routes/rule/apis/bulk_edit/validation/validate_snooze_schedule/v1.ts +++ b/x-pack/plugins/alerting/common/routes/rule/validation/validate_snooze_schedule/v1.ts @@ -5,11 +5,15 @@ * 2.0. */ +import { TypeOf } from '@kbn/config-schema'; import { Frequency } from '@kbn/rrule'; import moment from 'moment'; -import { RuleSnoozeScheduleV1 } from '../..'; +import { rRuleRequestSchema } from '../../../r_rule'; -export const validateSnoozeSchedule = (schedule: RuleSnoozeScheduleV1) => { +export const validateSnoozeSchedule = (schedule: { + rRule: TypeOf; + duration: number; +}) => { const intervalIsDaily = schedule.rRule.freq === Frequency.DAILY; const durationInDays = moment.duration(schedule.duration, 'milliseconds').asDays(); if (intervalIsDaily && schedule.rRule.interval && durationInDays >= schedule.rRule.interval) { diff --git a/x-pack/plugins/alerting/common/rule.ts b/x-pack/plugins/alerting/common/rule.ts index 5a8e1b275ef7e..ff74752df8695 100644 --- a/x-pack/plugins/alerting/common/rule.ts +++ b/x-pack/plugins/alerting/common/rule.ts @@ -191,7 +191,10 @@ export type SanitizedRule = Omit< > & { actions: SanitizedRuleAction[] }; export type ResolvedSanitizedRule = SanitizedRule & - Omit; + Omit & { + outcome: string; + alias_target_id?: string; + }; export type SanitizedRuleConfig = Pick< SanitizedRule, diff --git a/x-pack/plugins/alerting/docs/openapi/bundled.json b/x-pack/plugins/alerting/docs/openapi/bundled.json index 7a169c842a8e6..28ebb1cddae3c 100644 --- a/x-pack/plugins/alerting/docs/openapi/bundled.json +++ b/x-pack/plugins/alerting/docs/openapi/bundled.json @@ -14,8 +14,7 @@ }, "servers": [ { - "url": "http://localhost:5601", - "description": "local" + "url": "/" } ], "security": [ @@ -112,18 +111,8 @@ } } } - }, - "servers": [ - { - "url": "https://localhost:5601" - } - ] - }, - "servers": [ - { - "url": "https://localhost:5601" } - ] + } }, "/s/{spaceId}/api/alerting/rule/{ruleId}": { "get": { @@ -177,12 +166,7 @@ } } } - }, - "servers": [ - { - "url": "https://localhost:5601" - } - ] + } }, "delete": { "summary": "Deletes a rule.", @@ -226,12 +210,7 @@ } } } - }, - "servers": [ - { - "url": "https://localhost:5601" - } - ] + } }, "post": { "summary": "Creates a rule with a specific rule identifier.", @@ -321,12 +300,7 @@ } } } - }, - "servers": [ - { - "url": "https://localhost:5601" - } - ] + } }, "put": { "summary": "Updates the attributes for a rule.", @@ -397,18 +371,8 @@ } } } - }, - "servers": [ - { - "url": "https://localhost:5601" - } - ] - }, - "servers": [ - { - "url": "https://localhost:5601" } - ] + } }, "/s/{spaceId}/api/alerting/rule/{ruleId}/_disable": { "post": { @@ -453,18 +417,8 @@ } } } - }, - "servers": [ - { - "url": "https://localhost:5601" - } - ] - }, - "servers": [ - { - "url": "https://localhost:5601" } - ] + } }, "/s/{spaceId}/api/alerting/rule/{ruleId}/_enable": { "post": { @@ -509,18 +463,8 @@ } } } - }, - "servers": [ - { - "url": "https://localhost:5601" - } - ] - }, - "servers": [ - { - "url": "https://localhost:5601" } - ] + } }, "/s/{spaceId}/api/alerting/rules/_find": { "get": { @@ -694,18 +638,8 @@ } } } - }, - "servers": [ - { - "url": "https://localhost:5601" - } - ] - }, - "servers": [ - { - "url": "https://localhost:5601" } - ] + } }, "/s/{spaceId}/api/alerting/_health": { "get": { @@ -825,12 +759,7 @@ } } } - }, - "servers": [ - { - "url": "https://localhost:5601" - } - ] + } }, "/s/{spaceId}/api/alerting/rule_types": { "get": { @@ -1109,12 +1038,7 @@ } } } - }, - "servers": [ - { - "url": "https://localhost:5601" - } - ] + } }, "/s/{spaceId}/api/alerting/rule/{ruleId}/_mute_all": { "post": { @@ -1149,18 +1073,8 @@ } } } - }, - "servers": [ - { - "url": "https://localhost:5601" - } - ] - }, - "servers": [ - { - "url": "https://localhost:5601" } - ] + } }, "/s/{spaceId}/api/alerting/rule/{ruleId}/_unmute_all": { "post": { @@ -1195,18 +1109,8 @@ } } } - }, - "servers": [ - { - "url": "https://localhost:5601" - } - ] - }, - "servers": [ - { - "url": "https://localhost:5601" } - ] + } }, "/s/{spaceId}/api/alerting/rule/{ruleId}/_update_api_key": { "post": { @@ -1241,18 +1145,8 @@ } } } - }, - "servers": [ - { - "url": "https://localhost:5601" - } - ] - }, - "servers": [ - { - "url": "https://localhost:5601" } - ] + } }, "/s/{spaceId}/api/alerting/rule/{ruleId}/alert/{alertId}/_mute": { "post": { @@ -1290,18 +1184,8 @@ } } } - }, - "servers": [ - { - "url": "https://localhost:5601" - } - ] - }, - "servers": [ - { - "url": "https://localhost:5601" } - ] + } }, "/s/{spaceId}/api/alerting/rule/{ruleId}/alert/{alertId}/_unmute": { "post": { @@ -1339,18 +1223,8 @@ } } } - }, - "servers": [ - { - "url": "https://localhost:5601" - } - ] - }, - "servers": [ - { - "url": "https://localhost:5601" } - ] + } }, "/s/{spaceId}/api/alerts/alert/{alertId}": { "delete": { @@ -1393,12 +1267,7 @@ } } } - }, - "servers": [ - { - "url": "https://localhost:5601" - } - ] + } }, "get": { "summary": "Retrieves an alert by its identifier.", @@ -1444,12 +1313,7 @@ } } } - }, - "servers": [ - { - "url": "https://localhost:5601" - } - ] + } }, "post": { "summary": "Create an alert.", @@ -1600,12 +1464,7 @@ } } } - }, - "servers": [ - { - "url": "https://localhost:5601" - } - ] + } }, "put": { "summary": "Updates the attributes for an alert.", @@ -1742,18 +1601,8 @@ } } } - }, - "servers": [ - { - "url": "https://localhost:5601" - } - ] - }, - "servers": [ - { - "url": "https://localhost:5601" } - ] + } }, "/s/{spaceId}/api/alerts/alert/{alertId}/_disable": { "post": { @@ -1796,18 +1645,8 @@ } } } - }, - "servers": [ - { - "url": "https://localhost:5601" - } - ] - }, - "servers": [ - { - "url": "https://localhost:5601" } - ] + } }, "/s/{spaceId}/api/alerts/alert/{alertId}/_enable": { "post": { @@ -1850,18 +1689,8 @@ } } } - }, - "servers": [ - { - "url": "https://localhost:5601" - } - ] - }, - "servers": [ - { - "url": "https://localhost:5601" } - ] + } }, "/s/{spaceId}/api/alerts/alert/{alertId}/_mute_all": { "post": { @@ -1904,18 +1733,8 @@ } } } - }, - "servers": [ - { - "url": "https://localhost:5601" - } - ] - }, - "servers": [ - { - "url": "https://localhost:5601" } - ] + } }, "/s/{spaceId}/api/alerts/alert/{alertId}/_unmute_all": { "post": { @@ -1958,18 +1777,8 @@ } } } - }, - "servers": [ - { - "url": "https://localhost:5601" - } - ] - }, - "servers": [ - { - "url": "https://localhost:5601" } - ] + } }, "/s/{spaceId}/api/alerts/alerts/_find": { "get": { @@ -2136,18 +1945,8 @@ } } } - }, - "servers": [ - { - "url": "https://localhost:5601" - } - ] - }, - "servers": [ - { - "url": "https://localhost:5601" } - ] + } }, "/s/{spaceId}/api/alerts/alerts/_health": { "get": { @@ -2263,12 +2062,7 @@ } } } - }, - "servers": [ - { - "url": "https://localhost:5601" - } - ] + } }, "/s/{spaceId}/api/alerts/alerts/list_alert_types": { "get": { @@ -2418,12 +2212,7 @@ } } } - }, - "servers": [ - { - "url": "https://localhost:5601" - } - ] + } }, "/s/{spaceId}/api/alerts/alert/{alertId}/alert_instance/{alertInstanceId}/_mute": { "post": { @@ -2476,18 +2265,8 @@ } } } - }, - "servers": [ - { - "url": "https://localhost:5601" - } - ] - }, - "servers": [ - { - "url": "https://localhost:5601" } - ] + } }, "/s/{spaceId}/api/alerts/alert/{alertId}/alert_instance/{alertInstanceId}/_unmute": { "post": { @@ -2540,18 +2319,8 @@ } } } - }, - "servers": [ - { - "url": "https://localhost:5601" - } - ] - }, - "servers": [ - { - "url": "https://localhost:5601" } - ] + } } }, "components": { diff --git a/x-pack/plugins/alerting/docs/openapi/bundled.yaml b/x-pack/plugins/alerting/docs/openapi/bundled.yaml index 0465a9218f2db..b3b56044d2603 100644 --- a/x-pack/plugins/alerting/docs/openapi/bundled.yaml +++ b/x-pack/plugins/alerting/docs/openapi/bundled.yaml @@ -9,8 +9,7 @@ info: name: Elastic License 2.0 url: https://www.elastic.co/licensing/elastic-license servers: - - url: http://localhost:5601 - description: local + - url: / security: - basicAuth: [] - apiKeyAuth: [] @@ -68,10 +67,6 @@ paths: application/json: schema: $ref: '#/components/schemas/404_response' - servers: - - url: https://localhost:5601 - servers: - - url: https://localhost:5601 /s/{spaceId}/api/alerting/rule/{ruleId}: get: summary: Retrieves a rule by its identifier. @@ -105,8 +100,6 @@ paths: application/json: schema: $ref: '#/components/schemas/404_response' - servers: - - url: https://localhost:5601 delete: summary: Deletes a rule. operationId: deleteRule @@ -133,8 +126,6 @@ paths: application/json: schema: $ref: '#/components/schemas/404_response' - servers: - - url: https://localhost:5601 post: summary: Creates a rule with a specific rule identifier. operationId: createRuleId @@ -192,8 +183,6 @@ paths: application/json: schema: $ref: '#/components/schemas/404_response' - servers: - - url: https://localhost:5601 put: summary: Updates the attributes for a rule. operationId: updateRule @@ -236,10 +225,6 @@ paths: application/json: schema: $ref: '#/components/schemas/404_response' - servers: - - url: https://localhost:5601 - servers: - - url: https://localhost:5601 /s/{spaceId}/api/alerting/rule/{ruleId}/_disable: post: summary: Disables a rule. @@ -267,10 +252,6 @@ paths: application/json: schema: $ref: '#/components/schemas/404_response' - servers: - - url: https://localhost:5601 - servers: - - url: https://localhost:5601 /s/{spaceId}/api/alerting/rule/{ruleId}/_enable: post: summary: Enables a rule. @@ -298,10 +279,6 @@ paths: application/json: schema: $ref: '#/components/schemas/401_response' - servers: - - url: https://localhost:5601 - servers: - - url: https://localhost:5601 /s/{spaceId}/api/alerting/rules/_find: get: summary: Retrieves information about rules. @@ -415,10 +392,6 @@ paths: application/json: schema: $ref: '#/components/schemas/401_response' - servers: - - url: https://localhost:5601 - servers: - - url: https://localhost:5601 /s/{spaceId}/api/alerting/_health: get: summary: Retrieves the health status of the alerting framework. @@ -504,8 +477,6 @@ paths: application/json: schema: $ref: '#/components/schemas/401_response' - servers: - - url: https://localhost:5601 /s/{spaceId}/api/alerting/rule_types: get: summary: Retrieves a list of rule types. @@ -691,8 +662,6 @@ paths: application/json: schema: $ref: '#/components/schemas/401_response' - servers: - - url: https://localhost:5601 /s/{spaceId}/api/alerting/rule/{ruleId}/_mute_all: post: summary: Mutes all alerts. @@ -714,10 +683,6 @@ paths: application/json: schema: $ref: '#/components/schemas/401_response' - servers: - - url: https://localhost:5601 - servers: - - url: https://localhost:5601 /s/{spaceId}/api/alerting/rule/{ruleId}/_unmute_all: post: summary: Unmutes all alerts. @@ -739,10 +704,6 @@ paths: application/json: schema: $ref: '#/components/schemas/401_response' - servers: - - 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. @@ -763,10 +724,6 @@ paths: 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. @@ -789,10 +746,6 @@ paths: application/json: schema: $ref: '#/components/schemas/401_response' - servers: - - url: https://localhost:5601 - servers: - - url: https://localhost:5601 /s/{spaceId}/api/alerting/rule/{ruleId}/alert/{alertId}/_unmute: post: summary: Unmutes an alert. @@ -815,10 +768,6 @@ paths: application/json: schema: $ref: '#/components/schemas/401_response' - servers: - - url: https://localhost:5601 - servers: - - url: https://localhost:5601 /s/{spaceId}/api/alerts/alert/{alertId}: delete: summary: Permanently removes an alert. @@ -847,8 +796,6 @@ paths: application/json: schema: $ref: '#/components/schemas/401_response' - servers: - - url: https://localhost:5601 get: summary: Retrieves an alert by its identifier. operationId: legacyGetAlert @@ -878,8 +825,6 @@ paths: application/json: schema: $ref: '#/components/schemas/401_response' - servers: - - url: https://localhost:5601 post: summary: Create an alert. operationId: legacyCreateAlert @@ -989,8 +934,6 @@ paths: application/json: schema: $ref: '#/components/schemas/401_response' - servers: - - url: https://localhost:5601 put: summary: Updates the attributes for an alert. operationId: legacyUpdateAlert @@ -1089,10 +1032,6 @@ paths: application/json: schema: $ref: '#/components/schemas/401_response' - servers: - - url: https://localhost:5601 - servers: - - url: https://localhost:5601 /s/{spaceId}/api/alerts/alert/{alertId}/_disable: post: summary: Disables an alert. @@ -1120,10 +1059,6 @@ paths: application/json: schema: $ref: '#/components/schemas/401_response' - servers: - - url: https://localhost:5601 - servers: - - url: https://localhost:5601 /s/{spaceId}/api/alerts/alert/{alertId}/_enable: post: summary: Enables an alert. @@ -1151,10 +1086,6 @@ paths: application/json: schema: $ref: '#/components/schemas/401_response' - servers: - - url: https://localhost:5601 - servers: - - url: https://localhost:5601 /s/{spaceId}/api/alerts/alert/{alertId}/_mute_all: post: summary: Mutes all alert instances. @@ -1182,10 +1113,6 @@ paths: application/json: schema: $ref: '#/components/schemas/401_response' - servers: - - url: https://localhost:5601 - servers: - - url: https://localhost:5601 /s/{spaceId}/api/alerts/alert/{alertId}/_unmute_all: post: summary: Unmutes all alert instances. @@ -1213,10 +1140,6 @@ paths: application/json: schema: $ref: '#/components/schemas/401_response' - servers: - - url: https://localhost:5601 - servers: - - url: https://localhost:5601 /s/{spaceId}/api/alerts/alerts/_find: get: summary: Retrieves a paginated set of alerts. @@ -1326,10 +1249,6 @@ paths: application/json: schema: $ref: '#/components/schemas/401_response' - servers: - - url: https://localhost:5601 - servers: - - url: https://localhost:5601 /s/{spaceId}/api/alerts/alerts/_health: get: summary: Retrieves the health status of the alerting framework. @@ -1412,8 +1331,6 @@ paths: application/json: schema: $ref: '#/components/schemas/401_response' - servers: - - url: https://localhost:5601 /s/{spaceId}/api/alerts/alerts/list_alert_types: get: summary: Retrieves a list of alert types. @@ -1516,8 +1433,6 @@ paths: application/json: schema: $ref: '#/components/schemas/401_response' - servers: - - url: https://localhost:5601 /s/{spaceId}/api/alerts/alert/{alertId}/alert_instance/{alertInstanceId}/_mute: post: summary: Mutes an alert instance. @@ -1552,10 +1467,6 @@ paths: application/json: schema: $ref: '#/components/schemas/401_response' - servers: - - url: https://localhost:5601 - servers: - - url: https://localhost:5601 /s/{spaceId}/api/alerts/alert/{alertId}/alert_instance/{alertInstanceId}/_unmute: post: summary: Unmutes an alert instance. @@ -1590,10 +1501,6 @@ paths: application/json: schema: $ref: '#/components/schemas/401_response' - servers: - - url: https://localhost:5601 - servers: - - url: https://localhost:5601 components: securitySchemes: basicAuth: diff --git a/x-pack/plugins/alerting/docs/openapi/entrypoint.yaml b/x-pack/plugins/alerting/docs/openapi/entrypoint.yaml index f6beba7fdb82c..5b3d70e78069d 100644 --- a/x-pack/plugins/alerting/docs/openapi/entrypoint.yaml +++ b/x-pack/plugins/alerting/docs/openapi/entrypoint.yaml @@ -12,8 +12,7 @@ tags: - name: alerting description: Alerting APIs enable you to create and manage rules and alerts. servers: - - url: 'http://localhost:5601' - description: local + - url: / paths: '/s/{spaceId}/api/alerting/rule': $ref: 'paths/s@{spaceid}@api@alerting@rule.yaml' diff --git a/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerting@_health.yaml b/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerting@_health.yaml index cb2d541f86bed..5b856e24ca997 100644 --- a/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerting@_health.yaml +++ b/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerting@_health.yaml @@ -84,5 +84,3 @@ get: application/json: schema: $ref: '../components/schemas/401_response.yaml' -servers: - - url: https://localhost:5601 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 f88f69a437a9c..3afd4702ac2c5 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 @@ -52,8 +52,4 @@ post: content: application/json: schema: - $ref: '../components/schemas/404_response.yaml' - servers: - - url: https://localhost:5601 -servers: - - url: https://localhost:5601 \ No newline at end of file + $ref: '../components/schemas/404_response.yaml' \ No newline at end of file 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 058e825f1aac3..42c0f58387a60 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 @@ -35,8 +35,6 @@ get: application/json: schema: $ref: '../components/schemas/404_response.yaml' - servers: - - url: https://localhost:5601 delete: summary: Deletes a rule. @@ -67,8 +65,6 @@ delete: application/json: schema: $ref: '../components/schemas/404_response.yaml' - servers: - - url: https://localhost:5601 post: summary: Creates a rule with a specific rule identifier. @@ -134,8 +130,6 @@ post: application/json: schema: $ref: '../components/schemas/404_response.yaml' - servers: - - url: https://localhost:5601 put: summary: Updates the attributes for a rule. @@ -187,8 +181,4 @@ put: content: application/json: schema: - $ref: '../components/schemas/404_response.yaml' - servers: - - url: https://localhost:5601 -servers: - - url: https://localhost:5601 \ No newline at end of file + $ref: '../components/schemas/404_response.yaml' \ No newline at end of file diff --git a/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerting@rule@{ruleid}@_disable.yaml b/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerting@rule@{ruleid}@_disable.yaml index d0d5321a48420..10be1036c8766 100644 --- a/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerting@rule@{ruleid}@_disable.yaml +++ b/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerting@rule@{ruleid}@_disable.yaml @@ -26,8 +26,4 @@ post: content: application/json: schema: - $ref: '../components/schemas/404_response.yaml' - servers: - - url: https://localhost:5601 -servers: - - url: https://localhost:5601 \ No newline at end of file + $ref: '../components/schemas/404_response.yaml' \ No newline at end of file diff --git a/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerting@rule@{ruleid}@_enable.yaml b/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerting@rule@{ruleid}@_enable.yaml index 3759acc7093a1..c809cc7047c96 100644 --- a/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerting@rule@{ruleid}@_enable.yaml +++ b/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerting@rule@{ruleid}@_enable.yaml @@ -28,8 +28,4 @@ post: content: application/json: schema: - $ref: '../components/schemas/401_response.yaml' - servers: - - url: https://localhost:5601 -servers: - - url: https://localhost:5601 \ No newline at end of file + $ref: '../components/schemas/401_response.yaml' \ No newline at end of file diff --git a/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerting@rule@{ruleid}@_mute_all.yaml b/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerting@rule@{ruleid}@_mute_all.yaml index 00250d5a754a4..c4efec008217d 100644 --- a/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerting@rule@{ruleid}@_mute_all.yaml +++ b/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerting@rule@{ruleid}@_mute_all.yaml @@ -24,8 +24,4 @@ post: content: application/json: schema: - $ref: '../components/schemas/401_response.yaml' - servers: - - url: https://localhost:5601 -servers: - - url: https://localhost:5601 \ No newline at end of file + $ref: '../components/schemas/401_response.yaml' \ No newline at end of file diff --git a/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerting@rule@{ruleid}@_unmute_all.yaml b/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerting@rule@{ruleid}@_unmute_all.yaml index b0a887e7b427e..5ef2bb31de59f 100644 --- a/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerting@rule@{ruleid}@_unmute_all.yaml +++ b/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerting@rule@{ruleid}@_unmute_all.yaml @@ -23,8 +23,4 @@ post: content: application/json: schema: - $ref: '../components/schemas/401_response.yaml' - servers: - - url: https://localhost:5601 -servers: - - url: https://localhost:5601 \ No newline at end of file + $ref: '../components/schemas/401_response.yaml' \ No newline at end of file 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 index a4d79f12943cc..f1d390e888d7c 100644 --- 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 @@ -16,8 +16,4 @@ post: 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 + $ref: '../components/schemas/400_response.yaml' \ No newline at end of file diff --git a/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerting@rule@{ruleid}@alert@{alertid}@_mute.yaml b/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerting@rule@{ruleid}@alert@{alertid}@_mute.yaml index 040d6242b0596..3f12ffd3c8e4e 100644 --- a/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerting@rule@{ruleid}@alert@{alertid}@_mute.yaml +++ b/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerting@rule@{ruleid}@alert@{alertid}@_mute.yaml @@ -23,8 +23,4 @@ post: content: application/json: schema: - $ref: '../components/schemas/401_response.yaml' - servers: - - url: https://localhost:5601 -servers: - - url: https://localhost:5601 \ No newline at end of file + $ref: '../components/schemas/401_response.yaml' \ No newline at end of file diff --git a/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerting@rule@{ruleid}@alert@{alertid}@_unmute.yaml b/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerting@rule@{ruleid}@alert@{alertid}@_unmute.yaml index dd78b1d3449d0..a3ed064aaaebe 100644 --- a/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerting@rule@{ruleid}@alert@{alertid}@_unmute.yaml +++ b/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerting@rule@{ruleid}@alert@{alertid}@_unmute.yaml @@ -23,8 +23,4 @@ post: content: application/json: schema: - $ref: '../components/schemas/401_response.yaml' - servers: - - url: https://localhost:5601 -servers: - - url: https://localhost:5601 \ No newline at end of file + $ref: '../components/schemas/401_response.yaml' \ No newline at end of file diff --git a/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerting@rule_types.yaml b/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerting@rule_types.yaml index 8b7019ee54539..b6f8fafb35f17 100644 --- a/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerting@rule_types.yaml +++ b/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerting@rule_types.yaml @@ -193,6 +193,4 @@ get: content: application/json: schema: - $ref: '../components/schemas/401_response.yaml' -servers: - - url: https://localhost:5601 \ No newline at end of file + $ref: '../components/schemas/401_response.yaml' \ No newline at end of file diff --git a/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerting@rules@_find.yaml b/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerting@rules@_find.yaml index 3b58806865f43..f512a0660f181 100644 --- a/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerting@rules@_find.yaml +++ b/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerting@rules@_find.yaml @@ -120,8 +120,4 @@ get: content: application/json: schema: - $ref: '../components/schemas/401_response.yaml' - servers: - - url: https://localhost:5601 -servers: - - url: https://localhost:5601 \ No newline at end of file + $ref: '../components/schemas/401_response.yaml' \ No newline at end of file diff --git a/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerts@_find.yaml b/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerts@_find.yaml index bc8e2ecae4901..32dcbbf218a34 100644 --- a/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerts@_find.yaml +++ b/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerts@_find.yaml @@ -113,8 +113,4 @@ get: content: application/json: schema: - $ref: '../components/schemas/401_response.yaml' - servers: - - url: https://localhost:5601 -servers: - - url: https://localhost:5601 \ No newline at end of file + $ref: '../components/schemas/401_response.yaml' \ No newline at end of file diff --git a/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerts@_health.yaml b/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerts@_health.yaml index 2b9cd953596bc..eba22ac1b4092 100644 --- a/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerts@_health.yaml +++ b/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerts@_health.yaml @@ -78,6 +78,4 @@ get: content: application/json: schema: - $ref: '../components/schemas/401_response.yaml' -servers: - - url: https://localhost:5601 \ No newline at end of file + $ref: '../components/schemas/401_response.yaml' \ No newline at end of file diff --git a/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerts@alert@{alertid}.yaml b/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerts@alert@{alertid}.yaml index 7976041b14482..4af612fc150c5 100644 --- a/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerts@alert@{alertid}.yaml +++ b/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerts@alert@{alertid}.yaml @@ -26,8 +26,6 @@ delete: application/json: schema: $ref: '../components/schemas/401_response.yaml' - servers: - - url: https://localhost:5601 get: summary: Retrieves an alert by its identifier. @@ -58,8 +56,6 @@ get: application/json: schema: $ref: '../components/schemas/401_response.yaml' - servers: - - url: https://localhost:5601 post: summary: Create an alert. @@ -176,8 +172,6 @@ post: application/json: schema: $ref: '../components/schemas/401_response.yaml' - servers: - - url: https://localhost:5601 put: summary: Updates the attributes for an alert. @@ -282,9 +276,4 @@ put: content: application/json: schema: - $ref: '../components/schemas/401_response.yaml' - servers: - - url: https://localhost:5601 - -servers: - - url: https://localhost:5601 \ No newline at end of file + $ref: '../components/schemas/401_response.yaml' \ No newline at end of file diff --git a/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerts@alert@{alertid}@_disable.yaml b/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerts@alert@{alertid}@_disable.yaml index 09e27e410db07..62fc4de90cae9 100644 --- a/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerts@alert@{alertid}@_disable.yaml +++ b/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerts@alert@{alertid}@_disable.yaml @@ -23,8 +23,4 @@ post: content: application/json: schema: - $ref: '../components/schemas/401_response.yaml' - servers: - - url: https://localhost:5601 -servers: - - url: https://localhost:5601 \ No newline at end of file + $ref: '../components/schemas/401_response.yaml' \ No newline at end of file diff --git a/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerts@alert@{alertid}@_enable.yaml b/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerts@alert@{alertid}@_enable.yaml index 8a8af9f7a7483..85ede004c1890 100644 --- a/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerts@alert@{alertid}@_enable.yaml +++ b/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerts@alert@{alertid}@_enable.yaml @@ -23,8 +23,4 @@ post: content: application/json: schema: - $ref: '../components/schemas/401_response.yaml' - servers: - - url: https://localhost:5601 -servers: - - url: https://localhost:5601 \ No newline at end of file + $ref: '../components/schemas/401_response.yaml' \ No newline at end of file diff --git a/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerts@alert@{alertid}@_mute_all.yaml b/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerts@alert@{alertid}@_mute_all.yaml index 48c55a553e199..6507cf6da6a18 100644 --- a/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerts@alert@{alertid}@_mute_all.yaml +++ b/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerts@alert@{alertid}@_mute_all.yaml @@ -23,8 +23,4 @@ post: content: application/json: schema: - $ref: '../components/schemas/401_response.yaml' - servers: - - url: https://localhost:5601 -servers: - - url: https://localhost:5601 \ No newline at end of file + $ref: '../components/schemas/401_response.yaml' \ No newline at end of file diff --git a/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerts@alert@{alertid}@_unmute_all.yaml b/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerts@alert@{alertid}@_unmute_all.yaml index 8749d657b2de1..17c48dae2677b 100644 --- a/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerts@alert@{alertid}@_unmute_all.yaml +++ b/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerts@alert@{alertid}@_unmute_all.yaml @@ -23,8 +23,4 @@ post: content: application/json: schema: - $ref: '../components/schemas/401_response.yaml' - servers: - - url: https://localhost:5601 -servers: - - url: https://localhost:5601 \ No newline at end of file + $ref: '../components/schemas/401_response.yaml' \ No newline at end of file diff --git a/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerts@alert@{alertid}@alert_instance@{alertinstanceid}@_mute.yaml b/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerts@alert@{alertid}@alert_instance@{alertinstanceid}@_mute.yaml index ca407b420ecec..439445aa29a82 100644 --- a/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerts@alert@{alertid}@alert_instance@{alertinstanceid}@_mute.yaml +++ b/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerts@alert@{alertid}@alert_instance@{alertinstanceid}@_mute.yaml @@ -30,8 +30,4 @@ post: content: application/json: schema: - $ref: '../components/schemas/401_response.yaml' - servers: - - url: https://localhost:5601 -servers: - - url: https://localhost:5601 \ No newline at end of file + $ref: '../components/schemas/401_response.yaml' \ No newline at end of file diff --git a/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerts@alert@{alertid}@alert_instance@{alertinstanceid}@_unmute.yaml b/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerts@alert@{alertid}@alert_instance@{alertinstanceid}@_unmute.yaml index 85d6ef9c4384b..3a7fe8dc1d31a 100644 --- a/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerts@alert@{alertid}@alert_instance@{alertinstanceid}@_unmute.yaml +++ b/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerts@alert@{alertid}@alert_instance@{alertinstanceid}@_unmute.yaml @@ -30,8 +30,4 @@ post: content: application/json: schema: - $ref: '../components/schemas/401_response.yaml' - servers: - - url: https://localhost:5601 -servers: - - url: https://localhost:5601 \ No newline at end of file + $ref: '../components/schemas/401_response.yaml' \ No newline at end of file diff --git a/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerts@list_alert_types.yaml b/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerts@list_alert_types.yaml index 1f23d5c94e290..b82f701cef1fb 100644 --- a/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerts@list_alert_types.yaml +++ b/x-pack/plugins/alerting/docs/openapi/paths/s@{spaceid}@api@alerts@list_alert_types.yaml @@ -106,6 +106,4 @@ get: content: application/json: schema: - $ref: '../components/schemas/401_response.yaml' -servers: - - url: https://localhost:5601 \ No newline at end of file + $ref: '../components/schemas/401_response.yaml' \ No newline at end of file diff --git a/x-pack/plugins/alerting/public/pages/maintenance_windows/components/create_maintenance_windows_form.test.tsx b/x-pack/plugins/alerting/public/pages/maintenance_windows/components/create_maintenance_windows_form.test.tsx index dc78b4455d54b..c5fb3bdf8357a 100644 --- a/x-pack/plugins/alerting/public/pages/maintenance_windows/components/create_maintenance_windows_form.test.tsx +++ b/x-pack/plugins/alerting/public/pages/maintenance_windows/components/create_maintenance_windows_form.test.tsx @@ -189,6 +189,43 @@ describe('CreateMaintenanceWindowForm', () => { expect(managementInput).toBeChecked(); }); + it('should initialize MWs with selected category ids properly', async () => { + const result = appMockRenderer.render( + + ); + + await waitFor(() => { + expect( + result.queryByTestId('maintenanceWindowCategorySelectionLoading') + ).not.toBeInTheDocument(); + }); + + const observabilityInput = within( + result.getByTestId('maintenanceWindowCategorySelection') + ).getByTestId('checkbox-observability'); + const securityInput = within( + result.getByTestId('maintenanceWindowCategorySelection') + ).getByTestId('checkbox-securitySolution'); + const managementInput = within( + result.getByTestId('maintenanceWindowCategorySelection') + ).getByTestId('checkbox-management'); + + expect(observabilityInput).toBeChecked(); + expect(managementInput).toBeChecked(); + expect(securityInput).not.toBeChecked(); + }); + it('can select category IDs', async () => { const result = appMockRenderer.render(); diff --git a/x-pack/plugins/alerting/public/pages/maintenance_windows/components/create_maintenance_windows_form.tsx b/x-pack/plugins/alerting/public/pages/maintenance_windows/components/create_maintenance_windows_form.tsx index f51f16d972c02..3a99e8bf75b90 100644 --- a/x-pack/plugins/alerting/public/pages/maintenance_windows/components/create_maintenance_windows_form.tsx +++ b/x-pack/plugins/alerting/public/pages/maintenance_windows/components/create_maintenance_windows_form.tsx @@ -120,7 +120,7 @@ export const CreateMaintenanceWindowForm = React.memo({ + const [{ recurring, timezone, categoryIds }, _, mounted] = useFormData({ form, watch: ['recurring', 'timezone', 'categoryIds'], }); @@ -188,6 +188,9 @@ export const CreateMaintenanceWindowForm = React.memo ruleType.category))]); hasSetInitialCategories.current = true; // eslint-disable-next-line react-hooks/exhaustive-deps - }, [isEditMode, ruleTypes]); + }, [isEditMode, ruleTypes, mounted]); // For edit mode, if a maintenance window => category_ids is not an array, this means // the maintenance window was created before the introduction of category filters. @@ -206,6 +209,9 @@ export const CreateMaintenanceWindowForm = React.memo diff --git a/x-pack/plugins/alerting/public/pages/maintenance_windows/translations.ts b/x-pack/plugins/alerting/public/pages/maintenance_windows/translations.ts index 8e3988d64fcce..c8b1b3a8076b6 100644 --- a/x-pack/plugins/alerting/public/pages/maintenance_windows/translations.ts +++ b/x-pack/plugins/alerting/public/pages/maintenance_windows/translations.ts @@ -646,7 +646,7 @@ export const EXPERIMENTAL_DESCRIPTION = i18n.translate( 'xpack.alerting.maintenanceWindows.badge.experimentalDescription', { defaultMessage: - 'This functionality is in technical preview and may be changed or removed completely in a future release. Elastic will take a best effort approach to fix any issues, but features in technical preview are not subject to the support SLA of official GA features.', + 'This functionality is in technical preview and may be changed or removed completely in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features.', } ); diff --git a/x-pack/plugins/alerting/server/application/r_rule/schemas/r_rule_schema.ts b/x-pack/plugins/alerting/server/application/r_rule/schemas/r_rule_schema.ts index 6f8b2f8f4fc7a..5325c571f5d3e 100644 --- a/x-pack/plugins/alerting/server/application/r_rule/schemas/r_rule_schema.ts +++ b/x-pack/plugins/alerting/server/application/r_rule/schemas/r_rule_schema.ts @@ -37,10 +37,10 @@ export const rRuleSchema = schema.object({ byweekday: schema.maybe(schema.arrayOf(schema.oneOf([schema.string(), schema.number()]))), bymonth: schema.maybe(schema.arrayOf(schema.number())), bysetpos: schema.maybe(schema.arrayOf(schema.number())), - bymonthday: schema.arrayOf(schema.number()), - byyearday: schema.arrayOf(schema.number()), - byweekno: schema.arrayOf(schema.number()), - byhour: schema.arrayOf(schema.number()), - byminute: schema.arrayOf(schema.number()), - bysecond: schema.arrayOf(schema.number()), + bymonthday: schema.maybe(schema.arrayOf(schema.number())), + byyearday: schema.maybe(schema.arrayOf(schema.number())), + byweekno: schema.maybe(schema.arrayOf(schema.number())), + byhour: schema.maybe(schema.arrayOf(schema.number())), + byminute: schema.maybe(schema.arrayOf(schema.number())), + bysecond: schema.maybe(schema.arrayOf(schema.number())), }); diff --git a/x-pack/plugins/alerting/server/application/rule/methods/bulk_edit/types/bulk_edit_rules_options.ts b/x-pack/plugins/alerting/server/application/rule/methods/bulk_edit/types/bulk_edit_rules_options.ts index a74b7fe152069..c099cde044363 100644 --- a/x-pack/plugins/alerting/server/application/rule/methods/bulk_edit/types/bulk_edit_rules_options.ts +++ b/x-pack/plugins/alerting/server/application/rule/methods/bulk_edit/types/bulk_edit_rules_options.ts @@ -45,7 +45,7 @@ export type BulkEditOptionsFilter = BulkEditOptionsCo }; export type BulkEditOptionsIds = BulkEditOptionsCommon & { - ids: string[]; + ids?: string[]; }; export type BulkEditSkipReason = 'RULE_NOT_MODIFIED'; diff --git a/x-pack/plugins/alerting/server/application/rule/methods/resolve/index.ts b/x-pack/plugins/alerting/server/application/rule/methods/resolve/index.ts new file mode 100644 index 0000000000000..b8d44beb0610e --- /dev/null +++ b/x-pack/plugins/alerting/server/application/rule/methods/resolve/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 { ResolveParams } from './resolve_rule'; +export { resolveRule } from './resolve_rule'; diff --git a/x-pack/plugins/alerting/server/application/rule/methods/resolve/resolve_rule.ts b/x-pack/plugins/alerting/server/application/rule/methods/resolve/resolve_rule.ts new file mode 100644 index 0000000000000..cbde52a44b1fe --- /dev/null +++ b/x-pack/plugins/alerting/server/application/rule/methods/resolve/resolve_rule.ts @@ -0,0 +1,106 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import Boom from '@hapi/boom'; +import { withSpan } from '@kbn/apm-utils'; +import { AlertConsumers } from '@kbn/rule-data-utils'; +import { resolveRuleSavedObject } from '../../../../rules_client/lib'; +import { ruleAuditEvent, RuleAuditAction } from '../../../../rules_client/common/audit_events'; +import { RuleTypeParams } from '../../../../types'; +import { ReadOperations, AlertingAuthorizationEntity } from '../../../../authorization'; +import { RulesClientContext } from '../../../../rules_client/types'; +import { formatLegacyActions } from '../../../../rules_client/lib'; +import { transformRuleAttributesToRuleDomain, transformRuleDomainToRule } from '../../transforms'; +import { Rule } from '../../types'; +import { ruleSchema } from '../../schemas'; +import { resolveRuleParamsSchema } from './schemas'; +import type { ResolvedSanitizedRule } from '../../../../types'; + +export interface ResolveParams { + id: string; + includeSnoozeData?: boolean; +} + +export async function resolveRule( + context: RulesClientContext, + { id, includeSnoozeData = false }: ResolveParams +): // TODO (http-versioning): This should be of type Rule, change this when all rule types are fixed +Promise> { + try { + resolveRuleParamsSchema.validate({ id }); + } catch (error) { + throw Boom.badRequest(`Error validating resolve params - ${error.message}`); + } + const { saved_object: result, ...resolveResponse } = await withSpan( + { name: 'resolveRuleSavedObject', type: 'rules' }, + () => + resolveRuleSavedObject(context, { + ruleId: id, + }) + ); + try { + await context.authorization.ensureAuthorized({ + ruleTypeId: result.attributes.alertTypeId, + consumer: result.attributes.consumer, + operation: ReadOperations.Get, + entity: AlertingAuthorizationEntity.Rule, + }); + } catch (error) { + context.auditLogger?.log( + ruleAuditEvent({ + action: RuleAuditAction.RESOLVE, + savedObject: { type: 'alert', id }, + error, + }) + ); + throw error; + } + context.auditLogger?.log( + ruleAuditEvent({ + action: RuleAuditAction.RESOLVE, + savedObject: { type: 'alert', id }, + }) + ); + + const ruleDomain = transformRuleAttributesToRuleDomain(result.attributes, { + id: result.id, + logger: context.logger, + ruleType: context.ruleTypeRegistry.get(result.attributes.alertTypeId), + references: result.references, + includeSnoozeData, + }); + + const rule = transformRuleDomainToRule(ruleDomain); + + try { + ruleSchema.validate(rule); + } catch (error) { + context.logger.warn(`Error validating resolve data - ${error.message}`); + } + + // format legacy actions for SIEM rules + if (result.attributes.consumer === AlertConsumers.SIEM) { + // @ts-expect-error formatLegacyActions uses common Rule type instead of server; wontfix as this function is deprecated + const [migratedRule] = await formatLegacyActions([rule], { + savedObjectsClient: context.unsecuredSavedObjectsClient, + logger: context.logger, + }); + + return { + ...(migratedRule as Rule), + ...resolveResponse, + // TODO (http-versioning): Remove this cast, this enables us to move forward + // without fixing all of other solution types + } as ResolvedSanitizedRule; + } + + return { + ...rule, + ...resolveResponse, + // TODO (http-versioning): Remove this cast, this enables us to move forward + // without fixing all of other solution types + } as ResolvedSanitizedRule; +} diff --git a/x-pack/plugins/alerting/server/application/rule/methods/resolve/schemas/index.ts b/x-pack/plugins/alerting/server/application/rule/methods/resolve/schemas/index.ts new file mode 100644 index 0000000000000..09bccf1170ab4 --- /dev/null +++ b/x-pack/plugins/alerting/server/application/rule/methods/resolve/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 { resolveRuleParamsSchema } from './resolve_rule_params_schema'; diff --git a/x-pack/plugins/alerting/server/application/rule/methods/resolve/schemas/resolve_rule_params_schema.ts b/x-pack/plugins/alerting/server/application/rule/methods/resolve/schemas/resolve_rule_params_schema.ts new file mode 100644 index 0000000000000..a4371befd9f78 --- /dev/null +++ b/x-pack/plugins/alerting/server/application/rule/methods/resolve/schemas/resolve_rule_params_schema.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 resolveRuleParamsSchema = schema.object({ + id: schema.string(), +}); diff --git a/x-pack/plugins/alerting/server/application/rule/methods/resolve/types/index.ts b/x-pack/plugins/alerting/server/application/rule/methods/resolve/types/index.ts new file mode 100644 index 0000000000000..a4b7c56caab19 --- /dev/null +++ b/x-pack/plugins/alerting/server/application/rule/methods/resolve/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 * from './resolved_rule'; diff --git a/x-pack/plugins/alerting/server/application/rule/methods/resolve/types/resolved_rule.ts b/x-pack/plugins/alerting/server/application/rule/methods/resolve/types/resolved_rule.ts new file mode 100644 index 0000000000000..d9d0c3f0c5e8f --- /dev/null +++ b/x-pack/plugins/alerting/server/application/rule/methods/resolve/types/resolved_rule.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. + */ +import type { Rule } from '../../../types'; + +export type ResolvedRule = Rule & { outcome: string; alias_target_id?: string }; diff --git a/x-pack/plugins/alerting/server/application/rule/methods/snooze/index.ts b/x-pack/plugins/alerting/server/application/rule/methods/snooze/index.ts new file mode 100644 index 0000000000000..842e092d40d57 --- /dev/null +++ b/x-pack/plugins/alerting/server/application/rule/methods/snooze/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 { SnoozeRuleOptions } from './types'; +export { snoozeRule } from './snooze_rule'; diff --git a/x-pack/plugins/alerting/server/application/rule/methods/snooze/schemas/index.ts b/x-pack/plugins/alerting/server/application/rule/methods/snooze/schemas/index.ts new file mode 100644 index 0000000000000..b0744b893bbfb --- /dev/null +++ b/x-pack/plugins/alerting/server/application/rule/methods/snooze/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 { snoozeRuleParamsSchema } from './snooze_rule_params_schema'; +export { snoozeRuleBodySchema } from './snooze_rule_body_schema'; diff --git a/x-pack/plugins/alerting/server/application/rule/methods/snooze/schemas/snooze_rule_body_schema.ts b/x-pack/plugins/alerting/server/application/rule/methods/snooze/schemas/snooze_rule_body_schema.ts new file mode 100644 index 0000000000000..180e69fb33ad1 --- /dev/null +++ b/x-pack/plugins/alerting/server/application/rule/methods/snooze/schemas/snooze_rule_body_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'; +import { ruleSnoozeScheduleSchema as ruleSnoozeScheduleRequestSchema } from '../../../../../../common/routes/rule/request'; + +export const snoozeRuleBodySchema = schema.object({ + snoozeSchedule: ruleSnoozeScheduleRequestSchema, +}); diff --git a/x-pack/plugins/alerting/server/application/rule/methods/snooze/schemas/snooze_rule_params_schema.ts b/x-pack/plugins/alerting/server/application/rule/methods/snooze/schemas/snooze_rule_params_schema.ts new file mode 100644 index 0000000000000..2bacdb1c116f2 --- /dev/null +++ b/x-pack/plugins/alerting/server/application/rule/methods/snooze/schemas/snooze_rule_params_schema.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 snoozeRuleParamsSchema = schema.object({ + id: schema.string(), +}); diff --git a/x-pack/plugins/alerting/server/rules_client/methods/snooze.ts b/x-pack/plugins/alerting/server/application/rule/methods/snooze/snooze_rule.ts similarity index 53% rename from x-pack/plugins/alerting/server/rules_client/methods/snooze.ts rename to x-pack/plugins/alerting/server/application/rule/methods/snooze/snooze_rule.ts index 6f1187526b521..b10df195e5b77 100644 --- a/x-pack/plugins/alerting/server/rules_client/methods/snooze.ts +++ b/x-pack/plugins/alerting/server/application/rule/methods/snooze/snooze_rule.ts @@ -6,26 +6,32 @@ */ import Boom from '@hapi/boom'; -import { RawRule, RuleSnoozeSchedule } from '../../types'; -import { WriteOperations, AlertingAuthorizationEntity } from '../../authorization'; -import { retryIfConflicts } from '../../lib/retry_if_conflicts'; -import { partiallyUpdateAlert } from '../../saved_objects'; -import { ruleAuditEvent, RuleAuditAction } from '../common/audit_events'; -import { validateSnoozeStartDate } from '../../lib/validate_snooze_date'; -import { RuleMutedError } from '../../lib/errors/rule_muted'; -import { RulesClientContext } from '../types'; -import { getSnoozeAttributes, verifySnoozeAttributeScheduleLimit } from '../common'; -import { updateMeta } from '../lib'; +import { withSpan } from '@kbn/apm-utils'; +import { getRuleSavedObject } from '../../../../rules_client/lib'; +import { ruleAuditEvent, RuleAuditAction } from '../../../../rules_client/common/audit_events'; +import { WriteOperations, AlertingAuthorizationEntity } from '../../../../authorization'; +import { retryIfConflicts } from '../../../../lib/retry_if_conflicts'; +import { validateSnoozeStartDate } from '../../../../lib/validate_snooze_date'; +import { RuleMutedError } from '../../../../lib/errors/rule_muted'; +import { RulesClientContext } from '../../../../rules_client/types'; +import { + getSnoozeAttributes, + verifySnoozeAttributeScheduleLimit, +} from '../../../../rules_client/common'; +import { updateRuleSo } from '../../../../data/rule'; +import { updateMetaAttributes } from '../../../../rules_client/lib/update_meta_attributes'; +import { snoozeRuleParamsSchema } from './schemas'; +import type { SnoozeRuleOptions } from './types'; -export interface SnoozeParams { - id: string; - snoozeSchedule: RuleSnoozeSchedule; -} - -export async function snooze( +export async function snoozeRule( context: RulesClientContext, - { id, snoozeSchedule }: SnoozeParams + { id, snoozeSchedule }: SnoozeRuleOptions ): Promise { + try { + snoozeRuleParamsSchema.validate({ id }); + } catch (error) { + throw Boom.badRequest(`Error validating snooze params - ${error.message}`); + } const snoozeDateValidationMsg = validateSnoozeStartDate(snoozeSchedule.rRule.dtstart); if (snoozeDateValidationMsg) { throw new RuleMutedError(snoozeDateValidationMsg); @@ -40,17 +46,14 @@ export async function snooze( async function snoozeWithOCC( context: RulesClientContext, - { - id, - snoozeSchedule, - }: { - id: string; - snoozeSchedule: RuleSnoozeSchedule; - } + { id, snoozeSchedule }: SnoozeRuleOptions ) { - const { attributes, version } = await context.unsecuredSavedObjectsClient.get( - 'alert', - id + const { attributes, version } = await withSpan( + { name: 'getRuleSavedObject', type: 'rules' }, + () => + getRuleSavedObject(context, { + ruleId: id, + }) ); try { @@ -93,17 +96,14 @@ async function snoozeWithOCC( throw Boom.badRequest(error.message); } - const updateAttributes = updateMeta(context, { - ...newAttrs, - updatedBy: await context.getUserName(), - updatedAt: new Date().toISOString(), - }); - const updateOptions = { version }; - - await partiallyUpdateAlert( - context.unsecuredSavedObjectsClient, + await updateRuleSo({ + savedObjectsClient: context.unsecuredSavedObjectsClient, + savedObjectsUpdateOptions: { version }, id, - updateAttributes, - updateOptions - ); + updateRuleAttributes: updateMetaAttributes(context, { + ...newAttrs, + updatedBy: await context.getUserName(), + updatedAt: new Date().toISOString(), + }), + }); } diff --git a/x-pack/plugins/alerting/server/application/rule/methods/snooze/types/index.ts b/x-pack/plugins/alerting/server/application/rule/methods/snooze/types/index.ts new file mode 100644 index 0000000000000..ce69db70c3b8b --- /dev/null +++ b/x-pack/plugins/alerting/server/application/rule/methods/snooze/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 * from './snooze_rule_options'; diff --git a/x-pack/plugins/alerting/server/application/rule/methods/snooze/types/snooze_rule_options.ts b/x-pack/plugins/alerting/server/application/rule/methods/snooze/types/snooze_rule_options.ts new file mode 100644 index 0000000000000..77d077b6ee0e5 --- /dev/null +++ b/x-pack/plugins/alerting/server/application/rule/methods/snooze/types/snooze_rule_options.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 { TypeOf } from '@kbn/config-schema'; +import { ruleSnoozeScheduleSchema as ruleSnoozeScheduleRequestSchema } from '../../../../../../common/routes/rule/request'; + +export interface SnoozeRuleOptions { + id: string; + snoozeSchedule: TypeOf; +} diff --git a/x-pack/plugins/alerting/server/application/rule/methods/unsnooze/index.ts b/x-pack/plugins/alerting/server/application/rule/methods/unsnooze/index.ts new file mode 100644 index 0000000000000..3b897aa4675df --- /dev/null +++ b/x-pack/plugins/alerting/server/application/rule/methods/unsnooze/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 { UnsnoozeParams } from './unsnooze_rule'; +export { unsnoozeRule } from './unsnooze_rule'; diff --git a/x-pack/plugins/alerting/server/application/rule/methods/unsnooze/schemas/index.ts b/x-pack/plugins/alerting/server/application/rule/methods/unsnooze/schemas/index.ts new file mode 100644 index 0000000000000..8abf96bb36f04 --- /dev/null +++ b/x-pack/plugins/alerting/server/application/rule/methods/unsnooze/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 { unsnoozeRuleParamsSchema } from './unsnooze_rule_params_schema'; diff --git a/x-pack/plugins/alerting/server/application/rule/methods/unsnooze/schemas/unsnooze_rule_params_schema.ts b/x-pack/plugins/alerting/server/application/rule/methods/unsnooze/schemas/unsnooze_rule_params_schema.ts new file mode 100644 index 0000000000000..3f5b26e072519 --- /dev/null +++ b/x-pack/plugins/alerting/server/application/rule/methods/unsnooze/schemas/unsnooze_rule_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 unsnoozeRuleParamsSchema = schema.object({ + id: schema.string(), + scheduleIds: schema.maybe(schema.arrayOf(schema.string())), +}); diff --git a/x-pack/plugins/alerting/server/rules_client/methods/unsnooze.ts b/x-pack/plugins/alerting/server/application/rule/methods/unsnooze/unsnooze_rule.ts similarity index 54% rename from x-pack/plugins/alerting/server/rules_client/methods/unsnooze.ts rename to x-pack/plugins/alerting/server/application/rule/methods/unsnooze/unsnooze_rule.ts index 59d0ea62eb3ff..c47b39f28aedb 100644 --- a/x-pack/plugins/alerting/server/rules_client/methods/unsnooze.ts +++ b/x-pack/plugins/alerting/server/application/rule/methods/unsnooze/unsnooze_rule.ts @@ -5,21 +5,24 @@ * 2.0. */ -import { RawRule } from '../../types'; -import { WriteOperations, AlertingAuthorizationEntity } from '../../authorization'; -import { retryIfConflicts } from '../../lib/retry_if_conflicts'; -import { partiallyUpdateAlert } from '../../saved_objects'; -import { ruleAuditEvent, RuleAuditAction } from '../common/audit_events'; -import { RulesClientContext } from '../types'; -import { updateMeta } from '../lib'; -import { getUnsnoozeAttributes } from '../common'; +import Boom from '@hapi/boom'; +import { withSpan } from '@kbn/apm-utils'; +import { ruleAuditEvent, RuleAuditAction } from '../../../../rules_client/common/audit_events'; +import { getRuleSavedObject } from '../../../../rules_client/lib'; +import { WriteOperations, AlertingAuthorizationEntity } from '../../../../authorization'; +import { retryIfConflicts } from '../../../../lib/retry_if_conflicts'; +import { RulesClientContext } from '../../../../rules_client/types'; +import { getUnsnoozeAttributes } from '../../../../rules_client/common'; +import { updateRuleSo } from '../../../../data/rule'; +import { updateMetaAttributes } from '../../../../rules_client/lib/update_meta_attributes'; +import { unsnoozeRuleParamsSchema } from './schemas'; export interface UnsnoozeParams { id: string; scheduleIds?: string[]; } -export async function unsnooze( +export async function unsnoozeRule( context: RulesClientContext, { id, scheduleIds }: UnsnoozeParams ): Promise { @@ -31,9 +34,17 @@ export async function unsnooze( } async function unsnoozeWithOCC(context: RulesClientContext, { id, scheduleIds }: UnsnoozeParams) { - const { attributes, version } = await context.unsecuredSavedObjectsClient.get( - 'alert', - id + try { + unsnoozeRuleParamsSchema.validate({ id, scheduleIds }); + } catch (error) { + throw Boom.badRequest(`Error validating unsnooze params - ${error.message}`); + } + const { attributes, version } = await withSpan( + { name: 'getRuleSavedObject', type: 'rules' }, + () => + getRuleSavedObject(context, { + ruleId: id, + }) ); try { @@ -69,17 +80,14 @@ async function unsnoozeWithOCC(context: RulesClientContext, { id, scheduleIds }: context.ruleTypeRegistry.ensureRuleTypeEnabled(attributes.alertTypeId); const newAttrs = getUnsnoozeAttributes(attributes, scheduleIds); - const updateAttributes = updateMeta(context, { - ...newAttrs, - updatedBy: await context.getUserName(), - updatedAt: new Date().toISOString(), - }); - const updateOptions = { version }; - - await partiallyUpdateAlert( - context.unsecuredSavedObjectsClient, + await updateRuleSo({ + savedObjectsClient: context.unsecuredSavedObjectsClient, + savedObjectsUpdateOptions: { version }, id, - updateAttributes, - updateOptions - ); + updateRuleAttributes: updateMetaAttributes(context, { + ...newAttrs, + updatedBy: await context.getUserName(), + updatedAt: new Date().toISOString(), + }), + }); } diff --git a/x-pack/plugins/alerting/server/config.ts b/x-pack/plugins/alerting/server/config.ts index 3ec1edb2f3c1c..a49c393da1e95 100644 --- a/x-pack/plugins/alerting/server/config.ts +++ b/x-pack/plugins/alerting/server/config.ts @@ -39,6 +39,13 @@ const rulesSchema = schema.object({ enforce: schema.boolean({ defaultValue: false }), // if enforce is false, only warnings will be shown }), maxScheduledPerMinute: schema.number({ defaultValue: 10000, max: 10000, min: 0 }), + overwriteProducer: schema.maybe( + schema.oneOf([ + schema.literal('observability'), + schema.literal('siem'), + schema.literal('stackAlerts'), + ]) + ), run: schema.object({ timeout: schema.maybe(schema.string({ validate: validateDurationSchema })), actions: schema.object({ diff --git a/x-pack/plugins/alerting/server/data/r_rule/types/r_rule_attributes.ts b/x-pack/plugins/alerting/server/data/r_rule/types/r_rule_attributes.ts index e29bc5c7ab7e2..54b2547a71b00 100644 --- a/x-pack/plugins/alerting/server/data/r_rule/types/r_rule_attributes.ts +++ b/x-pack/plugins/alerting/server/data/r_rule/types/r_rule_attributes.ts @@ -20,10 +20,10 @@ export interface RRuleAttributes { byweekday?: Array; bymonth?: number[]; bysetpos?: number[]; - bymonthday: number[]; - byyearday: number[]; - byweekno: number[]; - byhour: number[]; - byminute: number[]; - bysecond: number[]; + bymonthday?: number[]; + byyearday?: number[]; + byweekno?: number[]; + byhour?: number[]; + byminute?: number[]; + bysecond?: number[]; } diff --git a/x-pack/plugins/alerting/server/data/rule/index.ts b/x-pack/plugins/alerting/server/data/rule/index.ts index f926adc23f39c..e61b182b92090 100644 --- a/x-pack/plugins/alerting/server/data/rule/index.ts +++ b/x-pack/plugins/alerting/server/data/rule/index.ts @@ -17,5 +17,9 @@ export { bulkCreateRulesSo } from './methods/bulk_create_rule_so'; export type { BulkCreateRulesSoParams } from './methods/bulk_create_rule_so'; export { bulkDeleteRulesSo } from './methods/bulk_delete_rules_so'; export type { BulkDeleteRulesSoParams } from './methods/bulk_delete_rules_so'; +export { resolveRuleSo } from './methods/resolve_rule_so'; +export type { ResolveRuleSoParams } from './methods/resolve_rule_so'; +export { getRuleSo } from './methods/get_rule_so'; +export type { GetRuleSoParams } from './methods/get_rule_so'; export { bulkDisableRulesSo } from './methods/bulk_disable_rules_so'; export type { BulkDisableRulesSoParams } from './methods/bulk_disable_rules_so'; diff --git a/x-pack/plugins/alerting/server/data/rule/methods/get_rule_so.ts b/x-pack/plugins/alerting/server/data/rule/methods/get_rule_so.ts new file mode 100644 index 0000000000000..c8777afef3f78 --- /dev/null +++ b/x-pack/plugins/alerting/server/data/rule/methods/get_rule_so.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 { SavedObjectsClientContract, SavedObject } from '@kbn/core/server'; +import { SavedObjectsGetOptions } from '@kbn/core-saved-objects-api-server'; +import { RuleAttributes } from '../types'; + +export interface GetRuleSoParams { + savedObjectsClient: SavedObjectsClientContract; + id: string; + savedObjectsGetOptions?: SavedObjectsGetOptions; +} + +export const getRuleSo = (params: GetRuleSoParams): Promise> => { + const { savedObjectsClient, id, savedObjectsGetOptions } = params; + + return savedObjectsClient.get('alert', id, savedObjectsGetOptions); +}; diff --git a/x-pack/plugins/alerting/server/data/rule/methods/resolve_rule_so.ts b/x-pack/plugins/alerting/server/data/rule/methods/resolve_rule_so.ts new file mode 100644 index 0000000000000..b8061cc6e3c3c --- /dev/null +++ b/x-pack/plugins/alerting/server/data/rule/methods/resolve_rule_so.ts @@ -0,0 +1,24 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { SavedObjectsClientContract, SavedObjectsResolveResponse } from '@kbn/core/server'; +import { SavedObjectsResolveOptions } from '@kbn/core-saved-objects-api-server'; +import { RuleAttributes } from '../types'; + +export interface ResolveRuleSoParams { + savedObjectsClient: SavedObjectsClientContract; + id: string; + savedObjectsResolveOptions?: SavedObjectsResolveOptions; +} + +export const resolveRuleSo = ( + params: ResolveRuleSoParams +): Promise> => { + const { savedObjectsClient, id, savedObjectsResolveOptions } = params; + + return savedObjectsClient.resolve('alert', id, savedObjectsResolveOptions); +}; diff --git a/x-pack/plugins/alerting/server/lib/create_get_alert_indices_alias.test.ts b/x-pack/plugins/alerting/server/lib/create_get_alert_indices_alias.test.ts index 52b9a12cc35c0..9a8109977962c 100644 --- a/x-pack/plugins/alerting/server/lib/create_get_alert_indices_alias.test.ts +++ b/x-pack/plugins/alerting/server/lib/create_get_alert_indices_alias.test.ts @@ -15,6 +15,7 @@ import { ILicenseState } from './license_state'; import { licenseStateMock } from './license_state.mock'; import { schema } from '@kbn/config-schema'; import { createGetAlertIndicesAliasFn } from './create_get_alert_indices_alias'; +import { AlertingConfig } from '../config'; describe('createGetAlertIndicesAliasFn', () => { const logger = loggingSystemMock.create().get(); @@ -23,6 +24,7 @@ describe('createGetAlertIndicesAliasFn', () => { const inMemoryMetrics = inMemoryMetricsMock.create(); const ruleTypeRegistryParams: ConstructorOptions = { + config: {} as AlertingConfig, logger, taskManager, taskRunnerFactory: new TaskRunnerFactory(), diff --git a/x-pack/plugins/alerting/server/plugin.ts b/x-pack/plugins/alerting/server/plugin.ts index 80b71a4dd8a7c..03431c2804c6e 100644 --- a/x-pack/plugins/alerting/server/plugin.ts +++ b/x-pack/plugins/alerting/server/plugin.ts @@ -97,7 +97,7 @@ import { type InitializationPromise, errorResult, } from './alerts_service'; -import { rulesSettingsFeature } from './rules_settings_feature'; +import { getRulesSettingsFeature } 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'; @@ -255,7 +255,7 @@ export class AlertingPlugin { }; }); - plugins.features.registerKibanaFeature(rulesSettingsFeature); + plugins.features.registerKibanaFeature(getRulesSettingsFeature(!!plugins.serverless)); plugins.features.registerKibanaFeature(maintenanceWindowFeature); @@ -296,6 +296,7 @@ export class AlertingPlugin { } const ruleTypeRegistry = new RuleTypeRegistry({ + config: this.config, logger: this.logger, taskManager: plugins.taskManager, taskRunnerFactory: this.taskRunnerFactory, diff --git a/x-pack/plugins/alerting/server/routes/index.ts b/x-pack/plugins/alerting/server/routes/index.ts index 93c66c45ce2af..d28854fb3ac6a 100644 --- a/x-pack/plugins/alerting/server/routes/index.ts +++ b/x-pack/plugins/alerting/server/routes/index.ts @@ -29,7 +29,7 @@ import { getActionErrorLogRoute } from './get_action_error_log'; import { getRuleExecutionKPIRoute } from './get_rule_execution_kpi'; import { getRuleStateRoute } from './get_rule_state'; import { healthRoute } from './health'; -import { resolveRuleRoute } from './resolve_rule'; +import { resolveRuleRoute } from './rule/apis/resolve'; import { ruleTypesRoute } from './rule_types'; import { muteAllRuleRoute } from './mute_all_rule'; import { muteAlertRoute } from './rule/apis/mute_alert/mute_alert'; @@ -37,8 +37,8 @@ import { unmuteAllRuleRoute } from './unmute_all_rule'; import { unmuteAlertRoute } from './unmute_alert'; import { updateRuleApiKeyRoute } from './update_rule_api_key'; import { bulkEditInternalRulesRoute } from './rule/apis/bulk_edit/bulk_edit_rules_route'; -import { snoozeRuleRoute } from './snooze_rule'; -import { unsnoozeRuleRoute } from './unsnooze_rule'; +import { snoozeRuleRoute } from './rule/apis/snooze'; +import { unsnoozeRuleRoute } from './rule/apis/unsnooze'; import { runSoonRoute } from './run_soon'; import { bulkDeleteRulesRoute } from './rule/apis/bulk_delete/bulk_delete_rules_route'; import { bulkEnableRulesRoute } from './bulk_enable_rules'; diff --git a/x-pack/plugins/alerting/server/routes/resolve_rule.ts b/x-pack/plugins/alerting/server/routes/resolve_rule.ts deleted file mode 100644 index e42dd6795f14a..0000000000000 --- a/x-pack/plugins/alerting/server/routes/resolve_rule.ts +++ /dev/null @@ -1,91 +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 { omit } from 'lodash'; -import { schema } from '@kbn/config-schema'; -import { IRouter } from '@kbn/core/server'; -import { ILicenseState } from '../lib'; -import { - verifyAccessAndContext, - RewriteResponseCase, - rewriteRuleLastRun, - rewriteActionsRes, -} from './lib'; -import { - RuleTypeParams, - AlertingRequestHandlerContext, - INTERNAL_BASE_ALERTING_API_PATH, - ResolvedSanitizedRule, -} from '../types'; - -const paramSchema = schema.object({ - id: schema.string(), -}); - -const rewriteBodyRes: RewriteResponseCase> = ({ - alertTypeId, - createdBy, - updatedBy, - createdAt, - updatedAt, - apiKeyOwner, - apiKeyCreatedByUser, - notifyWhen, - muteAll, - mutedInstanceIds, - executionStatus, - actions, - scheduledTaskId, - lastRun, - nextRun, - ...rest -}) => ({ - ...rest, - rule_type_id: alertTypeId, - created_by: createdBy, - updated_by: updatedBy, - created_at: createdAt, - updated_at: updatedAt, - api_key_owner: apiKeyOwner, - notify_when: notifyWhen, - mute_all: muteAll, - muted_alert_ids: mutedInstanceIds, - scheduled_task_id: scheduledTaskId, - execution_status: executionStatus && { - ...omit(executionStatus, 'lastExecutionDate', 'lastDuration'), - last_execution_date: executionStatus.lastExecutionDate, - last_duration: executionStatus.lastDuration, - }, - actions: rewriteActionsRes(actions), - ...(lastRun ? { last_run: rewriteRuleLastRun(lastRun) } : {}), - ...(nextRun ? { next_run: nextRun } : {}), - ...(apiKeyCreatedByUser !== undefined ? { api_key_created_by_user: apiKeyCreatedByUser } : {}), -}); - -export const resolveRuleRoute = ( - router: IRouter, - licenseState: ILicenseState -) => { - router.get( - { - path: `${INTERNAL_BASE_ALERTING_API_PATH}/rule/{id}/_resolve`, - validate: { - params: paramSchema, - }, - }, - router.handleLegacyErrors( - verifyAccessAndContext(licenseState, async function (context, req, res) { - const rulesClient = (await context.alerting).getRulesClient(); - const { id } = req.params; - const rule = await rulesClient.resolve({ id, includeSnoozeData: true }); - return res.ok({ - body: rewriteBodyRes(rule), - }); - }) - ) - ); -}; diff --git a/x-pack/plugins/alerting/server/routes/rule/apis/resolve/index.ts b/x-pack/plugins/alerting/server/routes/rule/apis/resolve/index.ts new file mode 100644 index 0000000000000..5b8e8120f92f9 --- /dev/null +++ b/x-pack/plugins/alerting/server/routes/rule/apis/resolve/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 { resolveRuleRoute } from './resolve_rule_route'; diff --git a/x-pack/plugins/alerting/server/routes/resolve_rule.test.ts b/x-pack/plugins/alerting/server/routes/rule/apis/resolve/resolve_rule_route.test.ts similarity index 75% rename from x-pack/plugins/alerting/server/routes/resolve_rule.test.ts rename to x-pack/plugins/alerting/server/routes/rule/apis/resolve/resolve_rule_route.test.ts index 273a7ea7fb8aa..e83cd05b02edd 100644 --- a/x-pack/plugins/alerting/server/routes/resolve_rule.test.ts +++ b/x-pack/plugins/alerting/server/routes/rule/apis/resolve/resolve_rule_route.test.ts @@ -6,17 +6,17 @@ */ import { pick } from 'lodash'; -import { resolveRuleRoute } from './resolve_rule'; +import { resolveRuleRoute } from './resolve_rule_route'; import { httpServiceMock } from '@kbn/core/server/mocks'; -import { licenseStateMock } from '../lib/license_state.mock'; -import { verifyApiAccess } from '../lib/license_api_access'; -import { mockHandlerArguments } from './_mock_handler_arguments'; -import { rulesClientMock } from '../rules_client.mock'; -import { ResolvedSanitizedRule } from '../types'; -import { AsApiContract } from './lib'; +import { licenseStateMock } from '../../../../lib/license_state.mock'; +import { verifyApiAccess } from '../../../../lib/license_api_access'; +import { mockHandlerArguments } from '../../../_mock_handler_arguments'; +import { rulesClientMock } from '../../../../rules_client.mock'; +import { ResolvedRule } from '../../../../application/rule/methods/resolve/types'; +import { ResolvedSanitizedRule } from '../../../../../common'; const rulesClient = rulesClientMock.create(); -jest.mock('../lib/license_api_access', () => ({ +jest.mock('../../../../lib/license_api_access', () => ({ verifyApiAccess: jest.fn(), })); @@ -25,7 +25,7 @@ beforeEach(() => { }); describe('resolveRuleRoute', () => { - const mockedRule: ResolvedSanitizedRule<{ + const mockedRule: ResolvedRule<{ bar: boolean; }> = { id: '1', @@ -67,7 +67,7 @@ describe('resolveRuleRoute', () => { revision: 0, }; - const resolveResult: AsApiContract> = { + const resolveResult = { ...pick( mockedRule, 'consumer', @@ -86,13 +86,13 @@ describe('resolveRuleRoute', () => { updated_by: mockedRule.updatedBy, api_key_owner: mockedRule.apiKeyOwner, muted_alert_ids: mockedRule.mutedInstanceIds, - created_at: mockedRule.createdAt, - updated_at: mockedRule.updatedAt, + created_at: mockedRule.createdAt.toISOString(), + updated_at: mockedRule.updatedAt.toISOString(), id: mockedRule.id, revision: mockedRule.revision, execution_status: { status: mockedRule.executionStatus.status, - last_execution_date: mockedRule.executionStatus.lastExecutionDate, + last_execution_date: mockedRule.executionStatus.lastExecutionDate.toISOString(), }, actions: [ { @@ -115,7 +115,9 @@ describe('resolveRuleRoute', () => { expect(config.path).toMatchInlineSnapshot(`"/internal/alerting/rule/{id}/_resolve"`); - rulesClient.resolve.mockResolvedValueOnce(mockedRule); + // TODO (http-versioning): Remove this cast, this enables us to move forward + // without fixing all of other solution types + rulesClient.resolve.mockResolvedValueOnce(mockedRule as ResolvedSanitizedRule); const [context, req, res] = mockHandlerArguments( { rulesClient }, @@ -142,7 +144,9 @@ describe('resolveRuleRoute', () => { const [, handler] = router.get.mock.calls[0]; - rulesClient.resolve.mockResolvedValueOnce(mockedRule); + // TODO (http-versioning): Remove this cast, this enables us to move forward + // without fixing all of other solution types + rulesClient.resolve.mockResolvedValueOnce(mockedRule as ResolvedSanitizedRule); const [context, req, res] = mockHandlerArguments( { rulesClient }, @@ -169,7 +173,9 @@ describe('resolveRuleRoute', () => { const [, handler] = router.get.mock.calls[0]; - rulesClient.resolve.mockResolvedValueOnce(mockedRule); + // TODO (http-versioning): Remove this cast, this enables us to move forward + // without fixing all of other solution types + rulesClient.resolve.mockResolvedValueOnce(mockedRule as ResolvedSanitizedRule); const [context, req, res] = mockHandlerArguments( { rulesClient }, diff --git a/x-pack/plugins/alerting/server/routes/rule/apis/resolve/resolve_rule_route.ts b/x-pack/plugins/alerting/server/routes/rule/apis/resolve/resolve_rule_route.ts new file mode 100644 index 0000000000000..2e6f016b5f6ac --- /dev/null +++ b/x-pack/plugins/alerting/server/routes/rule/apis/resolve/resolve_rule_route.ts @@ -0,0 +1,52 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { TypeOf } from '@kbn/config-schema'; +import { IRouter } from '@kbn/core/server'; +import { RuleParamsV1 } from '../../../../../common/routes/rule/response'; +import { ResolvedRule } from '../../../../application/rule/methods/resolve/types'; +import { + resolveParamsSchemaV1, + ResolveRuleResponseV1, +} from '../../../../../common/routes/rule/apis/resolve'; +import { ILicenseState } from '../../../../lib'; +import { verifyAccessAndContext } from '../../../lib'; +import { AlertingRequestHandlerContext, INTERNAL_BASE_ALERTING_API_PATH } from '../../../../types'; +import { transformResolveResponseV1 } from './transforms'; + +export type ResolveRuleRequestParamsV1 = TypeOf; + +export const resolveRuleRoute = ( + router: IRouter, + licenseState: ILicenseState +) => { + router.get( + { + path: `${INTERNAL_BASE_ALERTING_API_PATH}/rule/{id}/_resolve`, + validate: { + params: resolveParamsSchemaV1, + }, + }, + router.handleLegacyErrors( + verifyAccessAndContext(licenseState, async function (context, req, res) { + const rulesClient = (await context.alerting).getRulesClient(); + const params: ResolveRuleRequestParamsV1 = req.params; + const { id } = params; + // TODO (http-versioning): Remove this cast, this enables us to move forward + // without fixing all of other solution types + const rule = (await rulesClient.resolve({ + id, + includeSnoozeData: true, + })) as ResolvedRule; + const response: ResolveRuleResponseV1 = { + body: transformResolveResponseV1(rule), + }; + return res.ok(response); + }) + ) + ); +}; diff --git a/x-pack/plugins/alerting/server/routes/rule/apis/resolve/transforms/index.ts b/x-pack/plugins/alerting/server/routes/rule/apis/resolve/transforms/index.ts new file mode 100644 index 0000000000000..bda58b81a7238 --- /dev/null +++ b/x-pack/plugins/alerting/server/routes/rule/apis/resolve/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 { transformResolveResponse } from './transform_resolve_response/latest'; + +export { transformResolveResponse as transformResolveResponseV1 } from './transform_resolve_response/v1'; diff --git a/x-pack/plugins/alerting/server/routes/rule/apis/resolve/transforms/transform_resolve_response/latest.ts b/x-pack/plugins/alerting/server/routes/rule/apis/resolve/transforms/transform_resolve_response/latest.ts new file mode 100644 index 0000000000000..25300c97a6d2e --- /dev/null +++ b/x-pack/plugins/alerting/server/routes/rule/apis/resolve/transforms/transform_resolve_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 * from './v1'; diff --git a/x-pack/plugins/alerting/server/routes/rule/apis/resolve/transforms/transform_resolve_response/v1.ts b/x-pack/plugins/alerting/server/routes/rule/apis/resolve/transforms/transform_resolve_response/v1.ts new file mode 100644 index 0000000000000..060f6892403f4 --- /dev/null +++ b/x-pack/plugins/alerting/server/routes/rule/apis/resolve/transforms/transform_resolve_response/v1.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 { ResolvedRule } from '../../../../../../application/rule/methods/resolve/types'; +import { RuleParams } from '../../../../../../application/rule/types'; +import { transformRuleToRuleResponseV1 } from '../../../../transforms'; + +export const transformResolveResponse = ( + rule: ResolvedRule +) => ({ + ...transformRuleToRuleResponseV1(rule), + outcome: rule.outcome, + alias_target_id: rule.alias_target_id, +}); diff --git a/x-pack/plugins/alerting/server/routes/rule/apis/snooze/index.ts b/x-pack/plugins/alerting/server/routes/rule/apis/snooze/index.ts new file mode 100644 index 0000000000000..2554a9040c650 --- /dev/null +++ b/x-pack/plugins/alerting/server/routes/rule/apis/snooze/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 { snoozeRuleRoute } from './snooze_rule_route'; diff --git a/x-pack/plugins/alerting/server/routes/snooze_rule.test.ts b/x-pack/plugins/alerting/server/routes/rule/apis/snooze/snooze_rule_route.test.ts similarity index 90% rename from x-pack/plugins/alerting/server/routes/snooze_rule.test.ts rename to x-pack/plugins/alerting/server/routes/rule/apis/snooze/snooze_rule_route.test.ts index ab24103672521..51d1b9a23cda8 100644 --- a/x-pack/plugins/alerting/server/routes/snooze_rule.test.ts +++ b/x-pack/plugins/alerting/server/routes/rule/apis/snooze/snooze_rule_route.test.ts @@ -5,15 +5,15 @@ * 2.0. */ -import { snoozeRuleRoute } from './snooze_rule'; +import { snoozeRuleRoute } from './snooze_rule_route'; import { httpServiceMock } from '@kbn/core/server/mocks'; -import { licenseStateMock } from '../lib/license_state.mock'; -import { mockHandlerArguments } from './_mock_handler_arguments'; -import { rulesClientMock } from '../rules_client.mock'; -import { RuleTypeDisabledError } from '../lib/errors/rule_type_disabled'; +import { licenseStateMock } from '../../../../lib/license_state.mock'; +import { mockHandlerArguments } from '../../../_mock_handler_arguments'; +import { rulesClientMock } from '../../../../rules_client.mock'; +import { RuleTypeDisabledError } from '../../../../lib/errors/rule_type_disabled'; const rulesClient = rulesClientMock.create(); -jest.mock('../lib/license_api_access', () => ({ +jest.mock('../../../../lib/license_api_access', () => ({ verifyApiAccess: jest.fn(), })); diff --git a/x-pack/plugins/alerting/server/routes/snooze_rule.ts b/x-pack/plugins/alerting/server/routes/rule/apis/snooze/snooze_rule_route.ts similarity index 52% rename from x-pack/plugins/alerting/server/routes/snooze_rule.ts rename to x-pack/plugins/alerting/server/routes/rule/apis/snooze/snooze_rule_route.ts index 1ffac168fcd00..93b619b50d82c 100644 --- a/x-pack/plugins/alerting/server/routes/snooze_rule.ts +++ b/x-pack/plugins/alerting/server/routes/rule/apis/snooze/snooze_rule_route.ts @@ -5,36 +5,18 @@ * 2.0. */ +import { TypeOf } from '@kbn/config-schema'; import { IRouter } from '@kbn/core/server'; -import { schema } from '@kbn/config-schema'; -import { ILicenseState, RuleMutedError } from '../lib'; -import { verifyAccessAndContext, rRuleSchema } from './lib'; -import { SnoozeOptions } from '../rules_client'; -import { AlertingRequestHandlerContext, INTERNAL_ALERTING_SNOOZE_RULE } from '../types'; -import { validateSnoozeSchedule } from '../lib/validate_snooze_schedule'; +import { + snoozeBodySchema, + snoozeParamsSchema, +} from '../../../../../common/routes/rule/apis/snooze'; +import { ILicenseState, RuleMutedError } from '../../../../lib'; +import { verifyAccessAndContext } from '../../../lib'; +import { AlertingRequestHandlerContext, INTERNAL_ALERTING_SNOOZE_RULE } from '../../../../types'; +import { transformSnoozeBodyV1 } from './transforms'; -const paramSchema = schema.object({ - id: schema.string(), -}); - -export const snoozeScheduleSchema = schema.object( - { - id: schema.maybe(schema.string()), - duration: schema.number(), - rRule: rRuleSchema, - }, - { validate: validateSnoozeSchedule } -); - -const bodySchema = schema.object({ - snooze_schedule: snoozeScheduleSchema, -}); - -const rewriteBodyReq: (opts: { - snooze_schedule: SnoozeOptions['snoozeSchedule']; -}) => SnoozeOptions = ({ snooze_schedule: snoozeSchedule }) => ({ - snoozeSchedule, -}); +export type SnoozeRuleRequestParamsV1 = TypeOf; export const snoozeRuleRoute = ( router: IRouter, @@ -44,15 +26,15 @@ export const snoozeRuleRoute = ( { path: INTERNAL_ALERTING_SNOOZE_RULE, validate: { - params: paramSchema, - body: bodySchema, + params: snoozeParamsSchema, + body: snoozeBodySchema, }, }, router.handleLegacyErrors( verifyAccessAndContext(licenseState, async function (context, req, res) { const rulesClient = (await context.alerting).getRulesClient(); - const params = req.params; - const body = rewriteBodyReq(req.body); + const params: SnoozeRuleRequestParamsV1 = req.params; + const body = transformSnoozeBodyV1(req.body); try { await rulesClient.snooze({ ...params, ...body }); return res.noContent(); diff --git a/x-pack/plugins/alerting/server/routes/rule/apis/snooze/transforms/index.ts b/x-pack/plugins/alerting/server/routes/rule/apis/snooze/transforms/index.ts new file mode 100644 index 0000000000000..fce05888d26fa --- /dev/null +++ b/x-pack/plugins/alerting/server/routes/rule/apis/snooze/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 { transformSnoozeBody } from './transform_snooze_body/latest'; + +export { transformSnoozeBody as transformSnoozeBodyV1 } from './transform_snooze_body/v1'; diff --git a/x-pack/plugins/alerting/server/routes/rule/apis/snooze/transforms/transform_snooze_body/latest.ts b/x-pack/plugins/alerting/server/routes/rule/apis/snooze/transforms/transform_snooze_body/latest.ts new file mode 100644 index 0000000000000..25300c97a6d2e --- /dev/null +++ b/x-pack/plugins/alerting/server/routes/rule/apis/snooze/transforms/transform_snooze_body/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/alerting/server/routes/rule/apis/snooze/transforms/transform_snooze_body/v1.ts b/x-pack/plugins/alerting/server/routes/rule/apis/snooze/transforms/transform_snooze_body/v1.ts new file mode 100644 index 0000000000000..ff7c890ef9cbd --- /dev/null +++ b/x-pack/plugins/alerting/server/routes/rule/apis/snooze/transforms/transform_snooze_body/v1.ts @@ -0,0 +1,17 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { TypeOf } from '@kbn/config-schema'; +import { snoozeBodySchemaV1 } from '../../../../../../../common/routes/rule/apis/snooze'; + +type SnoozeBodySchema = TypeOf; + +export const transformSnoozeBody: (opts: SnoozeBodySchema) => { + snoozeSchedule: SnoozeBodySchema['snooze_schedule']; +} = ({ snooze_schedule: snoozeSchedule }) => ({ + snoozeSchedule, +}); diff --git a/x-pack/plugins/alerting/server/routes/rule/apis/unsnooze/index.ts b/x-pack/plugins/alerting/server/routes/rule/apis/unsnooze/index.ts new file mode 100644 index 0000000000000..5702c1a2da283 --- /dev/null +++ b/x-pack/plugins/alerting/server/routes/rule/apis/unsnooze/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 { unsnoozeRuleRoute } from './unsnooze_rule_route'; diff --git a/x-pack/plugins/alerting/server/routes/rule/apis/unsnooze/transforms/index.ts b/x-pack/plugins/alerting/server/routes/rule/apis/unsnooze/transforms/index.ts new file mode 100644 index 0000000000000..1ebc46c14819e --- /dev/null +++ b/x-pack/plugins/alerting/server/routes/rule/apis/unsnooze/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 { transformUnsnoozeBody } from './transform_unsnooze_body/latest'; + +export { transformUnsnoozeBody as transformUnsnoozeBodyV1 } from './transform_unsnooze_body/v1'; diff --git a/x-pack/plugins/alerting/server/routes/rule/apis/unsnooze/transforms/transform_unsnooze_body/latest.ts b/x-pack/plugins/alerting/server/routes/rule/apis/unsnooze/transforms/transform_unsnooze_body/latest.ts new file mode 100644 index 0000000000000..25300c97a6d2e --- /dev/null +++ b/x-pack/plugins/alerting/server/routes/rule/apis/unsnooze/transforms/transform_unsnooze_body/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/alerting/server/routes/rule/apis/unsnooze/transforms/transform_unsnooze_body/v1.ts b/x-pack/plugins/alerting/server/routes/rule/apis/unsnooze/transforms/transform_unsnooze_body/v1.ts new file mode 100644 index 0000000000000..bbaa37cf81f3b --- /dev/null +++ b/x-pack/plugins/alerting/server/routes/rule/apis/unsnooze/transforms/transform_unsnooze_body/v1.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 const transformUnsnoozeBody: (opts: { schedule_ids?: string[] }) => { + scheduleIds?: string[]; +} = ({ schedule_ids: scheduleIds }) => (scheduleIds ? { scheduleIds } : {}); diff --git a/x-pack/plugins/alerting/server/routes/unsnooze_rule.test.ts b/x-pack/plugins/alerting/server/routes/rule/apis/unsnooze/unsnooze_rule_route.test.ts similarity index 83% rename from x-pack/plugins/alerting/server/routes/unsnooze_rule.test.ts rename to x-pack/plugins/alerting/server/routes/rule/apis/unsnooze/unsnooze_rule_route.test.ts index 12a4c250bef1d..1d69b00eb8486 100644 --- a/x-pack/plugins/alerting/server/routes/unsnooze_rule.test.ts +++ b/x-pack/plugins/alerting/server/routes/rule/apis/unsnooze/unsnooze_rule_route.test.ts @@ -5,15 +5,15 @@ * 2.0. */ -import { unsnoozeRuleRoute } from './unsnooze_rule'; +import { unsnoozeRuleRoute } from './unsnooze_rule_route'; import { httpServiceMock } from '@kbn/core/server/mocks'; -import { licenseStateMock } from '../lib/license_state.mock'; -import { mockHandlerArguments } from './_mock_handler_arguments'; -import { rulesClientMock } from '../rules_client.mock'; -import { RuleTypeDisabledError } from '../lib/errors/rule_type_disabled'; +import { licenseStateMock } from '../../../../lib/license_state.mock'; +import { mockHandlerArguments } from '../../../_mock_handler_arguments'; +import { rulesClientMock } from '../../../../rules_client.mock'; +import { RuleTypeDisabledError } from '../../../../lib/errors/rule_type_disabled'; const rulesClient = rulesClientMock.create(); -jest.mock('../lib/license_api_access', () => ({ +jest.mock('../../../../lib/license_api_access', () => ({ verifyApiAccess: jest.fn(), })); diff --git a/x-pack/plugins/alerting/server/routes/unsnooze_rule.ts b/x-pack/plugins/alerting/server/routes/rule/apis/unsnooze/unsnooze_rule_route.ts similarity index 60% rename from x-pack/plugins/alerting/server/routes/unsnooze_rule.ts rename to x-pack/plugins/alerting/server/routes/rule/apis/unsnooze/unsnooze_rule_route.ts index 5efea85c93ec1..e37b5c0217f0a 100644 --- a/x-pack/plugins/alerting/server/routes/unsnooze_rule.ts +++ b/x-pack/plugins/alerting/server/routes/rule/apis/unsnooze/unsnooze_rule_route.ts @@ -5,25 +5,18 @@ * 2.0. */ +import { TypeOf } from '@kbn/config-schema'; import { IRouter } from '@kbn/core/server'; -import { schema } from '@kbn/config-schema'; -import { ILicenseState, RuleMutedError } from '../lib'; -import { verifyAccessAndContext, RewriteRequestCase } from './lib'; -import { AlertingRequestHandlerContext, INTERNAL_BASE_ALERTING_API_PATH } from '../types'; +import { + unsnoozeBodySchema, + unsnoozeParamsSchema, +} from '../../../../../common/routes/rule/apis/unsnooze'; +import { ILicenseState, RuleMutedError } from '../../../../lib'; +import { verifyAccessAndContext } from '../../../lib'; +import { AlertingRequestHandlerContext, INTERNAL_BASE_ALERTING_API_PATH } from '../../../../types'; +import { transformUnsnoozeBodyV1 } from './transforms'; -const paramSchema = schema.object({ - id: schema.string(), -}); - -export const scheduleIdsSchema = schema.maybe(schema.arrayOf(schema.string())); - -const bodySchema = schema.object({ - schedule_ids: scheduleIdsSchema, -}); - -const rewriteBodyReq: RewriteRequestCase<{ scheduleIds?: string[] }> = ({ - schedule_ids: scheduleIds, -}) => (scheduleIds ? { scheduleIds } : {}); +export type UnsnoozeRuleRequestParamsV1 = TypeOf; export const unsnoozeRuleRoute = ( router: IRouter, @@ -33,15 +26,15 @@ export const unsnoozeRuleRoute = ( { path: `${INTERNAL_BASE_ALERTING_API_PATH}/rule/{id}/_unsnooze`, validate: { - params: paramSchema, - body: bodySchema, + params: unsnoozeParamsSchema, + body: unsnoozeBodySchema, }, }, router.handleLegacyErrors( verifyAccessAndContext(licenseState, async function (context, req, res) { const rulesClient = (await context.alerting).getRulesClient(); - const params = req.params; - const body = rewriteBodyReq(req.body); + const params: UnsnoozeRuleRequestParamsV1 = req.params; + const body = transformUnsnoozeBodyV1(req.body); try { await rulesClient.unsnooze({ ...params, ...body }); return res.noContent(); diff --git a/x-pack/plugins/alerting/server/routes/rule/transforms/transform_rule_to_rule_response/v1.ts b/x-pack/plugins/alerting/server/routes/rule/transforms/transform_rule_to_rule_response/v1.ts index e43427fe4470a..74508cec9a640 100644 --- a/x-pack/plugins/alerting/server/routes/rule/transforms/transform_rule_to_rule_response/v1.ts +++ b/x-pack/plugins/alerting/server/routes/rule/transforms/transform_rule_to_rule_response/v1.ts @@ -82,6 +82,7 @@ export const transformRuleToRuleResponse = ( mute_all: rule.muteAll, ...(rule.notifyWhen !== undefined ? { notify_when: rule.notifyWhen } : {}), muted_alert_ids: rule.mutedInstanceIds, + ...(rule.scheduledTaskId !== undefined ? { scheduled_task_id: rule.scheduledTaskId } : {}), execution_status: { status: rule.executionStatus.status, ...(rule.executionStatus.error ? { error: rule.executionStatus.error } : {}), 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 1de3f7c0be400..8e01e7d05cbd1 100644 --- a/x-pack/plugins/alerting/server/rule_type_registry.test.ts +++ b/x-pack/plugins/alerting/server/rule_type_registry.test.ts @@ -17,6 +17,7 @@ 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 { AlertingConfig } from './config'; const logger = loggingSystemMock.create().get(); let mockedLicenseState: jest.Mocked; @@ -30,6 +31,7 @@ beforeEach(() => { jest.clearAllMocks(); mockedLicenseState = licenseStateMock.create(); ruleTypeRegistryParams = { + config: {} as AlertingConfig, logger, taskManager, taskRunnerFactory: new TaskRunnerFactory(), @@ -582,6 +584,63 @@ describe('Create Lifecycle', () => { expect(alertsService.register).not.toHaveBeenCalled(); }); + + test('registers rule with no overwrite on producer', () => { + const ruleType: RuleType = { + id: 'test', + name: 'Test', + actionGroups: [ + { + id: 'default', + name: 'Default', + }, + ], + defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', + isExportable: true, + executor: jest.fn(), + category: 'test', + producer: 'alerts', + ruleTaskTimeout: '20m', + validate: { + params: { validate: (params) => params }, + }, + }; + const registry = new RuleTypeRegistry(ruleTypeRegistryParams); + registry.register(ruleType); + expect(registry.get('test').producer).toEqual('alerts'); + }); + }); + + describe('register() with overwriteProducer', () => { + test('registers rule and overwrite producer', () => { + const ruleType: RuleType = { + id: 'test', + name: 'Test', + actionGroups: [ + { + id: 'default', + name: 'Default', + }, + ], + defaultActionGroupId: 'default', + minimumLicenseRequired: 'basic', + isExportable: true, + executor: jest.fn(), + category: 'test', + producer: 'alerts', + ruleTaskTimeout: '20m', + validate: { + params: { validate: (params) => params }, + }, + }; + const registry = new RuleTypeRegistry({ + ...ruleTypeRegistryParams, + config: { rules: { overwriteProducer: 'observability' } } as unknown as AlertingConfig, + }); + registry.register(ruleType); + expect(registry.get('test').producer).toEqual('observability'); + }); }); describe('get()', () => { diff --git a/x-pack/plugins/alerting/server/rule_type_registry.ts b/x-pack/plugins/alerting/server/rule_type_registry.ts index 1d147c2cb3d6a..d73d28950970e 100644 --- a/x-pack/plugins/alerting/server/rule_type_registry.ts +++ b/x-pack/plugins/alerting/server/rule_type_registry.ts @@ -39,8 +39,10 @@ import { InMemoryMetrics } from './monitoring'; import { AlertingRulesConfig } from '.'; import { AlertsService } from './alerts_service/alerts_service'; import { getRuleTypeIdValidLegacyConsumers } from './rule_type_registry_deprecated_consumers'; +import { AlertingConfig } from './config'; export interface ConstructorOptions { + config: AlertingConfig; logger: Logger; taskManager: TaskManagerSetupContract; taskRunnerFactory: TaskRunnerFactory; @@ -148,6 +150,7 @@ export type UntypedNormalizedRuleType = NormalizedRuleType< >; export class RuleTypeRegistry { + private readonly config: AlertingConfig; private readonly logger: Logger; private readonly taskManager: TaskManagerSetupContract; private readonly ruleTypes: Map = new Map(); @@ -159,6 +162,7 @@ export class RuleTypeRegistry { private readonly alertsService: AlertsService | null; constructor({ + config, logger, taskManager, taskRunnerFactory, @@ -168,6 +172,7 @@ export class RuleTypeRegistry { inMemoryMetrics, alertsService, }: ConstructorOptions) { + this.config = config; this.logger = logger; this.taskManager = taskManager; this.taskRunnerFactory = taskRunnerFactory; @@ -277,7 +282,7 @@ export class RuleTypeRegistry { ActionGroupIds, RecoveryActionGroupId, AlertData - >(ruleType); + >(ruleType, this.config); this.ruleTypes.set( ruleTypeIdSchema.validate(ruleType.id), @@ -457,7 +462,8 @@ function augmentActionGroupsWithReserved< ActionGroupIds, RecoveryActionGroupId, AlertData - > + >, + config: AlertingConfig ): NormalizedRuleType< Params, ExtractedParams, @@ -505,6 +511,7 @@ function augmentActionGroupsWithReserved< return { ...ruleType, + ...(config?.rules?.overwriteProducer ? { producer: config.rules.overwriteProducer } : {}), actionGroups: [...actionGroups, ...reservedActionGroups], recoveryActionGroup: recoveryActionGroup ?? RecoveredActionGroup, validLegacyConsumers: getRuleTypeIdValidLegacyConsumers(id), diff --git a/x-pack/plugins/alerting/server/rules_client/common/snooze_utils.ts b/x-pack/plugins/alerting/server/rules_client/common/snooze_utils.ts index edf61427b8339..1f8cf501f7868 100644 --- a/x-pack/plugins/alerting/server/rules_client/common/snooze_utils.ts +++ b/x-pack/plugins/alerting/server/rules_client/common/snooze_utils.ts @@ -6,18 +6,19 @@ */ import { i18n } from '@kbn/i18n'; -import { RawRule, RuleSnoozeSchedule } from '../../types'; import { + Rule, RuleDomain, RuleParams, RuleSnoozeSchedule as RuleDomainSnoozeSchedule, } from '../../application/rule/types'; +import { RuleAttributes } from '../../data/rule/types'; import { getActiveScheduledSnoozes } from '../../lib/is_rule_snoozed'; -/** - * @deprecated TODO (http-versioning): Deprecate this once we fix all RawRule types - */ -export function getSnoozeAttributes(attributes: RawRule, snoozeSchedule: RuleSnoozeSchedule) { +export function getSnoozeAttributes( + attributes: RuleAttributes, + snoozeSchedule: RuleDomainSnoozeSchedule +) { // If duration is -1, instead mute all const { id: snoozeId, duration } = snoozeSchedule; @@ -69,10 +70,7 @@ export function getBulkSnooze( }; } -/** - * @deprecated TODO (http-versioning): Deprecate this once we fix all RawRule types - */ -export function getUnsnoozeAttributes(attributes: RawRule, scheduleIds?: string[]) { +export function getUnsnoozeAttributes(attributes: RuleAttributes, scheduleIds?: string[]) { const snoozeSchedule = scheduleIds ? clearScheduledSnoozesAttributesById(attributes, scheduleIds) : clearCurrentActiveSnoozeAttributes(attributes); @@ -106,10 +104,7 @@ export function getBulkUnsnooze( }; } -/** - * @deprecated TODO (http-versioning): Deprecate this once we fix all RawRule types - */ -export function clearUnscheduledSnoozeAttributes(attributes: RawRule) { +export function clearUnscheduledSnoozeAttributes(attributes: RuleAttributes) { // Clear any snoozes that have no ID property. These are "simple" snoozes created with the quick UI, e.g. snooze for 3 days starting now return attributes.snoozeSchedule ? attributes.snoozeSchedule.filter((s) => typeof s.id !== 'undefined') @@ -120,10 +115,7 @@ export function clearUnscheduledSnooze(rule: RuleDoma return rule.snoozeSchedule ? rule.snoozeSchedule.filter((s) => typeof s.id !== 'undefined') : []; } -/** - * @deprecated TODO (http-versioning): Deprecate this once we fix all RawRule types - */ -export function clearScheduledSnoozesAttributesById(attributes: RawRule, ids: string[]) { +export function clearScheduledSnoozesAttributesById(attributes: RuleAttributes, ids: string[]) { return attributes.snoozeSchedule ? attributes.snoozeSchedule.filter((s) => s.id && !ids.includes(s.id)) : []; @@ -136,10 +128,7 @@ export function clearScheduledSnoozesById( return rule.snoozeSchedule ? rule.snoozeSchedule.filter((s) => s.id && !ids.includes(s.id)) : []; } -/** - * @deprecated TODO (http-versioning): Deprecate this once we fix all RawRule types - */ -export function clearCurrentActiveSnoozeAttributes(attributes: RawRule) { +export function clearCurrentActiveSnoozeAttributes(attributes: RuleAttributes) { // First attempt to cancel a simple (unscheduled) snooze const clearedUnscheduledSnoozes = clearUnscheduledSnoozeAttributes(attributes); // Now clear any scheduled snoozes that are currently active and never recur @@ -193,10 +182,7 @@ export function clearCurrentActiveSnooze(rule: RuleDo return clearedSnoozesAndSkippedRecurringSnoozes; } -/** - * @deprecated TODO (http-versioning): Deprecate this once we fix all RawRule types - */ -export function verifySnoozeAttributeScheduleLimit(attributes: Partial) { +export function verifySnoozeAttributeScheduleLimit(attributes: Partial) { const schedules = attributes.snoozeSchedule?.filter((snooze) => snooze.id); if (schedules && schedules.length > 5) { throw Error( diff --git a/x-pack/plugins/alerting/server/rules_client/lib/get_alert_from_raw.ts b/x-pack/plugins/alerting/server/rules_client/lib/get_alert_from_raw.ts index 2b4dbce71f76a..ddf1e40728b28 100644 --- a/x-pack/plugins/alerting/server/rules_client/lib/get_alert_from_raw.ts +++ b/x-pack/plugins/alerting/server/rules_client/lib/get_alert_from_raw.ts @@ -37,6 +37,9 @@ export interface GetAlertFromRawParams { omitGeneratedValues?: boolean; } +/** + * @deprecated in favor of transformRuleAttributesToRuleDomain + */ export function getAlertFromRaw( context: RulesClientContext, id: string, diff --git a/x-pack/plugins/alerting/server/rules_client/lib/get_rule_saved_object.ts b/x-pack/plugins/alerting/server/rules_client/lib/get_rule_saved_object.ts new file mode 100644 index 0000000000000..43e0344e259fd --- /dev/null +++ b/x-pack/plugins/alerting/server/rules_client/lib/get_rule_saved_object.ts @@ -0,0 +1,39 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { SavedObject } from '@kbn/core/server'; +import { withSpan } from '@kbn/apm-utils'; +import { ruleAuditEvent, RuleAuditAction } from '../common/audit_events'; +import { RulesClientContext } from '../types'; +import { getRuleSo } from '../../data/rule'; +import { RuleAttributes } from '../../data/rule/types'; + +interface GetRuleSavedObjectParams { + ruleId: string; +} + +export async function getRuleSavedObject( + context: RulesClientContext, + params: GetRuleSavedObjectParams +): Promise> { + const { ruleId } = params; + + context.auditLogger?.log( + ruleAuditEvent({ + action: RuleAuditAction.GET, + outcome: 'unknown', + savedObject: { type: 'alert', id: ruleId }, + }) + ); + + return await withSpan({ name: 'unsecuredSavedObjectsClient.get', type: 'rules' }, () => + getRuleSo({ + id: ruleId, + savedObjectsClient: context.unsecuredSavedObjectsClient, + }) + ); +} diff --git a/x-pack/plugins/alerting/server/rules_client/lib/index.ts b/x-pack/plugins/alerting/server/rules_client/lib/index.ts index ab1f33df01c10..ede7c3034a7f2 100644 --- a/x-pack/plugins/alerting/server/rules_client/lib/index.ts +++ b/x-pack/plugins/alerting/server/rules_client/lib/index.ts @@ -6,9 +6,13 @@ */ export { createRuleSavedObject } from './create_rule_saved_object'; +export { resolveRuleSavedObject } from './resolve_rule_saved_object'; +export { getRuleSavedObject } from './get_rule_saved_object'; + export { extractReferences } from './extract_references'; export { validateActions } from './validate_actions'; export { updateMeta } from './update_meta'; +export { updateMetaAttributes } from './update_meta_attributes'; export * from './get_alert_from_raw'; export { getAuthorizationFilter } from './get_authorization_filter'; export { checkAuthorizationAndGetTotal } from './check_authorization_and_get_total'; diff --git a/x-pack/plugins/alerting/server/rules_client/lib/resolve_rule_saved_object.ts b/x-pack/plugins/alerting/server/rules_client/lib/resolve_rule_saved_object.ts new file mode 100644 index 0000000000000..101f846ae9ba9 --- /dev/null +++ b/x-pack/plugins/alerting/server/rules_client/lib/resolve_rule_saved_object.ts @@ -0,0 +1,39 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { SavedObjectsResolveResponse } from '@kbn/core/server'; +import { withSpan } from '@kbn/apm-utils'; +import { ruleAuditEvent, RuleAuditAction } from '../common/audit_events'; +import { RulesClientContext } from '../types'; +import { resolveRuleSo } from '../../data/rule'; +import { RuleAttributes } from '../../data/rule/types'; + +interface ResolveRuleSavedObjectParams { + ruleId: string; +} + +export async function resolveRuleSavedObject( + context: RulesClientContext, + params: ResolveRuleSavedObjectParams +): Promise> { + const { ruleId } = params; + + context.auditLogger?.log( + ruleAuditEvent({ + action: RuleAuditAction.RESOLVE, + outcome: 'unknown', + savedObject: { type: 'alert', id: ruleId }, + }) + ); + + return await withSpan({ name: 'unsecuredSavedObjectsClient.resolve', type: 'rules' }, () => + resolveRuleSo({ + id: ruleId, + savedObjectsClient: context.unsecuredSavedObjectsClient, + }) + ); +} diff --git a/x-pack/plugins/alerting/server/rules_client/lib/update_meta.ts b/x-pack/plugins/alerting/server/rules_client/lib/update_meta.ts index 5fbe2b275f077..278a6ac267df5 100644 --- a/x-pack/plugins/alerting/server/rules_client/lib/update_meta.ts +++ b/x-pack/plugins/alerting/server/rules_client/lib/update_meta.ts @@ -8,6 +8,9 @@ import { RawRule } from '../../types'; import { RulesClientContext } from '../types'; +/** + * @deprecated Use updateMetaAttributes instead + */ export function updateMeta>( context: RulesClientContext, alertAttributes: T diff --git a/x-pack/plugins/alerting/server/rules_client/lib/update_meta_attributes.ts b/x-pack/plugins/alerting/server/rules_client/lib/update_meta_attributes.ts new file mode 100644 index 0000000000000..716e0a8beacb9 --- /dev/null +++ b/x-pack/plugins/alerting/server/rules_client/lib/update_meta_attributes.ts @@ -0,0 +1,25 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { RuleAttributes } from '../../data/rule/types'; +import { RulesClientContext } from '../types'; + +export function updateMetaAttributes>( + context: RulesClientContext, + alertAttributes: T +): T { + if (alertAttributes.hasOwnProperty('apiKey') || alertAttributes.hasOwnProperty('apiKeyOwner')) { + return { + ...alertAttributes, + meta: { + ...(alertAttributes.meta ?? {}), + versionApiKeyLastmodified: context.kibanaVersion, + }, + }; + } + return alertAttributes; +} diff --git a/x-pack/plugins/alerting/server/rules_client/methods/mute_all.ts b/x-pack/plugins/alerting/server/rules_client/methods/mute_all.ts index ca5584da706a7..72a693aace7ac 100644 --- a/x-pack/plugins/alerting/server/rules_client/methods/mute_all.ts +++ b/x-pack/plugins/alerting/server/rules_client/methods/mute_all.ts @@ -11,8 +11,9 @@ import { retryIfConflicts } from '../../lib/retry_if_conflicts'; import { partiallyUpdateAlert } from '../../saved_objects'; import { ruleAuditEvent, RuleAuditAction } from '../common/audit_events'; import { RulesClientContext } from '../types'; -import { updateMeta } from '../lib'; +import { updateMetaAttributes } from '../lib'; import { clearUnscheduledSnoozeAttributes } from '../common'; +import { RuleAttributes } from '../../data/rule/types'; export async function muteAll(context: RulesClientContext, { id }: { id: string }): Promise { return await retryIfConflicts( @@ -60,10 +61,10 @@ async function muteAllWithOCC(context: RulesClientContext, { id }: { id: string context.ruleTypeRegistry.ensureRuleTypeEnabled(attributes.alertTypeId); - const updateAttributes = updateMeta(context, { + const updateAttributes = updateMetaAttributes(context, { muteAll: true, mutedInstanceIds: [], - snoozeSchedule: clearUnscheduledSnoozeAttributes(attributes), + snoozeSchedule: clearUnscheduledSnoozeAttributes(attributes as RuleAttributes), updatedBy: await context.getUserName(), updatedAt: new Date().toISOString(), }); diff --git a/x-pack/plugins/alerting/server/rules_client/methods/resolve.ts b/x-pack/plugins/alerting/server/rules_client/methods/resolve.ts deleted file mode 100644 index a663b9aac56d1..0000000000000 --- a/x-pack/plugins/alerting/server/rules_client/methods/resolve.ts +++ /dev/null @@ -1,81 +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 { AlertConsumers } from '@kbn/rule-data-utils'; - -import { RawRule, RuleTypeParams, ResolvedSanitizedRule } from '../../types'; -import { ReadOperations, AlertingAuthorizationEntity } from '../../authorization'; -import { ruleAuditEvent, RuleAuditAction } from '../common/audit_events'; -import { getAlertFromRaw } from '../lib/get_alert_from_raw'; -import { RulesClientContext } from '../types'; -import { formatLegacyActions } from '../lib'; - -export interface ResolveParams { - id: string; - includeLegacyId?: boolean; - includeSnoozeData?: boolean; -} - -export async function resolve( - context: RulesClientContext, - { id, includeLegacyId, includeSnoozeData = false }: ResolveParams -): Promise> { - const { saved_object: result, ...resolveResponse } = - await context.unsecuredSavedObjectsClient.resolve('alert', id); - try { - await context.authorization.ensureAuthorized({ - ruleTypeId: result.attributes.alertTypeId, - consumer: result.attributes.consumer, - operation: ReadOperations.Get, - entity: AlertingAuthorizationEntity.Rule, - }); - } catch (error) { - context.auditLogger?.log( - ruleAuditEvent({ - action: RuleAuditAction.RESOLVE, - savedObject: { type: 'alert', id }, - error, - }) - ); - throw error; - } - context.auditLogger?.log( - ruleAuditEvent({ - action: RuleAuditAction.RESOLVE, - savedObject: { type: 'alert', id }, - }) - ); - - const rule = getAlertFromRaw( - context, - result.id, - result.attributes.alertTypeId, - result.attributes, - result.references, - includeLegacyId, - false, - includeSnoozeData - ); - - // format legacy actions for SIEM rules - if (result.attributes.consumer === AlertConsumers.SIEM) { - const [migratedRule] = await formatLegacyActions([rule], { - savedObjectsClient: context.unsecuredSavedObjectsClient, - logger: context.logger, - }); - - return { - ...migratedRule, - ...resolveResponse, - }; - } - - return { - ...rule, - ...resolveResponse, - }; -} diff --git a/x-pack/plugins/alerting/server/rules_client/methods/unmute_all.ts b/x-pack/plugins/alerting/server/rules_client/methods/unmute_all.ts index e69f09a219700..52403e2d8f70e 100644 --- a/x-pack/plugins/alerting/server/rules_client/methods/unmute_all.ts +++ b/x-pack/plugins/alerting/server/rules_client/methods/unmute_all.ts @@ -11,8 +11,9 @@ import { retryIfConflicts } from '../../lib/retry_if_conflicts'; import { partiallyUpdateAlert } from '../../saved_objects'; import { ruleAuditEvent, RuleAuditAction } from '../common/audit_events'; import { RulesClientContext } from '../types'; -import { updateMeta } from '../lib'; +import { updateMetaAttributes } from '../lib'; import { clearUnscheduledSnoozeAttributes } from '../common'; +import { RuleAttributes } from '../../data/rule/types'; export async function unmuteAll( context: RulesClientContext, @@ -63,10 +64,10 @@ async function unmuteAllWithOCC(context: RulesClientContext, { id }: { id: strin context.ruleTypeRegistry.ensureRuleTypeEnabled(attributes.alertTypeId); - const updateAttributes = updateMeta(context, { + const updateAttributes = updateMetaAttributes(context, { muteAll: false, mutedInstanceIds: [], - snoozeSchedule: clearUnscheduledSnoozeAttributes(attributes), + snoozeSchedule: clearUnscheduledSnoozeAttributes(attributes as RuleAttributes), updatedBy: await context.getUserName(), updatedAt: new Date().toISOString(), }); diff --git a/x-pack/plugins/alerting/server/rules_client/rules_client.ts b/x-pack/plugins/alerting/server/rules_client/rules_client.ts index 12212b772ce71..0a2da42d7e424 100644 --- a/x-pack/plugins/alerting/server/rules_client/rules_client.ts +++ b/x-pack/plugins/alerting/server/rules_client/rules_client.ts @@ -12,8 +12,10 @@ import { parseDuration } from '../../common/parse_duration'; import { RulesClientContext, BulkOptions } from './types'; import { clone, CloneArguments } from './methods/clone'; import { createRule, CreateRuleParams } from '../application/rule/methods/create'; +import { snoozeRule, SnoozeRuleOptions } from '../application/rule/methods/snooze'; +import { unsnoozeRule, UnsnoozeParams } from '../application/rule/methods/unsnooze'; import { get, GetParams } from './methods/get'; -import { resolve, ResolveParams } from './methods/resolve'; +import { resolveRule, ResolveParams } from '../application/rule/methods/resolve'; import { getAlertState, GetAlertStateParams } from './methods/get_alert_state'; import { getAlertSummary, GetAlertSummaryParams } from './methods/get_alert_summary'; import { @@ -54,8 +56,6 @@ import { bulkEnableRules } from './methods/bulk_enable'; import { updateApiKey } from './methods/update_api_key'; import { enable } from './methods/enable'; import { disable } from './methods/disable'; -import { snooze, SnoozeParams } from './methods/snooze'; -import { unsnooze, UnsnoozeParams } from './methods/unsnooze'; import { clearExpiredSnoozes } from './methods/clear_expired_snoozes'; import { muteInstance } from '../application/rule/methods/mute_alert/mute_instance'; import { muteAll } from './methods/mute_all'; @@ -130,7 +130,7 @@ export class RulesClient { public get = (params: GetParams) => get(this.context, params); public resolve = (params: ResolveParams) => - resolve(this.context, params); + resolveRule(this.context, params); public update = (params: UpdateOptions) => update(this.context, params); @@ -162,8 +162,8 @@ export class RulesClient { public enable = (options: { id: string }) => enable(this.context, options); public disable = (options: { id: string }) => disable(this.context, options); - public snooze = (options: SnoozeParams) => snooze(this.context, options); - public unsnooze = (options: UnsnoozeParams) => unsnooze(this.context, options); + public snooze = (options: SnoozeRuleOptions) => snoozeRule(this.context, options); + public unsnooze = (options: UnsnoozeParams) => unsnoozeRule(this.context, options); public clearExpiredSnoozes = (options: { rule: Pick, 'id' | 'snoozeSchedule'>; diff --git a/x-pack/plugins/alerting/server/rules_client/tests/resolve.test.ts b/x-pack/plugins/alerting/server/rules_client/tests/resolve.test.ts index 0cf9e792cc1bf..70c6388c41ff4 100644 --- a/x-pack/plugins/alerting/server/rules_client/tests/resolve.test.ts +++ b/x-pack/plugins/alerting/server/rules_client/tests/resolve.test.ts @@ -96,6 +96,11 @@ describe('resolve()', () => { }, ], notifyWhen: 'onActiveAlert', + executionStatus: { + status: 'ok', + last_execution_date: new Date().toISOString(), + last_duration: 10, + }, }, references: [ { @@ -123,82 +128,11 @@ describe('resolve()', () => { "alertTypeId": "123", "alias_target_id": "2", "createdAt": 2019-02-12T21:01:22.479Z, - "id": "1", - "notifyWhen": "onActiveAlert", - "outcome": "aliasMatch", - "params": Object { - "bar": true, + "executionStatus": Object { + "lastExecutionDate": 2019-02-12T21:01:22.479Z, + "status": "ok", }, - "schedule": Object { - "interval": "10s", - }, - "snoozeSchedule": Array [], - "updatedAt": 2019-02-12T21:01:22.479Z, - } - `); - expect(unsecuredSavedObjectsClient.resolve).toHaveBeenCalledTimes(1); - expect(unsecuredSavedObjectsClient.resolve.mock.calls[0]).toMatchInlineSnapshot(` - Array [ - "alert", - "1", - ] - `); - }); - - test('calls saved objects client with id and includeLegacyId params', async () => { - const rulesClient = new RulesClient(rulesClientParams); - unsecuredSavedObjectsClient.resolve.mockResolvedValueOnce({ - saved_object: { - id: '1', - type: 'alert', - attributes: { - legacyId: 'some-legacy-id', - alertTypeId: '123', - schedule: { interval: '10s' }, - params: { - bar: true, - }, - createdAt: new Date().toISOString(), - updatedAt: new Date().toISOString(), - actions: [ - { - group: 'default', - actionRef: 'action_0', - params: { - foo: true, - }, - }, - ], - notifyWhen: 'onActiveAlert', - }, - references: [ - { - name: 'action_0', - type: 'action', - id: '1', - }, - ], - }, - outcome: 'aliasMatch', - alias_target_id: '2', - }); - const result = await rulesClient.resolve({ id: '1', includeLegacyId: true }); - expect(result).toMatchInlineSnapshot(` - Object { - "actions": Array [ - Object { - "group": "default", - "id": "1", - "params": Object { - "foo": true, - }, - }, - ], - "alertTypeId": "123", - "alias_target_id": "2", - "createdAt": 2019-02-12T21:01:22.479Z, "id": "1", - "legacyId": "some-legacy-id", "notifyWhen": "onActiveAlert", "outcome": "aliasMatch", "params": Object { @@ -213,11 +147,12 @@ describe('resolve()', () => { `); expect(unsecuredSavedObjectsClient.resolve).toHaveBeenCalledTimes(1); expect(unsecuredSavedObjectsClient.resolve.mock.calls[0]).toMatchInlineSnapshot(` - Array [ - "alert", - "1", - ] - `); + Array [ + "alert", + "1", + undefined, + ] + `); }); test('calls saved objects client with id and includeSnoozeData params', async () => { @@ -256,6 +191,11 @@ describe('resolve()', () => { }, ], notifyWhen: 'onActiveAlert', + executionStatus: { + status: 'ok', + last_execution_date: new Date().toISOString(), + last_duration: 10, + }, }, references: [ { @@ -323,6 +263,11 @@ describe('resolve()', () => { }, ], notifyWhen: 'onActiveAlert', + executionStatus: { + status: 'ok', + last_execution_date: new Date().toISOString(), + last_duration: 10, + }, }, references: [ { @@ -363,6 +308,10 @@ describe('resolve()', () => { "alertTypeId": "123", "alias_target_id": "2", "createdAt": 2019-02-12T21:01:22.479Z, + "executionStatus": Object { + "lastExecutionDate": 2019-02-12T21:01:22.479Z, + "status": "ok", + }, "id": "1", "notifyWhen": "onActiveAlert", "outcome": "aliasMatch", @@ -400,6 +349,11 @@ describe('resolve()', () => { }, }, ], + executionStatus: { + status: 'ok', + last_execution_date: new Date().toISOString(), + last_duration: 10, + }, }, references: [], }, @@ -505,6 +459,11 @@ describe('resolve()', () => { }, }, ], + executionStatus: { + status: 'ok', + last_execution_date: new Date().toISOString(), + last_duration: 10, + }, }, references: [ { @@ -563,6 +522,11 @@ describe('resolve()', () => { bar: true, }, actions: [], + executionStatus: { + status: 'ok', + last_execution_date: new Date().toISOString(), + last_duration: 10, + }, }, references: [], }, @@ -633,6 +597,11 @@ describe('resolve()', () => { }, ], notifyWhen: 'onActiveAlert', + executionStatus: { + status: 'ok', + last_execution_date: new Date().toISOString(), + last_duration: 10, + }, }, references: [ { diff --git a/x-pack/plugins/alerting/server/rules_settings_feature.test.ts b/x-pack/plugins/alerting/server/rules_settings_feature.test.ts new file mode 100644 index 0000000000000..cdf4f034bc528 --- /dev/null +++ b/x-pack/plugins/alerting/server/rules_settings_feature.test.ts @@ -0,0 +1,194 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { getRulesSettingsFeature } from './rules_settings_feature'; + +test('returns rule settings feature with query delay subfeature if serverless', async () => { + expect(getRulesSettingsFeature(true)).toEqual({ + app: [], + category: { + euiIconType: 'managementApp', + id: 'management', + label: 'Management', + order: 5000, + }, + id: 'rulesSettings', + management: { + insightsAndAlerting: ['triggersActions'], + }, + name: 'Rules Settings', + privileges: { + all: { + api: [], + app: [], + management: { + insightsAndAlerting: ['triggersActions'], + }, + savedObject: { + all: ['rules-settings'], + read: [], + }, + ui: ['show', 'save'], + }, + read: { + api: [], + app: [], + management: { + insightsAndAlerting: ['triggersActions'], + }, + savedObject: { + all: [], + read: ['rules-settings'], + }, + ui: ['show'], + }, + }, + subFeatures: [ + { + name: 'Flapping detection', + privilegeGroups: [ + { + groupType: 'mutually_exclusive', + privileges: [ + { + api: ['read-flapping-settings', 'write-flapping-settings'], + id: 'allFlappingSettings', + includeIn: 'all', + name: 'All', + savedObject: { + all: ['rules-settings'], + read: [], + }, + ui: ['writeFlappingSettingsUI', 'readFlappingSettingsUI'], + }, + { + api: ['read-flapping-settings'], + id: 'readFlappingSettings', + includeIn: 'read', + name: 'Read', + savedObject: { + all: [], + read: ['rules-settings'], + }, + ui: ['readFlappingSettingsUI'], + }, + ], + }, + ], + }, + { + name: 'Query delay', + privilegeGroups: [ + { + groupType: 'mutually_exclusive', + privileges: [ + { + api: ['read-query-delay-settings', 'write-query-delay-settings'], + id: 'allQueryDelaySettings', + includeIn: 'all', + name: 'All', + savedObject: { + all: ['rules-settings'], + read: [], + }, + ui: ['writeQueryDelaySettingsUI', 'readQueryDelaySettingsUI'], + }, + { + api: ['read-query-delay-settings'], + id: 'readQueryDelaySettings', + includeIn: 'read', + name: 'Read', + savedObject: { + all: [], + read: ['rules-settings'], + }, + ui: ['readQueryDelaySettingsUI'], + }, + ], + }, + ], + }, + ], + }); +}); + +test('returns rule settings feature without query delay subfeature if not serverless', async () => { + expect(getRulesSettingsFeature(false)).toEqual({ + app: [], + category: { + euiIconType: 'managementApp', + id: 'management', + label: 'Management', + order: 5000, + }, + id: 'rulesSettings', + management: { + insightsAndAlerting: ['triggersActions'], + }, + name: 'Rules Settings', + privileges: { + all: { + api: [], + app: [], + management: { + insightsAndAlerting: ['triggersActions'], + }, + savedObject: { + all: ['rules-settings'], + read: [], + }, + ui: ['show', 'save'], + }, + read: { + api: [], + app: [], + management: { + insightsAndAlerting: ['triggersActions'], + }, + savedObject: { + all: [], + read: ['rules-settings'], + }, + ui: ['show'], + }, + }, + subFeatures: [ + { + name: 'Flapping detection', + privilegeGroups: [ + { + groupType: 'mutually_exclusive', + privileges: [ + { + api: ['read-flapping-settings', 'write-flapping-settings'], + id: 'allFlappingSettings', + includeIn: 'all', + name: 'All', + savedObject: { + all: ['rules-settings'], + read: [], + }, + ui: ['writeFlappingSettingsUI', 'readFlappingSettingsUI'], + }, + { + api: ['read-flapping-settings'], + id: 'readFlappingSettings', + includeIn: 'read', + name: 'Read', + savedObject: { + all: [], + read: ['rules-settings'], + }, + ui: ['readFlappingSettingsUI'], + }, + ], + }, + ], + }, + ], + }); +}); diff --git a/x-pack/plugins/alerting/server/rules_settings_feature.ts b/x-pack/plugins/alerting/server/rules_settings_feature.ts index 2d39b9290a0cd..ed346121ecde8 100644 --- a/x-pack/plugins/alerting/server/rules_settings_feature.ts +++ b/x-pack/plugins/alerting/server/rules_settings_feature.ts @@ -18,78 +18,86 @@ import { READ_QUERY_DELAY_SETTINGS_SUB_FEATURE_ID, } from '../common'; -export const rulesSettingsFeature: KibanaFeatureConfig = { - id: RULES_SETTINGS_FEATURE_ID, - name: i18n.translate('xpack.alerting.feature.rulesSettingsFeatureName', { - defaultMessage: 'Rules Settings', - }), - category: DEFAULT_APP_CATEGORIES.management, - app: [], - management: { - insightsAndAlerting: ['triggersActions'], - }, - privileges: { - all: { - app: [], - api: [], - management: { - insightsAndAlerting: ['triggersActions'], - }, - savedObject: { - all: [RULES_SETTINGS_SAVED_OBJECT_TYPE], - read: [], - }, - ui: ['show', 'save'], +export function getRulesSettingsFeature(isServerless: boolean): KibanaFeatureConfig { + const settings = { + id: RULES_SETTINGS_FEATURE_ID, + name: i18n.translate('xpack.alerting.feature.rulesSettingsFeatureName', { + defaultMessage: 'Rules Settings', + }), + category: DEFAULT_APP_CATEGORIES.management, + app: [], + management: { + insightsAndAlerting: ['triggersActions'], }, - read: { - app: [], - api: [], - management: { - insightsAndAlerting: ['triggersActions'], + privileges: { + all: { + app: [], + api: [], + management: { + insightsAndAlerting: ['triggersActions'], + }, + savedObject: { + all: [RULES_SETTINGS_SAVED_OBJECT_TYPE], + read: [], + }, + ui: ['show', 'save'], }, - savedObject: { - all: [], - read: [RULES_SETTINGS_SAVED_OBJECT_TYPE], + read: { + app: [], + api: [], + management: { + insightsAndAlerting: ['triggersActions'], + }, + savedObject: { + all: [], + read: [RULES_SETTINGS_SAVED_OBJECT_TYPE], + }, + ui: ['show'], }, - ui: ['show'], }, - }, - subFeatures: [ - { - name: i18n.translate('xpack.alerting.feature.flappingSettingsSubFeatureName', { - defaultMessage: 'Flapping detection', - }), - privilegeGroups: [ - { - groupType: 'mutually_exclusive', - privileges: [ - { - api: [API_PRIVILEGES.READ_FLAPPING_SETTINGS, API_PRIVILEGES.WRITE_FLAPPING_SETTINGS], - name: 'All', - id: ALL_FLAPPING_SETTINGS_SUB_FEATURE_ID, - includeIn: 'all', - savedObject: { - all: [RULES_SETTINGS_SAVED_OBJECT_TYPE], - read: [], + subFeatures: [ + { + name: i18n.translate('xpack.alerting.feature.flappingSettingsSubFeatureName', { + defaultMessage: 'Flapping detection', + }), + privilegeGroups: [ + { + groupType: 'mutually_exclusive', + privileges: [ + { + api: [ + API_PRIVILEGES.READ_FLAPPING_SETTINGS, + API_PRIVILEGES.WRITE_FLAPPING_SETTINGS, + ], + name: 'All', + id: ALL_FLAPPING_SETTINGS_SUB_FEATURE_ID, + includeIn: 'all', + savedObject: { + all: [RULES_SETTINGS_SAVED_OBJECT_TYPE], + read: [], + }, + ui: ['writeFlappingSettingsUI', 'readFlappingSettingsUI'], }, - ui: ['writeFlappingSettingsUI', 'readFlappingSettingsUI'], - }, - { - api: [API_PRIVILEGES.READ_FLAPPING_SETTINGS], - name: 'Read', - id: READ_FLAPPING_SETTINGS_SUB_FEATURE_ID, - includeIn: 'read', - savedObject: { - all: [], - read: [RULES_SETTINGS_SAVED_OBJECT_TYPE], + { + api: [API_PRIVILEGES.READ_FLAPPING_SETTINGS], + name: 'Read', + id: READ_FLAPPING_SETTINGS_SUB_FEATURE_ID, + includeIn: 'read', + savedObject: { + all: [], + read: [RULES_SETTINGS_SAVED_OBJECT_TYPE], + }, + ui: ['readFlappingSettingsUI'], }, - ui: ['readFlappingSettingsUI'], - }, - ], - }, - ], - }, - { + ], + }, + ], + }, + ], + }; + + if (isServerless) { + settings.subFeatures.push({ name: i18n.translate('xpack.alerting.feature.queryDelaySettingsSubFeatureName', { defaultMessage: 'Query delay', }), @@ -125,6 +133,8 @@ export const rulesSettingsFeature: KibanaFeatureConfig = { ], }, ], - }, - ], -}; + }); + } + + return settings as KibanaFeatureConfig; +} diff --git a/x-pack/plugins/alerting/server/saved_objects/is_rule_exportable.test.ts b/x-pack/plugins/alerting/server/saved_objects/is_rule_exportable.test.ts index 6a799370b546f..442dcf0a9469d 100644 --- a/x-pack/plugins/alerting/server/saved_objects/is_rule_exportable.test.ts +++ b/x-pack/plugins/alerting/server/saved_objects/is_rule_exportable.test.ts @@ -15,6 +15,7 @@ import { licensingMock } from '@kbn/licensing-plugin/server/mocks'; import { isRuleExportable } from './is_rule_exportable'; import { inMemoryMetricsMock } from '../monitoring/in_memory_metrics.mock'; import { loggingSystemMock } from '@kbn/core/server/mocks'; +import { AlertingConfig } from '../config'; let ruleTypeRegistryParams: ConstructorOptions; let logger: MockedLogger; @@ -27,6 +28,7 @@ beforeEach(() => { mockedLicenseState = licenseStateMock.create(); logger = loggerMock.create(); ruleTypeRegistryParams = { + config: {} as AlertingConfig, logger: loggingSystemMock.create().get(), taskManager, alertsService: null, diff --git a/x-pack/plugins/alerting/server/types.ts b/x-pack/plugins/alerting/server/types.ts index 26eed5f254bc9..d5e0b331833d5 100644 --- a/x-pack/plugins/alerting/server/types.ts +++ b/x-pack/plugins/alerting/server/types.ts @@ -442,6 +442,9 @@ export interface RawRuleExecutionStatus extends SavedObjectAttributes { }; } +/** + * @deprecated in favor of Rule + */ export interface RawRule extends SavedObjectAttributes { enabled: boolean; name: string; diff --git a/x-pack/plugins/alerting/tsconfig.json b/x-pack/plugins/alerting/tsconfig.json index 987ad98b927cf..9eb0b05f7884c 100644 --- a/x-pack/plugins/alerting/tsconfig.json +++ b/x-pack/plugins/alerting/tsconfig.json @@ -59,7 +59,8 @@ "@kbn/serverless", "@kbn/core-http-router-server-mocks", "@kbn/core-elasticsearch-server", - "@kbn/core-application-common" + "@kbn/core-application-common", + "@kbn/core-saved-objects-api-server" ], "exclude": ["target/**/*"] } diff --git a/x-pack/plugins/apm/common/rules/apm_rule_types.ts b/x-pack/plugins/apm/common/rules/apm_rule_types.ts index b18ea1f0c49ce..39659f146db8b 100644 --- a/x-pack/plugins/apm/common/rules/apm_rule_types.ts +++ b/x-pack/plugins/apm/common/rules/apm_rule_types.ts @@ -16,6 +16,7 @@ import type { ActionGroup } from '@kbn/alerting-plugin/common'; import { formatDurationFromTimeUnitChar } from '@kbn/observability-plugin/common'; import { ML_ANOMALY_SEVERITY } from '@kbn/ml-anomaly-utils/anomaly_severity'; import { ML_ANOMALY_THRESHOLD } from '@kbn/ml-anomaly-utils/anomaly_threshold'; +import { ApmRuleType } from '@kbn/rule-data-utils'; import { ERROR_GROUP_ID, ERROR_GROUP_NAME, @@ -28,13 +29,6 @@ import { getEnvironmentLabel } from '../environment_filter_values'; export const APM_SERVER_FEATURE_ID = 'apm'; -export enum ApmRuleType { - ErrorCount = 'apm.error_rate', // ErrorRate was renamed to ErrorCount but the key is kept as `error_rate` for backwards-compat. - TransactionErrorRate = 'apm.transaction_error_rate', - TransactionDuration = 'apm.transaction_duration', - Anomaly = 'apm.anomaly', -} - export enum AggregationType { Avg = 'avg', P95 = '95th', diff --git a/x-pack/plugins/apm/common/rules/get_all_groupby_fields.ts b/x-pack/plugins/apm/common/rules/get_all_groupby_fields.ts index 696a30df3a78c..055fb1984defe 100644 --- a/x-pack/plugins/apm/common/rules/get_all_groupby_fields.ts +++ b/x-pack/plugins/apm/common/rules/get_all_groupby_fields.ts @@ -6,7 +6,7 @@ */ import { union } from 'lodash'; -import { ApmRuleType } from './apm_rule_types'; +import { ApmRuleType } from '@kbn/rule-data-utils'; import { SERVICE_ENVIRONMENT, SERVICE_NAME, diff --git a/x-pack/plugins/apm/common/rules/schema.ts b/x-pack/plugins/apm/common/rules/schema.ts index 9041e4c0c8e5a..c38fe85561696 100644 --- a/x-pack/plugins/apm/common/rules/schema.ts +++ b/x-pack/plugins/apm/common/rules/schema.ts @@ -7,7 +7,8 @@ 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'; +import { ApmRuleType } from '@kbn/rule-data-utils'; +import { AggregationType } from './apm_rule_types'; export const searchConfigurationSchema = schema.object({ query: schema.object({ diff --git a/x-pack/plugins/apm/kibana.jsonc b/x-pack/plugins/apm/kibana.jsonc index a72209f18fa52..61ba6be743370 100644 --- a/x-pack/plugins/apm/kibana.jsonc +++ b/x-pack/plugins/apm/kibana.jsonc @@ -41,7 +41,6 @@ "discover", "fleet", "fieldFormats", - "infra", "home", "ml", "security", diff --git a/x-pack/plugins/apm/public/application/index.tsx b/x-pack/plugins/apm/public/application/index.tsx index 52020aed93453..9e62f0257f489 100644 --- a/x-pack/plugins/apm/public/application/index.tsx +++ b/x-pack/plugins/apm/public/application/index.tsx @@ -49,7 +49,6 @@ export const renderApp = ({ plugins: pluginsSetup, data: pluginsStart.data, inspector: pluginsStart.inspector, - infra: pluginsStart.infra, observability: pluginsStart.observability, observabilityShared: pluginsStart.observabilityShared, observabilityRuleTypeRegistry, diff --git a/x-pack/plugins/apm/public/components/alerting/rule_types/register_apm_rule_types.ts b/x-pack/plugins/apm/public/components/alerting/rule_types/register_apm_rule_types.ts index e8f2c6185ebd6..d3ddffc131e14 100644 --- a/x-pack/plugins/apm/public/components/alerting/rule_types/register_apm_rule_types.ts +++ b/x-pack/plugins/apm/public/components/alerting/rule_types/register_apm_rule_types.ts @@ -7,13 +7,12 @@ import { i18n } from '@kbn/i18n'; import { lazy } from 'react'; -import { ALERT_REASON } from '@kbn/rule-data-utils'; +import { ALERT_REASON, ApmRuleType } from '@kbn/rule-data-utils'; import type { ObservabilityRuleTypeRegistry } from '@kbn/observability-plugin/public'; import { getAlertUrlErrorCount, getAlertUrlTransaction, } from '../../../../common/utils/formatters'; -import { ApmRuleType } from '../../../../common/rules/apm_rule_types'; import { anomalyMessage, errorCountMessage, diff --git a/x-pack/plugins/apm/public/components/alerting/ui_components/alerting_flyout/index.tsx b/x-pack/plugins/apm/public/components/alerting/ui_components/alerting_flyout/index.tsx index 0180b2f940a58..95820bf8f84d4 100644 --- a/x-pack/plugins/apm/public/components/alerting/ui_components/alerting_flyout/index.tsx +++ b/x-pack/plugins/apm/public/components/alerting/ui_components/alerting_flyout/index.tsx @@ -7,10 +7,8 @@ import React, { useCallback, useMemo } from 'react'; import { useKibana } from '@kbn/kibana-react-plugin/public'; -import { - ApmRuleType, - APM_SERVER_FEATURE_ID, -} from '../../../../../common/rules/apm_rule_types'; +import { ApmRuleType } from '@kbn/rule-data-utils'; +import { APM_SERVER_FEATURE_ID } from '../../../../../common/rules/apm_rule_types'; import { getInitialAlertValues } from '../../utils/get_initial_alert_values'; import { ApmPluginStartDeps } from '../../../../plugin'; import { useServiceName } from '../../../../hooks/use_service_name'; @@ -70,6 +68,7 @@ export function AlertingFlyout(props: Props) { start, end, } as AlertMetadata, + useRuleProducer: true, }), /* eslint-disable-next-line react-hooks/exhaustive-deps */ [ diff --git a/x-pack/plugins/apm/public/components/alerting/utils/get_initial_alert_values.test.ts b/x-pack/plugins/apm/public/components/alerting/utils/get_initial_alert_values.test.ts index e590e66c2c7ee..c82e36f0cd935 100644 --- a/x-pack/plugins/apm/public/components/alerting/utils/get_initial_alert_values.test.ts +++ b/x-pack/plugins/apm/public/components/alerting/utils/get_initial_alert_values.test.ts @@ -6,10 +6,8 @@ */ import { getInitialAlertValues } from './get_initial_alert_values'; -import { - ApmRuleType, - RULE_TYPES_CONFIG, -} from '../../../../common/rules/apm_rule_types'; +import { RULE_TYPES_CONFIG } from '../../../../common/rules/apm_rule_types'; +import { ApmRuleType } from '@kbn/rule-data-utils'; test('handles null rule type and undefined service name', () => { expect(getInitialAlertValues(null, undefined)).toEqual({ tags: ['apm'] }); diff --git a/x-pack/plugins/apm/public/components/alerting/utils/get_initial_alert_values.ts b/x-pack/plugins/apm/public/components/alerting/utils/get_initial_alert_values.ts index 452a4561f34e1..4a5e53f436e1a 100644 --- a/x-pack/plugins/apm/public/components/alerting/utils/get_initial_alert_values.ts +++ b/x-pack/plugins/apm/public/components/alerting/utils/get_initial_alert_values.ts @@ -5,10 +5,8 @@ * 2.0. */ -import { - ApmRuleType, - RULE_TYPES_CONFIG, -} from '../../../../common/rules/apm_rule_types'; +import { ApmRuleType } from '@kbn/rule-data-utils'; +import { RULE_TYPES_CONFIG } from '../../../../common/rules/apm_rule_types'; export function getInitialAlertValues( ruleType: ApmRuleType | null, diff --git a/x-pack/plugins/apm/public/components/app/alerts_overview/index.tsx b/x-pack/plugins/apm/public/components/app/alerts_overview/index.tsx index 759e878ad4cab..dbf2d94b20699 100644 --- a/x-pack/plugins/apm/public/components/app/alerts_overview/index.tsx +++ b/x-pack/plugins/apm/public/components/app/alerts_overview/index.tsx @@ -110,7 +110,7 @@ export function AlertsOverview() { } id={'service-overview-alerts'} configurationId={AlertConsumers.OBSERVABILITY} - featureIds={[AlertConsumers.APM]} + featureIds={[AlertConsumers.APM, AlertConsumers.OBSERVABILITY]} query={esQuery} showAlertStatusWithFlapping /> diff --git a/x-pack/plugins/apm/public/components/app/infra_overview/infra_tabs/use_tabs.test.tsx b/x-pack/plugins/apm/public/components/app/infra_overview/infra_tabs/use_tabs.test.tsx index d62aa7d0473dc..245d4e90631a1 100644 --- a/x-pack/plugins/apm/public/components/app/infra_overview/infra_tabs/use_tabs.test.tsx +++ b/x-pack/plugins/apm/public/components/app/infra_overview/infra_tabs/use_tabs.test.tsx @@ -12,7 +12,7 @@ import { CoreStart } from '@kbn/core/public'; import { shallow } from 'enzyme'; const KibanaReactContext = createKibanaReactContext({ - infra: { + metricsDataAccess: { HostMetricsTable: () => 'Host metrics table', ContainerMetricsTable: () => 'Container metrics table', PodMetricsTable: () => 'Pods metrics table', diff --git a/x-pack/plugins/apm/public/components/app/infra_overview/infra_tabs/use_tabs.tsx b/x-pack/plugins/apm/public/components/app/infra_overview/infra_tabs/use_tabs.tsx index d9a802e2c78b5..57fea256308d2 100644 --- a/x-pack/plugins/apm/public/components/app/infra_overview/infra_tabs/use_tabs.tsx +++ b/x-pack/plugins/apm/public/components/app/infra_overview/infra_tabs/use_tabs.tsx @@ -42,10 +42,10 @@ export function useTabs({ end: string; }) { const { services } = useKibana(); - const { infra } = services; - const HostMetricsTable = infra?.HostMetricsTable; - const ContainerMetricsTable = infra?.ContainerMetricsTable; - const PodMetricsTable = infra?.PodMetricsTable; + const { metricsDataAccess } = services; + const HostMetricsTable = metricsDataAccess?.HostMetricsTable; + const ContainerMetricsTable = metricsDataAccess?.ContainerMetricsTable; + const PodMetricsTable = metricsDataAccess?.PodMetricsTable; const timerange = useMemo( () => ({ @@ -91,7 +91,10 @@ export function useTabs({ <> {ContainerMetricsTable && - ContainerMetricsTable({ timerange, filterClauseDsl: containersFilter })} + ContainerMetricsTable({ + timerange, + filterClauseDsl: containersFilter, + })} ); @@ -99,7 +102,10 @@ export function useTabs({ <> {PodMetricsTable && - PodMetricsTable({ timerange, filterClauseDsl: podsFilter })} + PodMetricsTable({ + timerange, + filterClauseDsl: podsFilter, + })} ); @@ -107,7 +113,10 @@ export function useTabs({ <> {HostMetricsTable && - HostMetricsTable({ timerange, filterClauseDsl: hostsFilter })} + HostMetricsTable({ + timerange, + filterClauseDsl: hostsFilter, + })} ); diff --git a/x-pack/plugins/apm/public/components/app/service_overview/service_overview_instances_table/instance_actions_menu/index.tsx b/x-pack/plugins/apm/public/components/app/service_overview/service_overview_instances_table/instance_actions_menu/index.tsx index b6d51aec3268e..450c5ec061971 100644 --- a/x-pack/plugins/apm/public/components/app/service_overview/service_overview_instances_table/instance_actions_menu/index.tsx +++ b/x-pack/plugins/apm/public/components/app/service_overview/service_overview_instances_table/instance_actions_menu/index.tsx @@ -19,6 +19,10 @@ import { AllDatasetsLocatorParams, ALL_DATASETS_LOCATOR_ID, } from '@kbn/deeplinks-observability/locators'; +import { + NODE_LOGS_LOCATOR_ID, + NodeLogsLocatorParams, +} from '@kbn/logs-shared-plugin/common'; import { isJavaAgentName } from '../../../../../../common/agent_name'; import { SERVICE_NODE_NAME } from '../../../../../../common/es_fields/apm'; import { useApmPluginContext } from '../../../../../context/apm_plugin/use_apm_plugin_context'; @@ -44,7 +48,7 @@ export function InstanceActionsMenu({ kuery, onClose, }: Props) { - const { core, infra, share } = useApmPluginContext(); + const { core, share } = useApmPluginContext(); const { data, status } = useInstanceDetailsFetcher({ serviceName, serviceNodeName, @@ -59,6 +63,8 @@ export function InstanceActionsMenu({ const allDatasetsLocator = share.url.locators.get( ALL_DATASETS_LOCATOR_ID )!; + const nodeLogsLocator = + share.url.locators.get(NODE_LOGS_LOCATOR_ID)!; if (isPending(status)) { return ( @@ -97,8 +103,8 @@ export function InstanceActionsMenu({ basePath: core.http.basePath, onFilterByInstanceClick: handleFilterByInstanceClick, metricsHref, - infraLocators: infra?.locators, allDatasetsLocator, + nodeLogsLocator, }); return ( diff --git a/x-pack/plugins/apm/public/components/app/service_overview/service_overview_instances_table/instance_actions_menu/menu_sections.ts b/x-pack/plugins/apm/public/components/app/service_overview/service_overview_instances_table/instance_actions_menu/menu_sections.ts index 4188f6e7fa106..8401cc6bbc744 100644 --- a/x-pack/plugins/apm/public/components/app/service_overview/service_overview_instances_table/instance_actions_menu/menu_sections.ts +++ b/x-pack/plugins/apm/public/components/app/service_overview/service_overview_instances_table/instance_actions_menu/menu_sections.ts @@ -8,9 +8,9 @@ import { i18n } from '@kbn/i18n'; import { IBasePath } from '@kbn/core/public'; import moment from 'moment'; -import type { InfraLocators } from '@kbn/infra-plugin/common/locators'; import type { LocatorPublic } from '@kbn/share-plugin/public'; import { AllDatasetsLocatorParams } from '@kbn/deeplinks-observability/locators'; +import { NodeLogsLocatorParams } from '@kbn/logs-shared-plugin/common'; import { getNodeLogsHref } from '../../../../shared/links/observability_logs_link'; import { APIReturnType } from '../../../../../services/rest/create_call_apm_api'; import { getInfraHref } from '../../../../shared/links/infra_link'; @@ -41,15 +41,15 @@ export function getMenuSections({ basePath, onFilterByInstanceClick, metricsHref, - infraLocators, allDatasetsLocator, + nodeLogsLocator, }: { instanceDetails: InstaceDetails; basePath: IBasePath; onFilterByInstanceClick: () => void; metricsHref: string; - infraLocators?: InfraLocators; allDatasetsLocator: LocatorPublic; + nodeLogsLocator: LocatorPublic; }) { const podId = instanceDetails.kubernetes?.pod?.uid; const containerId = instanceDetails.container?.id; @@ -57,21 +57,20 @@ export function getMenuSections({ ? new Date(instanceDetails['@timestamp']).valueOf() : undefined; const infraMetricsQuery = getInfraMetricsQuery(instanceDetails['@timestamp']); - const infraNodeLocator = infraLocators?.nodeLogsLocator; const podLogsHref = getNodeLogsHref( 'pod', podId!, time, allDatasetsLocator, - infraNodeLocator + nodeLogsLocator ); const containerLogsHref = getNodeLogsHref( 'container', containerId!, time, allDatasetsLocator, - infraNodeLocator + nodeLogsLocator ); const podActions: Action[] = [ @@ -96,7 +95,7 @@ export function getMenuSections({ path: `/link-to/pod-detail/${podId}`, query: infraMetricsQuery, }), - condition: !!podId && !!infraLocators, + condition: !!podId, }, ]; @@ -122,7 +121,7 @@ export function getMenuSections({ path: `/link-to/container-detail/${containerId}`, query: infraMetricsQuery, }), - condition: !!containerId && !!infraLocators, + condition: !!containerId, }, ]; diff --git a/x-pack/plugins/apm/public/components/app/settings/agent_explorer/agent_instances/agent_instances_details/index.tsx b/x-pack/plugins/apm/public/components/app/settings/agent_explorer/agent_instances/agent_instances_details/index.tsx index 49dd43cc5c3fe..0f3c8284b9a13 100644 --- a/x-pack/plugins/apm/public/components/app/settings/agent_explorer/agent_instances/agent_instances_details/index.tsx +++ b/x-pack/plugins/apm/public/components/app/settings/agent_explorer/agent_instances/agent_instances_details/index.tsx @@ -15,6 +15,7 @@ import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; import React from 'react'; import { ValuesType } from 'utility-types'; +import { MetricOverviewLink } from '../../../../../shared/links/apm/metric_overview_link'; import { AgentExplorerFieldName } from '../../../../../../../common/agent_explorer'; import { isOpenTelemetryAgentName } from '../../../../../../../common/agent_name'; import { @@ -26,7 +27,6 @@ import { APIReturnType } from '../../../../../../services/rest/create_call_apm_a import { unit } from '../../../../../../utils/style'; import { EnvironmentBadge } from '../../../../../shared/environment_badge'; import { ItemsBadge } from '../../../../../shared/item_badge'; -import { ServiceNodeMetricOverviewLink } from '../../../../../shared/links/apm/service_node_metric_overview_link'; import { PopoverTooltip } from '../../../../../shared/popover_tooltip'; import { TimestampTooltip } from '../../../../../shared/timestamp_tooltip'; import { TruncateWithTooltip } from '../../../../../shared/truncate_with_tooltip'; @@ -108,12 +108,15 @@ export function getInstanceColumns( content={ <> {serviceNode ? ( - ({ + ...query, + kuery: `service.node.name:"${displayedName}"`, + })} > - {displayedName} - + {displayedName} + ) : ( {displayedName} )} diff --git a/x-pack/plugins/apm/public/components/routing/app_root/apm_header_action_menu/alerting_popover_flyout.tsx b/x-pack/plugins/apm/public/components/routing/app_root/apm_header_action_menu/alerting_popover_flyout.tsx index 2a6514a9da7c9..5b8fc78c91eba 100644 --- a/x-pack/plugins/apm/public/components/routing/app_root/apm_header_action_menu/alerting_popover_flyout.tsx +++ b/x-pack/plugins/apm/public/components/routing/app_root/apm_header_action_menu/alerting_popover_flyout.tsx @@ -13,7 +13,7 @@ import { } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import React, { useState } from 'react'; -import { ApmRuleType } from '../../../../../common/rules/apm_rule_types'; +import { ApmRuleType } from '@kbn/rule-data-utils'; import { AlertingFlyout } from '../../../alerting/ui_components/alerting_flyout'; import { useApmPluginContext } from '../../../../context/apm_plugin/use_apm_plugin_context'; diff --git a/x-pack/plugins/apm/public/components/shared/links/infra_link.tsx b/x-pack/plugins/apm/public/components/shared/links/infra_link.tsx index fcc3f2ce9d728..b98652b710020 100644 --- a/x-pack/plugins/apm/public/components/shared/links/infra_link.tsx +++ b/x-pack/plugins/apm/public/components/shared/links/infra_link.tsx @@ -9,7 +9,7 @@ import { EuiLink, EuiLinkAnchorProps } from '@elastic/eui'; import { IBasePath } from '@kbn/core/public'; import React from 'react'; import url from 'url'; -import { InfraAppId } from '@kbn/infra-plugin/public'; +import { InfraAppId } from '@kbn/observability-shared-plugin/public/infra'; import { useApmPluginContext } from '../../../context/apm_plugin/use_apm_plugin_context'; import { fromQuery } from './url_helpers'; diff --git a/x-pack/plugins/apm/public/components/shared/links/observability_logs_link.ts b/x-pack/plugins/apm/public/components/shared/links/observability_logs_link.ts index 85bbaf2d09bdf..72ae29960942e 100644 --- a/x-pack/plugins/apm/public/components/shared/links/observability_logs_link.ts +++ b/x-pack/plugins/apm/public/components/shared/links/observability_logs_link.ts @@ -6,9 +6,9 @@ */ import type { - NodeLogsLocator, - LogsLocator, -} from '@kbn/infra-plugin/common/locators'; + LogsLocatorParams, + NodeLogsLocatorParams, +} from '@kbn/logs-shared-plugin/common'; import { AllDatasetsLocatorParams } from '@kbn/deeplinks-observability/locators'; import { LocatorPublic } from '@kbn/share-plugin/common'; import moment from 'moment'; @@ -27,7 +27,7 @@ export const getNodeLogsHref = ( id: string, time: number | undefined, allDatasetsLocator: LocatorPublic, - infraNodeLocator?: NodeLogsLocator + infraNodeLocator?: LocatorPublic ): string => { if (infraNodeLocator) return infraNodeLocator?.getRedirectUrl({ @@ -53,7 +53,7 @@ export const getTraceLogsHref = ( traceId: string, time: number | undefined, allDatasetsLocator: LocatorPublic, - infraLogsLocator?: LogsLocator + infraLogsLocator: LocatorPublic ): string => { const query = `trace.id:"${traceId}" OR (not trace.id:* AND "${traceId}")`; diff --git a/x-pack/plugins/apm/public/components/shared/technical_preview_badge.tsx b/x-pack/plugins/apm/public/components/shared/technical_preview_badge.tsx index b00d0c256f3f5..2ff1b1b9050b3 100644 --- a/x-pack/plugins/apm/public/components/shared/technical_preview_badge.tsx +++ b/x-pack/plugins/apm/public/components/shared/technical_preview_badge.tsx @@ -23,7 +23,7 @@ export function TechnicalPreviewBadge({ icon, size, style }: Props) { 'xpack.apm.technicalPreviewBadgeDescription', { defaultMessage: - 'This functionality is in technical preview and may be changed or removed completely in a future release. Elastic will take a best effort approach to fix any issues, but features in technical preview are not subject to the support SLA of official GA features.', + 'This functionality is in technical preview and may be changed or removed completely in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features.', } )} iconType={icon} diff --git a/x-pack/plugins/apm/public/components/shared/transaction_action_menu/sections.test.ts b/x-pack/plugins/apm/public/components/shared/transaction_action_menu/sections.test.ts index df066a57418fc..fe8cb9d68fdfb 100644 --- a/x-pack/plugins/apm/public/components/shared/transaction_action_menu/sections.test.ts +++ b/x-pack/plugins/apm/public/components/shared/transaction_action_menu/sections.test.ts @@ -7,6 +7,11 @@ import { createMemoryHistory } from 'history'; import { IBasePath } from '@kbn/core/public'; +import { LocatorPublic } from '@kbn/share-plugin/common'; +import { + LogsLocatorParams, + NodeLogsLocatorParams, +} from '@kbn/logs-shared-plugin/common'; import { Transaction } from '../../../../typings/es_schemas/ui/transaction'; import { getSections } from './sections'; import { @@ -24,12 +29,12 @@ const apmRouter = { `some-basepath/app/apm${apmRouterBase.link(...args)}`, } as ApmRouter; -const infraLocators = infraLocatorsMock; const { allDatasetsLocator } = observabilityLogExplorerLocatorsMock; +const { nodeLogsLocator, logsLocator } = infraLocatorsMock; const expectInfraLocatorsToBeCalled = () => { - expect(infraLocators.nodeLogsLocator.getRedirectUrl).toBeCalledTimes(3); - expect(infraLocators.logsLocator.getRedirectUrl).toBeCalledTimes(1); + expect(nodeLogsLocator.getRedirectUrl).toBeCalledTimes(3); + expect(logsLocator.getRedirectUrl).toBeCalledTimes(1); }; describe('Transaction action menu', () => { @@ -64,8 +69,10 @@ describe('Transaction action menu', () => { basePath, location, apmRouter, - infraLocators, allDatasetsLocator, + logsLocator: logsLocator as unknown as LocatorPublic, + nodeLogsLocator: + nodeLogsLocator as unknown as LocatorPublic, infraLinksAvailable: false, rangeFrom: 'now-24h', rangeTo: 'now', @@ -130,7 +137,9 @@ describe('Transaction action menu', () => { basePath, location, apmRouter, - infraLocators, + logsLocator: logsLocator as unknown as LocatorPublic, + nodeLogsLocator: + nodeLogsLocator as unknown as LocatorPublic, allDatasetsLocator, infraLinksAvailable: true, rangeFrom: 'now-24h', @@ -215,7 +224,9 @@ describe('Transaction action menu', () => { basePath, location, apmRouter, - infraLocators, + logsLocator: logsLocator as unknown as LocatorPublic, + nodeLogsLocator: + nodeLogsLocator as unknown as LocatorPublic, allDatasetsLocator, infraLinksAvailable: true, rangeFrom: 'now-24h', diff --git a/x-pack/plugins/apm/public/components/shared/transaction_action_menu/sections.ts b/x-pack/plugins/apm/public/components/shared/transaction_action_menu/sections.ts index 04b8f7f41bdf1..a944a80a458f7 100644 --- a/x-pack/plugins/apm/public/components/shared/transaction_action_menu/sections.ts +++ b/x-pack/plugins/apm/public/components/shared/transaction_action_menu/sections.ts @@ -11,7 +11,10 @@ import { IBasePath } from '@kbn/core/public'; import { isEmpty, pickBy } from 'lodash'; import moment from 'moment'; import url from 'url'; -import type { InfraLocators } from '@kbn/infra-plugin/common/locators'; +import { + LogsLocatorParams, + NodeLogsLocatorParams, +} from '@kbn/logs-shared-plugin/common'; import { LocatorPublic } from '@kbn/share-plugin/common'; import { AllDatasetsLocatorParams } from '@kbn/deeplinks-observability/locators'; import type { ProfilingLocators } from '@kbn/observability-shared-plugin/public'; @@ -44,32 +47,33 @@ export const getSections = ({ basePath, location, apmRouter, - infraLocators, infraLinksAvailable, profilingLocators, rangeFrom, rangeTo, environment, allDatasetsLocator, + logsLocator, + nodeLogsLocator, }: { transaction?: Transaction; basePath: IBasePath; location: Location; apmRouter: ApmRouter; - infraLocators?: InfraLocators; infraLinksAvailable: boolean; profilingLocators?: ProfilingLocators; rangeFrom: string; rangeTo: string; environment: Environment; allDatasetsLocator: LocatorPublic; + logsLocator: LocatorPublic; + nodeLogsLocator: LocatorPublic; }) => { if (!transaction) return []; const hostName = transaction.host?.hostname; const podId = transaction.kubernetes?.pod?.uid; const containerId = transaction.container?.id; - const { nodeLogsLocator, logsLocator } = infraLocators ?? {}; const time = Math.round(transaction.timestamp.us / 1000); const infraMetricsQuery = getInfraMetricsQuery(transaction); diff --git a/x-pack/plugins/apm/public/components/shared/transaction_action_menu/transaction_action_menu.test.tsx b/x-pack/plugins/apm/public/components/shared/transaction_action_menu/transaction_action_menu.test.tsx index 5e1b8e6b099d0..28fc0657ee831 100644 --- a/x-pack/plugins/apm/public/components/shared/transaction_action_menu/transaction_action_menu.test.tsx +++ b/x-pack/plugins/apm/public/components/shared/transaction_action_menu/transaction_action_menu.test.tsx @@ -10,11 +10,16 @@ import React from 'react'; import { MemoryRouter } from 'react-router-dom'; import { createMemoryHistory } from 'history'; import { License } from '@kbn/licensing-plugin/common/license'; +import { + LOGS_LOCATOR_ID, + NODE_LOGS_LOCATOR_ID, +} from '@kbn/logs-shared-plugin/common'; import { Transaction } from '../../../../typings/es_schemas/ui/transaction'; import { ApmPluginContextValue } from '../../../context/apm_plugin/apm_plugin_context'; import { mockApmPluginContextValue, MockApmPluginContextWrapper, + infraLocatorsMock, } from '../../../context/apm_plugin/mock_apm_plugin_context'; import { LicenseContext } from '../../../context/license/license_context'; import * as hooks from '../../../hooks/use_fetcher'; @@ -32,6 +37,21 @@ const apmContextMock = { ...mockApmPluginContextValue.core, application: { capabilities: { apm: { save: true }, ml: {} } }, }, + share: { + url: { + locators: { + get: (id: string) => { + if (id === LOGS_LOCATOR_ID) { + return infraLocatorsMock.logsLocator; + } + + if (id === NODE_LOGS_LOCATOR_ID) { + return infraLocatorsMock.nodeLogsLocator; + } + }, + }, + }, + }, } as unknown as ApmPluginContextValue; const history = createMemoryHistory(); @@ -68,12 +88,8 @@ const renderTransaction = async (transaction: Record) => { }; const expectInfraLocatorsToBeCalled = () => { - expect( - apmContextMock.infra?.locators.nodeLogsLocator.getRedirectUrl - ).toBeCalled(); - expect( - apmContextMock.infra?.locators.logsLocator.getRedirectUrl - ).toBeCalled(); + expect(infraLocatorsMock.nodeLogsLocator.getRedirectUrl).toBeCalled(); + expect(infraLocatorsMock.logsLocator.getRedirectUrl).toBeCalled(); }; describe('TransactionActionMenu component', () => { diff --git a/x-pack/plugins/apm/public/components/shared/transaction_action_menu/transaction_action_menu.tsx b/x-pack/plugins/apm/public/components/shared/transaction_action_menu/transaction_action_menu.tsx index 4dcd10a3ea540..02664e370b9c3 100644 --- a/x-pack/plugins/apm/public/components/shared/transaction_action_menu/transaction_action_menu.tsx +++ b/x-pack/plugins/apm/public/components/shared/transaction_action_menu/transaction_action_menu.tsx @@ -25,6 +25,12 @@ import { AllDatasetsLocatorParams, ALL_DATASETS_LOCATOR_ID, } from '@kbn/deeplinks-observability/locators'; +import { + LOGS_LOCATOR_ID, + LogsLocatorParams, + NODE_LOGS_LOCATOR_ID, + NodeLogsLocatorParams, +} from '@kbn/logs-shared-plugin/common'; import type { ProfilingLocators } from '@kbn/observability-shared-plugin/public'; import { useAnyOfApmParams } from '../../../hooks/use_apm_params'; import { ApmFeatureFlagName } from '../../../../common/apm_feature_flags'; @@ -129,13 +135,17 @@ function ActionMenuSections({ transaction?: Transaction; profilingLocators?: ProfilingLocators; }) { - const { core, uiActions, infra, share } = useApmPluginContext(); + const { core, uiActions, share } = useApmPluginContext(); const location = useLocation(); const apmRouter = useApmRouter(); const allDatasetsLocator = share.url.locators.get( ALL_DATASETS_LOCATOR_ID )!; + const logsLocator = + share.url.locators.get(LOGS_LOCATOR_ID)!; + const nodeLogsLocator = + share.url.locators.get(NODE_LOGS_LOCATOR_ID)!; const infraLinksAvailable = useApmFeatureFlag( ApmFeatureFlagName.InfraUiAvailable @@ -155,13 +165,14 @@ function ActionMenuSections({ basePath: core.http.basePath, location, apmRouter, - infraLocators: infra?.locators, infraLinksAvailable, profilingLocators, rangeFrom, rangeTo, environment, allDatasetsLocator, + logsLocator, + nodeLogsLocator, }); const externalMenuItems = useAsync(() => { diff --git a/x-pack/plugins/apm/public/context/apm_plugin/apm_plugin_context.tsx b/x-pack/plugins/apm/public/context/apm_plugin/apm_plugin_context.tsx index efe88ced91d4a..9440a5e1c13f5 100644 --- a/x-pack/plugins/apm/public/context/apm_plugin/apm_plugin_context.tsx +++ b/x-pack/plugins/apm/public/context/apm_plugin/apm_plugin_context.tsx @@ -15,7 +15,6 @@ import type { DataViewsPublicPluginStart } from '@kbn/data-views-plugin/public'; import type { UnifiedSearchPublicPluginStart } from '@kbn/unified-search-plugin/public'; import type { DataPublicPluginStart } from '@kbn/data-plugin/public'; import type { UiActionsStart } from '@kbn/ui-actions-plugin/public'; -import type { InfraClientStartExports } from '@kbn/infra-plugin/public'; import type { ObservabilityAIAssistantPluginStart } from '@kbn/observability-ai-assistant-plugin/public'; import { SharePluginSetup } from '@kbn/share-plugin/public'; import type { ApmPluginSetupDeps } from '../../plugin'; @@ -29,7 +28,6 @@ export interface ApmPluginContextValue { plugins: ApmPluginSetupDeps & { maps?: MapsStartApi }; observabilityRuleTypeRegistry: ObservabilityRuleTypeRegistry; observability: ObservabilityPublicStart; - infra?: InfraClientStartExports; dataViews: DataViewsPublicPluginStart; data: DataPublicPluginStart; unifiedSearch: UnifiedSearchPublicPluginStart; diff --git a/x-pack/plugins/apm/public/context/apm_plugin/mock_apm_plugin_context.tsx b/x-pack/plugins/apm/public/context/apm_plugin/mock_apm_plugin_context.tsx index e135161129c7c..61710babd1dac 100644 --- a/x-pack/plugins/apm/public/context/apm_plugin/mock_apm_plugin_context.tsx +++ b/x-pack/plugins/apm/public/context/apm_plugin/mock_apm_plugin_context.tsx @@ -17,7 +17,6 @@ import { UI_SETTINGS } from '@kbn/data-plugin/common'; import { MlLocatorDefinition } from '@kbn/ml-plugin/public'; import { enableComparisonByDefault } from '@kbn/observability-plugin/public'; import { sharePluginMock } from '@kbn/share-plugin/public/mocks'; -import type { InfraLocators } from '@kbn/infra-plugin/common/locators'; import { apmEnableProfilingIntegration } from '@kbn/observability-plugin/common'; import { ApmPluginContext, ApmPluginContextValue } from './apm_plugin_context'; import { ConfigSchema } from '../..'; @@ -127,16 +126,16 @@ const mockPlugin = { }, }; -export const infraLocatorsMock: InfraLocators = { - logsLocator: sharePluginMock.createLocator(), - nodeLogsLocator: sharePluginMock.createLocator(), -}; - export const observabilityLogExplorerLocatorsMock = { allDatasetsLocator: sharePluginMock.createLocator(), singleDatasetLocator: sharePluginMock.createLocator(), }; +export const infraLocatorsMock = { + nodeLogsLocator: sharePluginMock.createLocator(), + logsLocator: sharePluginMock.createLocator(), +}; + const mockCorePlugins = { embeddable: {}, inspector: {}, @@ -159,9 +158,6 @@ export const mockApmPluginContextValue = { plugins: mockPlugin, observabilityRuleTypeRegistry: createObservabilityRuleTypeRegistryMock(), corePlugins: mockCorePlugins, - infra: { - locators: infraLocatorsMock, - }, deps: {}, share: sharePluginMock.createSetupContract(), unifiedSearch: mockUnifiedSearch, diff --git a/x-pack/plugins/apm/public/plugin.ts b/x-pack/plugins/apm/public/plugin.ts index f9206b8aaa782..80dfa77ca40d0 100644 --- a/x-pack/plugins/apm/public/plugin.ts +++ b/x-pack/plugins/apm/public/plugin.ts @@ -35,7 +35,7 @@ import { FieldFormatsStart } from '@kbn/field-formats-plugin/public'; import type { FleetStart } from '@kbn/fleet-plugin/public'; import type { HomePublicPluginSetup } from '@kbn/home-plugin/public'; import { i18n } from '@kbn/i18n'; -import { InfraClientStartExports } from '@kbn/infra-plugin/public'; +import { MetricsDataPluginStart } from '@kbn/metrics-data-access-plugin/public'; import { Start as InspectorPluginStart } from '@kbn/inspector-plugin/public'; import type { IStorageWrapper } from '@kbn/kibana-utils-plugin/public'; import { LensPublicStart } from '@kbn/lens-plugin/public'; @@ -128,7 +128,6 @@ export interface ApmPluginStartDeps { fieldFormats?: FieldFormatsStart; security?: SecurityPluginStart; spaces?: SpacesPluginStart; - infra?: InfraClientStartExports; dataViews: DataViewsPublicPluginStart; unifiedSearch: UnifiedSearchPublicPluginStart; storage: IStorageWrapper; @@ -137,6 +136,7 @@ export interface ApmPluginStartDeps { profiling?: ProfilingPluginStart; observabilityAIAssistant: ObservabilityAIAssistantPluginStart; dashboard: DashboardStart; + metricsDataAccess: MetricsDataPluginStart; } const servicesTitle = i18n.translate('xpack.apm.navigation.servicesTitle', { diff --git a/x-pack/plugins/apm/server/feature.ts b/x-pack/plugins/apm/server/feature.ts index 79136af2f8856..5a0ba552a0c18 100644 --- a/x-pack/plugins/apm/server/feature.ts +++ b/x-pack/plugins/apm/server/feature.ts @@ -14,10 +14,8 @@ import { } from '@kbn/licensing-plugin/server'; import { APM_INDEX_SETTINGS_SAVED_OBJECT_TYPE } from '@kbn/apm-data-access-plugin/server/saved_objects/apm_indices'; -import { - ApmRuleType, - APM_SERVER_FEATURE_ID, -} from '../common/rules/apm_rule_types'; +import { ApmRuleType } from '@kbn/rule-data-utils'; +import { APM_SERVER_FEATURE_ID } from '../common/rules/apm_rule_types'; const ruleTypes = Object.values(ApmRuleType); diff --git a/x-pack/plugins/apm/server/routes/alerts/rule_types/anomaly/register_anomaly_rule_type.ts b/x-pack/plugins/apm/server/routes/alerts/rule_types/anomaly/register_anomaly_rule_type.ts index 5e761229be8f6..407b128c03240 100644 --- a/x-pack/plugins/apm/server/routes/alerts/rule_types/anomaly/register_anomaly_rule_type.ts +++ b/x-pack/plugins/apm/server/routes/alerts/rule_types/anomaly/register_anomaly_rule_type.ts @@ -21,6 +21,7 @@ import { ALERT_EVALUATION_VALUE, ALERT_REASON, ALERT_SEVERITY, + ApmRuleType, } from '@kbn/rule-data-utils'; import { createLifecycleRuleTypeFactory } from '@kbn/rule-registry-plugin/server'; import { addSpaceIdToPath } from '@kbn/spaces-plugin/common'; @@ -43,7 +44,7 @@ import { } from '../../../../../common/environment_filter_values'; import { ANOMALY_ALERT_SEVERITY_TYPES, - ApmRuleType, + APM_SERVER_FEATURE_ID, formatAnomalyReason, RULE_TYPES_CONFIG, } from '../../../../../common/rules/apm_rule_types'; @@ -94,7 +95,7 @@ export function registerAnomalyRuleType({ ], }, category: DEFAULT_APP_CATEGORIES.observability.id, - producer: 'apm', + producer: APM_SERVER_FEATURE_ID, minimumLicenseRequired: 'basic', isExportable: true, executor: async ({ 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 a1fcb98d7a323..653c5562804c0 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 @@ -11,6 +11,7 @@ import { termQuery, } from '@kbn/observability-plugin/server'; import { ProcessorEvent } from '@kbn/observability-plugin/common'; +import { ApmRuleType } from '@kbn/rule-data-utils'; import { ERROR_GROUP_ID, PROCESSOR_EVENT, @@ -21,7 +22,6 @@ import { environmentQuery } from '../../../../../common/utils/environment_query' import { APMEventClient } from '../../../../lib/helpers/create_es_client/create_apm_event_client'; import { getGroupByTerms } from '../utils/get_groupby_terms'; import { getAllGroupByFields } from '../../../../../common/rules/get_all_groupby_fields'; -import { ApmRuleType } from '../../../../../common/rules/apm_rule_types'; import { BarSeriesDataMap, getFilteredBarSeries, 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 6a0a5b8fdbbe6..ba053dbcb8577 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 @@ -18,6 +18,7 @@ import { ALERT_EVALUATION_THRESHOLD, ALERT_EVALUATION_VALUE, ALERT_REASON, + ApmRuleType, } from '@kbn/rule-data-utils'; import { createLifecycleRuleTypeFactory } from '@kbn/rule-registry-plugin/server'; import { @@ -34,7 +35,6 @@ import { SERVICE_NAME, } from '../../../../../common/es_fields/apm'; import { - ApmRuleType, APM_SERVER_FEATURE_ID, formatErrorCountReason, RULE_TYPES_CONFIG, 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 db968bdfcc2ce..0384ad24839f2 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 @@ -11,10 +11,8 @@ import { rangeQuery, termQuery, } from '@kbn/observability-plugin/server'; -import { - AggregationType, - ApmRuleType, -} from '../../../../../common/rules/apm_rule_types'; +import { ApmRuleType } from '@kbn/rule-data-utils'; +import { AggregationType } from '../../../../../common/rules/apm_rule_types'; import { SERVICE_NAME, 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 3789a55e6e4e0..ef0cb2beb21c9 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 @@ -24,6 +24,7 @@ import { ALERT_EVALUATION_THRESHOLD, ALERT_EVALUATION_VALUE, ALERT_REASON, + ApmRuleType, } from '@kbn/rule-data-utils'; import { createLifecycleRuleTypeFactory } from '@kbn/rule-registry-plugin/server'; import { addSpaceIdToPath } from '@kbn/spaces-plugin/common'; @@ -38,7 +39,6 @@ import { TRANSACTION_TYPE, } from '../../../../../common/es_fields/apm'; import { - ApmRuleType, APM_SERVER_FEATURE_ID, formatTransactionDurationReason, RULE_TYPES_CONFIG, @@ -87,9 +87,9 @@ export const transactionDurationActionVariables = [ export function registerTransactionDurationRuleType({ alerting, + apmConfig, ruleDataClient, getApmIndices, - apmConfig, logger, basePath, }: RegisterRuleDependencies) { 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 853252e6ef453..10f5457380719 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 @@ -10,7 +10,7 @@ import { rangeQuery, termQuery, } from '@kbn/observability-plugin/server'; -import { ApmRuleType } from '../../../../../common/rules/apm_rule_types'; +import { ApmRuleType } from '@kbn/rule-data-utils'; import { SERVICE_NAME, 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 7e3c7bce8baf3..30c8c6fb96b96 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 @@ -23,6 +23,7 @@ import { ALERT_EVALUATION_THRESHOLD, ALERT_EVALUATION_VALUE, ALERT_REASON, + ApmRuleType, } from '@kbn/rule-data-utils'; import { createLifecycleRuleTypeFactory } from '@kbn/rule-registry-plugin/server'; import { addSpaceIdToPath } from '@kbn/spaces-plugin/common'; @@ -39,7 +40,6 @@ import { } from '../../../../../common/es_fields/apm'; import { EventOutcome } from '../../../../../common/event_outcome'; import { - ApmRuleType, APM_SERVER_FEATURE_ID, formatTransactionErrorRateReason, RULE_TYPES_CONFIG, @@ -83,9 +83,9 @@ export const transactionErrorRateActionVariables = [ export function registerTransactionErrorRateRuleType({ alerting, alertsLocator, + apmConfig, basePath, getApmIndices, - apmConfig, logger, ruleDataClient, }: RegisterRuleDependencies) { diff --git a/x-pack/plugins/apm/server/routes/alerts/test_utils/index.ts b/x-pack/plugins/apm/server/routes/alerts/test_utils/index.ts index b4b5692708456..a447ab2a75d4b 100644 --- a/x-pack/plugins/apm/server/routes/alerts/test_utils/index.ts +++ b/x-pack/plugins/apm/server/routes/alerts/test_utils/index.ts @@ -56,7 +56,9 @@ export const createRuleTypeMocks = () => { publicBaseUrl: 'http://localhost:5601/eyr', serverBasePath: '/eyr', } as IBasePath, - apmConfig: { searchAggregatedTransactions: true } as any as APMConfig, + apmConfig: { + searchAggregatedTransactions: true, + } as any as APMConfig, getApmIndices: async () => ({ error: 'apm-*', transaction: 'apm-*', diff --git a/x-pack/plugins/apm/tsconfig.json b/x-pack/plugins/apm/tsconfig.json index 2c225c509fad6..47aab0ba345a3 100644 --- a/x-pack/plugins/apm/tsconfig.json +++ b/x-pack/plugins/apm/tsconfig.json @@ -28,7 +28,6 @@ "@kbn/alerting-plugin", "@kbn/cloud-plugin", "@kbn/features-plugin", - "@kbn/infra-plugin", "@kbn/licensing-plugin", "@kbn/license-management-plugin", "@kbn/maps-plugin", diff --git a/x-pack/plugins/apm/typings/common.d.ts b/x-pack/plugins/apm/typings/common.d.ts index d265c7b8410f1..aa4653c2971f3 100644 --- a/x-pack/plugins/apm/typings/common.d.ts +++ b/x-pack/plugins/apm/typings/common.d.ts @@ -5,7 +5,6 @@ * 2.0. */ -import '@kbn/infra-plugin/types/eui'; import './apm_rum_react'; // Allow unknown properties in an object diff --git a/x-pack/plugins/asset_manager/common/constants_routes.ts b/x-pack/plugins/asset_manager/common/constants_routes.ts index d256e4264a035..969df93d1bc9d 100644 --- a/x-pack/plugins/asset_manager/common/constants_routes.ts +++ b/x-pack/plugins/asset_manager/common/constants_routes.ts @@ -17,3 +17,4 @@ export const GET_ASSETS_DIFF = base('/assets/diff'); export const GET_HOSTS = base('/assets/hosts'); export const GET_SERVICES = base('/assets/services'); +export const GET_CONTAINERS = base('/assets/containers'); diff --git a/x-pack/plugins/asset_manager/common/types_api.ts b/x-pack/plugins/asset_manager/common/types_api.ts index 3b63f26819202..dd555c69328e5 100644 --- a/x-pack/plugins/asset_manager/common/types_api.ts +++ b/x-pack/plugins/asset_manager/common/types_api.ts @@ -27,7 +27,6 @@ export const assetKindRT = rt.keyof({ pod: null, container: null, service: null, - alert: null, }); export type AssetKind = rt.TypeOf; @@ -166,18 +165,24 @@ export interface K8sCluster extends WithTimestamp { }; } -export interface AssetFilters { - type?: AssetType | AssetType[]; - kind?: AssetKind | AssetKind[]; - ean?: string | string[]; - id?: string; - typeLike?: string; - kindLike?: string; - eanLike?: string; - collectionVersion?: number | 'latest' | 'all'; - from?: string | number; - to?: string | number; -} +export const assetFiltersSingleKindRT = rt.exact( + rt.partial({ + type: rt.union([assetTypeRT, rt.array(assetTypeRT)]), + ean: rt.union([rt.string, rt.array(rt.string)]), + id: rt.string, + ['cloud.provider']: rt.string, + ['cloud.region']: rt.string, + }) +); + +export type SingleKindAssetFilters = rt.TypeOf; + +export const assetFiltersRT = rt.intersection([ + assetFiltersSingleKindRT, + rt.partial({ kind: rt.union([assetKindRT, rt.array(assetKindRT)]) }), +]); + +export type AssetFilters = rt.TypeOf; export const relationRT = rt.union([ rt.literal('ancestors'), @@ -200,30 +205,53 @@ export const assetDateRT = rt.union([dateRt, datemathStringRt]); /** * Hosts */ -export const getHostAssetsQueryOptionsRT = rt.exact( +export const getHostAssetsQueryOptionsRT = rt.intersection([ + rt.strict({ from: assetDateRT }), rt.partial({ - from: assetDateRT, to: assetDateRT, size: sizeRT, - }) -); + stringFilters: rt.string, + filters: assetFiltersSingleKindRT, + }), +]); export type GetHostAssetsQueryOptions = rt.TypeOf; export const getHostAssetsResponseRT = rt.type({ hosts: rt.array(assetRT), }); export type GetHostAssetsResponse = rt.TypeOf; +/** + * Containers + */ +export const getContainerAssetsQueryOptionsRT = rt.intersection([ + rt.strict({ from: assetDateRT }), + rt.partial({ + to: assetDateRT, + size: sizeRT, + stringFilters: rt.string, + filters: assetFiltersSingleKindRT, + }), +]); +export type GetContainerAssetsQueryOptions = rt.TypeOf; +export const getContainerAssetsResponseRT = rt.type({ + containers: rt.array(assetRT), +}); +export type GetContainerAssetsResponse = rt.TypeOf; + /** * Services */ -export const getServiceAssetsQueryOptionsRT = rt.exact( +export const getServiceAssetsQueryOptionsRT = rt.intersection([ + rt.strict({ from: assetDateRT }), rt.partial({ from: assetDateRT, to: assetDateRT, size: sizeRT, parent: rt.string, - }) -); + stringFilters: rt.string, + filters: assetFiltersSingleKindRT, + }), +]); export type GetServiceAssetsQueryOptions = rt.TypeOf; export const getServiceAssetsResponseRT = rt.type({ diff --git a/x-pack/plugins/asset_manager/common/types_client.ts b/x-pack/plugins/asset_manager/common/types_client.ts index 79d2c11e42abf..40b3eb5e07e8f 100644 --- a/x-pack/plugins/asset_manager/common/types_client.ts +++ b/x-pack/plugins/asset_manager/common/types_client.ts @@ -5,13 +5,22 @@ * 2.0. */ -export interface SharedAssetsOptionsPublic { +import { AssetFilters, SingleKindAssetFilters } from './types_api'; + +export interface SharedAssetsOptionsPublic { from: string; to?: string; + filters?: F; + stringFilters?: string; } -export type GetHostsOptionsPublic = SharedAssetsOptionsPublic; +// Methods that return only a single "kind" of asset should not accept +// a filter of "kind" to filter by asset kinds + +export type GetHostsOptionsPublic = SharedAssetsOptionsPublic; +export type GetContainersOptionsPublic = SharedAssetsOptionsPublic; -export interface GetServicesOptionsPublic extends SharedAssetsOptionsPublic { +export interface GetServicesOptionsPublic + extends SharedAssetsOptionsPublic { parent?: string; } diff --git a/x-pack/plugins/asset_manager/public/lib/public_assets_client.test.ts b/x-pack/plugins/asset_manager/public/lib/public_assets_client.test.ts index 5eca030e832db..f465fa66ad2b8 100644 --- a/x-pack/plugins/asset_manager/public/lib/public_assets_client.test.ts +++ b/x-pack/plugins/asset_manager/public/lib/public_assets_client.test.ts @@ -38,6 +38,18 @@ describe('Public assets client', () => { }); }); + it('should include provided filters, but in string form', async () => { + const client = new PublicAssetsClient(http); + const filters = { id: '*id-1*' }; + await client.getHosts({ from: 'x', filters }); + expect(http.get).toBeCalledWith(routePaths.GET_HOSTS, { + query: { + from: 'x', + stringFilters: JSON.stringify(filters), + }, + }); + }); + it('should return the direct results of http.get', async () => { const client = new PublicAssetsClient(http); http.get.mockResolvedValueOnce('my hosts'); @@ -46,6 +58,41 @@ describe('Public assets client', () => { }); }); + describe('getContainers', () => { + it('should call the REST API', async () => { + const client = new PublicAssetsClient(http); + await client.getContainers({ from: 'x', to: 'y' }); + expect(http.get).toBeCalledTimes(1); + }); + + it('should include specified "from" and "to" parameters in http.get query', async () => { + const client = new PublicAssetsClient(http); + await client.getContainers({ from: 'x', to: 'y' }); + expect(http.get).toBeCalledWith(routePaths.GET_CONTAINERS, { + query: { from: 'x', to: 'y' }, + }); + }); + + it('should include provided filters, but in string form', async () => { + const client = new PublicAssetsClient(http); + const filters = { id: '*id-1*' }; + await client.getContainers({ from: 'x', filters }); + expect(http.get).toBeCalledWith(routePaths.GET_CONTAINERS, { + query: { + from: 'x', + stringFilters: JSON.stringify(filters), + }, + }); + }); + + it('should return the direct results of http.get', async () => { + const client = new PublicAssetsClient(http); + http.get.mockResolvedValueOnce('my hosts'); + const result = await client.getContainers({ from: 'x', to: 'y' }); + expect(result).toBe('my hosts'); + }); + }); + describe('getServices', () => { it('should call the REST API', async () => { const client = new PublicAssetsClient(http); @@ -61,6 +108,18 @@ describe('Public assets client', () => { }); }); + it('should include provided filters, but in string form', async () => { + const client = new PublicAssetsClient(http); + const filters = { id: '*id-1*' }; + await client.getServices({ from: 'x', filters }); + expect(http.get).toBeCalledWith(routePaths.GET_SERVICES, { + query: { + from: 'x', + stringFilters: JSON.stringify(filters), + }, + }); + }); + it('should include specified "parent" parameter in http.get query', async () => { const client = new PublicAssetsClient(http); await client.getServices({ from: 'x', to: 'y', parent: 'container:123' }); diff --git a/x-pack/plugins/asset_manager/public/lib/public_assets_client.ts b/x-pack/plugins/asset_manager/public/lib/public_assets_client.ts index 9509e61e073a6..7ff5617d8ceb5 100644 --- a/x-pack/plugins/asset_manager/public/lib/public_assets_client.ts +++ b/x-pack/plugins/asset_manager/public/lib/public_assets_client.ts @@ -6,18 +6,40 @@ */ import { HttpStart } from '@kbn/core/public'; -import { GetHostsOptionsPublic, GetServicesOptionsPublic } from '../../common/types_client'; -import { GetHostAssetsResponse, GetServiceAssetsResponse } from '../../common/types_api'; -import { GET_HOSTS, GET_SERVICES } from '../../common/constants_routes'; +import { + GetContainersOptionsPublic, + GetHostsOptionsPublic, + GetServicesOptionsPublic, +} from '../../common/types_client'; +import { + GetContainerAssetsResponse, + GetHostAssetsResponse, + GetServiceAssetsResponse, +} from '../../common/types_api'; +import { GET_CONTAINERS, GET_HOSTS, GET_SERVICES } from '../../common/constants_routes'; import { IPublicAssetsClient } from '../types'; export class PublicAssetsClient implements IPublicAssetsClient { constructor(private readonly http: HttpStart) {} async getHosts(options: GetHostsOptionsPublic) { + const { filters, ...otherOptions } = options; const results = await this.http.get(GET_HOSTS, { query: { - ...options, + stringFilters: JSON.stringify(filters), + ...otherOptions, + }, + }); + + return results; + } + + async getContainers(options: GetContainersOptionsPublic) { + const { filters, ...otherOptions } = options; + const results = await this.http.get(GET_CONTAINERS, { + query: { + stringFilters: JSON.stringify(filters), + ...otherOptions, }, }); @@ -25,9 +47,11 @@ export class PublicAssetsClient implements IPublicAssetsClient { } async getServices(options: GetServicesOptionsPublic) { + const { filters, ...otherOptions } = options; const results = await this.http.get(GET_SERVICES, { query: { - ...options, + stringFilters: JSON.stringify(filters), + ...otherOptions, }, }); diff --git a/x-pack/plugins/asset_manager/public/plugin.ts b/x-pack/plugins/asset_manager/public/plugin.ts index 4b2d91f3a60f1..620c2060b83e9 100644 --- a/x-pack/plugins/asset_manager/public/plugin.ts +++ b/x-pack/plugins/asset_manager/public/plugin.ts @@ -7,6 +7,7 @@ import { CoreSetup, CoreStart, PluginInitializerContext } from '@kbn/core/public'; import { Logger } from '@kbn/logging'; + import { AssetManagerPluginClass } from './types'; import { PublicAssetsClient } from './lib/public_assets_client'; import type { AssetManagerPublicConfig } from '../common/config'; diff --git a/x-pack/plugins/asset_manager/server/lib/accessors/containers/get_containers.test.ts b/x-pack/plugins/asset_manager/server/lib/accessors/containers/get_containers.test.ts new file mode 100644 index 0000000000000..0a7b34b9ad1ad --- /dev/null +++ b/x-pack/plugins/asset_manager/server/lib/accessors/containers/get_containers.test.ts @@ -0,0 +1,357 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { elasticsearchClientMock } from '@kbn/core-elasticsearch-client-server-mocks'; +import { savedObjectsClientMock } from '@kbn/core-saved-objects-api-server-mocks'; +import { GetApmIndicesMethod } from '../../asset_client_types'; +import { getContainers } from './get_containers'; +import { + createGetApmIndicesMock, + expectToThrowValidationErrorWithStatusCode, +} from '../../../test_utils'; +import { MetricsDataClient, MetricsDataClientMock } from '@kbn/metrics-data-access-plugin/server'; +import { SearchRequest } from '@elastic/elasticsearch/lib/api/types'; + +function createBaseOptions({ + getApmIndicesMock, + metricsDataClientMock, +}: { + getApmIndicesMock: GetApmIndicesMethod; + metricsDataClientMock: MetricsDataClient; +}) { + return { + sourceIndices: { + logs: 'my-logs*', + }, + getApmIndices: getApmIndicesMock, + metricsClient: metricsDataClientMock, + }; +} + +describe('getHosts', () => { + let getApmIndicesMock = createGetApmIndicesMock(); + let metricsDataClientMock = MetricsDataClientMock.create(); + let baseOptions = createBaseOptions({ getApmIndicesMock, metricsDataClientMock }); + let esClientMock = elasticsearchClientMock.createScopedClusterClient().asCurrentUser; + let soClientMock = savedObjectsClientMock.create(); + + function resetMocks() { + getApmIndicesMock = createGetApmIndicesMock(); + metricsDataClientMock = MetricsDataClientMock.create(); + baseOptions = createBaseOptions({ getApmIndicesMock, metricsDataClientMock }); + esClientMock = elasticsearchClientMock.createScopedClusterClient().asCurrentUser; + soClientMock = savedObjectsClientMock.create(); + } + + beforeEach(() => { + resetMocks(); + + // ES returns no results, just enough structure to not blow up + esClientMock.search.mockResolvedValueOnce({ + took: 1, + timed_out: false, + _shards: { + failed: 0, + successful: 1, + total: 1, + }, + hits: { + hits: [], + }, + }); + }); + + it('should query Elasticsearch correctly', async () => { + await getContainers({ + ...baseOptions, + from: 'now-5d', + to: 'now-3d', + elasticsearchClient: esClientMock, + savedObjectsClient: soClientMock, + }); + + expect(metricsDataClientMock.getMetricIndices).toHaveBeenCalledTimes(1); + expect(metricsDataClientMock.getMetricIndices).toHaveBeenCalledWith({ + savedObjectsClient: soClientMock, + }); + + const dsl = esClientMock.search.mock.lastCall?.[0] as SearchRequest | undefined; + const { bool } = dsl?.query || {}; + expect(bool).toBeDefined(); + + expect(bool?.filter).toEqual([ + { + range: { + '@timestamp': { + gte: 'now-5d', + lte: 'now-3d', + }, + }, + }, + ]); + + expect(bool?.must).toEqual([ + { + exists: { + field: 'container.id', + }, + }, + ]); + + expect(bool?.should).toEqual([ + { exists: { field: 'kubernetes.container.id' } }, + { exists: { field: 'kubernetes.pod.uid' } }, + { exists: { field: 'kubernetes.node.name' } }, + { exists: { field: 'host.hostname' } }, + ]); + }); + + it('should correctly include an EAN filter as a container ID term query', async () => { + const mockContainerId = '123abc'; + + await getContainers({ + ...baseOptions, + from: 'now-1h', + elasticsearchClient: esClientMock, + savedObjectsClient: soClientMock, + filters: { + ean: `container:${mockContainerId}`, + }, + }); + + const dsl = esClientMock.search.mock.lastCall?.[0] as SearchRequest | undefined; + const { bool } = dsl?.query || {}; + expect(bool).toBeDefined(); + + expect(bool?.must).toEqual( + expect.arrayContaining([ + { + exists: { + field: 'container.id', + }, + }, + { + term: { + 'container.id': mockContainerId, + }, + }, + ]) + ); + }); + + it('should not query ES and return empty if filtering on non-container EAN', async () => { + const mockId = 'some-id-123'; + + const result = await getContainers({ + ...baseOptions, + from: 'now-1h', + elasticsearchClient: esClientMock, + savedObjectsClient: soClientMock, + filters: { + ean: `pod:${mockId}`, + }, + }); + + expect(esClientMock.search).toHaveBeenCalledTimes(0); + expect(result).toEqual({ containers: [] }); + }); + + it('should throw an error when an invalid EAN is provided', async () => { + try { + await getContainers({ + ...baseOptions, + from: 'now-1h', + elasticsearchClient: esClientMock, + savedObjectsClient: soClientMock, + filters: { + ean: `invalid`, + }, + }); + } catch (error) { + const hasMessage = 'message' in error; + expect(hasMessage).toEqual(true); + expect(error.message).toEqual('invalid is not a valid EAN'); + } + + try { + await getContainers({ + ...baseOptions, + from: 'now-1h', + elasticsearchClient: esClientMock, + savedObjectsClient: soClientMock, + filters: { + ean: `invalid:toomany:colons`, + }, + }); + } catch (error) { + const hasMessage = 'message' in error; + expect(hasMessage).toEqual(true); + expect(error.message).toEqual('invalid:toomany:colons is not a valid EAN'); + } + }); + + it('should include a wildcard ID filter when an ID filter is provided with asterisks included', async () => { + const mockIdPattern = '*partial-id*'; + + await getContainers({ + ...baseOptions, + from: 'now-1h', + elasticsearchClient: esClientMock, + savedObjectsClient: soClientMock, + filters: { + id: mockIdPattern, + }, + }); + + const dsl = esClientMock.search.mock.lastCall?.[0] as SearchRequest | undefined; + const { bool } = dsl?.query || {}; + expect(bool).toBeDefined(); + + expect(bool?.must).toEqual( + expect.arrayContaining([ + { + exists: { + field: 'container.id', + }, + }, + { + wildcard: { + 'container.id': mockIdPattern, + }, + }, + ]) + ); + }); + + it('should include a term ID filter when an ID filter is provided without asterisks included', async () => { + const mockId = 'full-id'; + + await getContainers({ + ...baseOptions, + from: 'now-1h', + elasticsearchClient: esClientMock, + savedObjectsClient: soClientMock, + filters: { + id: mockId, + }, + }); + + const dsl = esClientMock.search.mock.lastCall?.[0] as SearchRequest | undefined; + const { bool } = dsl?.query || {}; + expect(bool).toBeDefined(); + + expect(bool?.must).toEqual( + expect.arrayContaining([ + { + exists: { + field: 'container.id', + }, + }, + { + term: { + 'container.id': mockId, + }, + }, + ]) + ); + }); + + it('should include a term filter for cloud filters', async () => { + const mockCloudProvider = 'gcp'; + const mockCloudRegion = 'us-central-1'; + + await getContainers({ + ...baseOptions, + from: 'now-1h', + elasticsearchClient: esClientMock, + savedObjectsClient: soClientMock, + filters: { + 'cloud.provider': mockCloudProvider, + 'cloud.region': mockCloudRegion, + }, + }); + + const dsl = esClientMock.search.mock.lastCall?.[0] as SearchRequest | undefined; + const { bool } = dsl?.query || {}; + expect(bool).toBeDefined(); + + expect(bool?.must).toEqual( + expect.arrayContaining([ + { + exists: { + field: 'container.id', + }, + }, + { + term: { + 'cloud.provider': mockCloudProvider, + }, + }, + { + term: { + 'cloud.region': mockCloudRegion, + }, + }, + ]) + ); + }); + + it('should reject with 400 for invalid "from" date', () => { + return expectToThrowValidationErrorWithStatusCode( + () => + getContainers({ + ...baseOptions, + from: 'now-1zz', + to: 'now-3d', + elasticsearchClient: esClientMock, + savedObjectsClient: soClientMock, + }), + { statusCode: 400 } + ); + }); + + it('should reject with 400 for invalid "to" date', () => { + return expectToThrowValidationErrorWithStatusCode( + () => + getContainers({ + ...baseOptions, + from: 'now-5d', + to: 'now-3fe', + elasticsearchClient: esClientMock, + savedObjectsClient: soClientMock, + }), + { statusCode: 400 } + ); + }); + + it('should reject with 400 when "from" is a date that is after "to"', () => { + return expectToThrowValidationErrorWithStatusCode( + () => + getContainers({ + ...baseOptions, + from: 'now', + to: 'now-5d', + elasticsearchClient: esClientMock, + savedObjectsClient: soClientMock, + }), + { statusCode: 400 } + ); + }); + + it('should reject with 400 when "from" is in the future', () => { + return expectToThrowValidationErrorWithStatusCode( + () => + getContainers({ + ...baseOptions, + from: 'now+1d', + elasticsearchClient: esClientMock, + savedObjectsClient: soClientMock, + }), + { statusCode: 400 } + ); + }); +}); diff --git a/x-pack/plugins/asset_manager/server/lib/accessors/containers/get_containers.ts b/x-pack/plugins/asset_manager/server/lib/accessors/containers/get_containers.ts new file mode 100644 index 0000000000000..c3c11bc375a84 --- /dev/null +++ b/x-pack/plugins/asset_manager/server/lib/accessors/containers/get_containers.ts @@ -0,0 +1,91 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license 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'; +import { Asset } from '../../../../common/types_api'; +import { GetContainersOptionsPublic } from '../../../../common/types_client'; +import { + AssetClientDependencies, + AssetClientOptionsWithInjectedValues, +} from '../../asset_client_types'; +import { parseEan } from '../../parse_ean'; +import { collectContainers } from '../../collectors'; +import { validateStringDateRange } from '../../validators/validate_date_range'; + +export type GetContainersOptions = GetContainersOptionsPublic & AssetClientDependencies; +export type GetContainersOptionsInjected = + AssetClientOptionsWithInjectedValues; + +export async function getContainers( + options: GetContainersOptionsInjected +): Promise<{ containers: Asset[] }> { + validateStringDateRange(options.from, options.to); + + const metricsIndices = await options.metricsClient.getMetricIndices({ + savedObjectsClient: options.savedObjectsClient, + }); + + const filters: QueryDslQueryContainer[] = []; + + if (options.filters?.ean) { + const ean = Array.isArray(options.filters.ean) ? options.filters.ean[0] : options.filters.ean; + const { kind, id } = parseEan(ean); + + // if EAN filter isn't targeting a container asset, we don't need to do this query + if (kind !== 'container') { + return { + containers: [], + }; + } + + filters.push({ + term: { + 'container.id': id, + }, + }); + } + + if (options.filters?.id) { + const fn = options.filters.id.includes('*') ? 'wildcard' : 'term'; + filters.push({ + [fn]: { + 'container.id': options.filters.id, + }, + }); + } + + if (options.filters?.['cloud.provider']) { + filters.push({ + term: { + 'cloud.provider': options.filters['cloud.provider'], + }, + }); + } + + if (options.filters?.['cloud.region']) { + filters.push({ + term: { + 'cloud.region': options.filters['cloud.region'], + }, + }); + } + + const { assets } = await collectContainers({ + client: options.elasticsearchClient, + from: options.from, + to: options.to || 'now', + filters, + sourceIndices: { + metrics: metricsIndices, + logs: options.sourceIndices.logs, + }, + }); + + return { + containers: assets, + }; +} diff --git a/x-pack/plugins/asset_manager/server/lib/accessors/hosts/get_hosts.test.ts b/x-pack/plugins/asset_manager/server/lib/accessors/hosts/get_hosts.test.ts new file mode 100644 index 0000000000000..147d7d7aed5b8 --- /dev/null +++ b/x-pack/plugins/asset_manager/server/lib/accessors/hosts/get_hosts.test.ts @@ -0,0 +1,357 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { elasticsearchClientMock } from '@kbn/core-elasticsearch-client-server-mocks'; +import { savedObjectsClientMock } from '@kbn/core-saved-objects-api-server-mocks'; +import { GetApmIndicesMethod } from '../../asset_client_types'; +import { getHosts } from './get_hosts'; +import { + createGetApmIndicesMock, + expectToThrowValidationErrorWithStatusCode, +} from '../../../test_utils'; +import { MetricsDataClient, MetricsDataClientMock } from '@kbn/metrics-data-access-plugin/server'; +import { SearchRequest } from '@elastic/elasticsearch/lib/api/types'; + +function createBaseOptions({ + getApmIndicesMock, + metricsDataClientMock, +}: { + getApmIndicesMock: GetApmIndicesMethod; + metricsDataClientMock: MetricsDataClient; +}) { + return { + sourceIndices: { + logs: 'my-logs*', + }, + getApmIndices: getApmIndicesMock, + metricsClient: metricsDataClientMock, + }; +} + +describe('getHosts', () => { + let getApmIndicesMock = createGetApmIndicesMock(); + let metricsDataClientMock = MetricsDataClientMock.create(); + let baseOptions = createBaseOptions({ getApmIndicesMock, metricsDataClientMock }); + let esClientMock = elasticsearchClientMock.createScopedClusterClient().asCurrentUser; + let soClientMock = savedObjectsClientMock.create(); + + function resetMocks() { + getApmIndicesMock = createGetApmIndicesMock(); + metricsDataClientMock = MetricsDataClientMock.create(); + baseOptions = createBaseOptions({ getApmIndicesMock, metricsDataClientMock }); + esClientMock = elasticsearchClientMock.createScopedClusterClient().asCurrentUser; + soClientMock = savedObjectsClientMock.create(); + } + + beforeEach(() => { + resetMocks(); + + // ES returns no results, just enough structure to not blow up + esClientMock.search.mockResolvedValueOnce({ + took: 1, + timed_out: false, + _shards: { + failed: 0, + successful: 1, + total: 1, + }, + hits: { + hits: [], + }, + }); + }); + + it('should query Elasticsearch correctly', async () => { + await getHosts({ + ...baseOptions, + from: 'now-5d', + to: 'now-3d', + elasticsearchClient: esClientMock, + savedObjectsClient: soClientMock, + }); + + expect(metricsDataClientMock.getMetricIndices).toHaveBeenCalledTimes(1); + expect(metricsDataClientMock.getMetricIndices).toHaveBeenCalledWith({ + savedObjectsClient: soClientMock, + }); + + const dsl = esClientMock.search.mock.lastCall?.[0] as SearchRequest | undefined; + const { bool } = dsl?.query || {}; + expect(bool).toBeDefined(); + + expect(bool?.filter).toEqual([ + { + range: { + '@timestamp': { + gte: 'now-5d', + lte: 'now-3d', + }, + }, + }, + ]); + + expect(bool?.must).toEqual([ + { + exists: { + field: 'host.hostname', + }, + }, + ]); + + expect(bool?.should).toEqual([ + { exists: { field: 'kubernetes.node.name' } }, + { exists: { field: 'kubernetes.pod.uid' } }, + { exists: { field: 'container.id' } }, + { exists: { field: 'cloud.provider' } }, + ]); + }); + + it('should correctly include an EAN filter as a hostname term query', async () => { + const mockHostName = 'some-hostname-123'; + + await getHosts({ + ...baseOptions, + from: 'now-1h', + elasticsearchClient: esClientMock, + savedObjectsClient: soClientMock, + filters: { + ean: `host:${mockHostName}`, + }, + }); + + const dsl = esClientMock.search.mock.lastCall?.[0] as SearchRequest | undefined; + const { bool } = dsl?.query || {}; + expect(bool).toBeDefined(); + + expect(bool?.must).toEqual( + expect.arrayContaining([ + { + exists: { + field: 'host.hostname', + }, + }, + { + term: { + 'host.hostname': mockHostName, + }, + }, + ]) + ); + }); + + it('should not query ES and return empty if filtering on non-host EAN', async () => { + const mockId = 'some-id-123'; + + const result = await getHosts({ + ...baseOptions, + from: 'now-1h', + elasticsearchClient: esClientMock, + savedObjectsClient: soClientMock, + filters: { + ean: `container:${mockId}`, + }, + }); + + expect(esClientMock.search).toHaveBeenCalledTimes(0); + expect(result).toEqual({ hosts: [] }); + }); + + it('should throw an error when an invalid EAN is provided', async () => { + try { + await getHosts({ + ...baseOptions, + from: 'now-1h', + elasticsearchClient: esClientMock, + savedObjectsClient: soClientMock, + filters: { + ean: `invalid`, + }, + }); + } catch (error) { + const hasMessage = 'message' in error; + expect(hasMessage).toEqual(true); + expect(error.message).toEqual('invalid is not a valid EAN'); + } + + try { + await getHosts({ + ...baseOptions, + from: 'now-1h', + elasticsearchClient: esClientMock, + savedObjectsClient: soClientMock, + filters: { + ean: `invalid:toomany:colons`, + }, + }); + } catch (error) { + const hasMessage = 'message' in error; + expect(hasMessage).toEqual(true); + expect(error.message).toEqual('invalid:toomany:colons is not a valid EAN'); + } + }); + + it('should include a wildcard ID filter when an ID filter is provided with asterisks included', async () => { + const mockIdPattern = '*partial-id*'; + + await getHosts({ + ...baseOptions, + from: 'now-1h', + elasticsearchClient: esClientMock, + savedObjectsClient: soClientMock, + filters: { + id: mockIdPattern, + }, + }); + + const dsl = esClientMock.search.mock.lastCall?.[0] as SearchRequest | undefined; + const { bool } = dsl?.query || {}; + expect(bool).toBeDefined(); + + expect(bool?.must).toEqual( + expect.arrayContaining([ + { + exists: { + field: 'host.hostname', + }, + }, + { + wildcard: { + 'host.hostname': mockIdPattern, + }, + }, + ]) + ); + }); + + it('should include a term ID filter when an ID filter is provided without asterisks included', async () => { + const mockId = 'full-id'; + + await getHosts({ + ...baseOptions, + from: 'now-1h', + elasticsearchClient: esClientMock, + savedObjectsClient: soClientMock, + filters: { + id: mockId, + }, + }); + + const dsl = esClientMock.search.mock.lastCall?.[0] as SearchRequest | undefined; + const { bool } = dsl?.query || {}; + expect(bool).toBeDefined(); + + expect(bool?.must).toEqual( + expect.arrayContaining([ + { + exists: { + field: 'host.hostname', + }, + }, + { + term: { + 'host.hostname': mockId, + }, + }, + ]) + ); + }); + + it('should include a term filter for cloud filters', async () => { + const mockCloudProvider = 'gcp'; + const mockCloudRegion = 'us-central-1'; + + await getHosts({ + ...baseOptions, + from: 'now-1h', + elasticsearchClient: esClientMock, + savedObjectsClient: soClientMock, + filters: { + 'cloud.provider': mockCloudProvider, + 'cloud.region': mockCloudRegion, + }, + }); + + const dsl = esClientMock.search.mock.lastCall?.[0] as SearchRequest | undefined; + const { bool } = dsl?.query || {}; + expect(bool).toBeDefined(); + + expect(bool?.must).toEqual( + expect.arrayContaining([ + { + exists: { + field: 'host.hostname', + }, + }, + { + term: { + 'cloud.provider': mockCloudProvider, + }, + }, + { + term: { + 'cloud.region': mockCloudRegion, + }, + }, + ]) + ); + }); + + it('should reject with 400 for invalid "from" date', () => { + return expectToThrowValidationErrorWithStatusCode( + () => + getHosts({ + ...baseOptions, + from: 'now-1zz', + to: 'now-3d', + elasticsearchClient: esClientMock, + savedObjectsClient: soClientMock, + }), + { statusCode: 400 } + ); + }); + + it('should reject with 400 for invalid "to" date', () => { + return expectToThrowValidationErrorWithStatusCode( + () => + getHosts({ + ...baseOptions, + from: 'now-5d', + to: 'now-3fe', + elasticsearchClient: esClientMock, + savedObjectsClient: soClientMock, + }), + { statusCode: 400 } + ); + }); + + it('should reject with 400 when "from" is a date that is after "to"', () => { + return expectToThrowValidationErrorWithStatusCode( + () => + getHosts({ + ...baseOptions, + from: 'now', + to: 'now-5d', + elasticsearchClient: esClientMock, + savedObjectsClient: soClientMock, + }), + { statusCode: 400 } + ); + }); + + it('should reject with 400 when "from" is in the future', () => { + return expectToThrowValidationErrorWithStatusCode( + () => + getHosts({ + ...baseOptions, + from: 'now+1d', + elasticsearchClient: esClientMock, + savedObjectsClient: soClientMock, + }), + { statusCode: 400 } + ); + }); +}); diff --git a/x-pack/plugins/asset_manager/server/lib/accessors/hosts/get_hosts.ts b/x-pack/plugins/asset_manager/server/lib/accessors/hosts/get_hosts.ts index 632b234b5512f..62c4fe404c0a5 100644 --- a/x-pack/plugins/asset_manager/server/lib/accessors/hosts/get_hosts.ts +++ b/x-pack/plugins/asset_manager/server/lib/accessors/hosts/get_hosts.ts @@ -5,6 +5,7 @@ * 2.0. */ +import { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/types'; import { Asset } from '../../../../common/types_api'; import { collectHosts } from '../../collectors/hosts'; import { GetHostsOptionsPublic } from '../../../../common/types_client'; @@ -12,24 +13,75 @@ import { AssetClientDependencies, AssetClientOptionsWithInjectedValues, } from '../../asset_client_types'; +import { parseEan } from '../../parse_ean'; +import { validateStringDateRange } from '../../validators/validate_date_range'; export type GetHostsOptions = GetHostsOptionsPublic & AssetClientDependencies; export type GetHostsOptionsInjected = AssetClientOptionsWithInjectedValues; export async function getHosts(options: GetHostsOptionsInjected): Promise<{ hosts: Asset[] }> { + validateStringDateRange(options.from, options.to); + const metricsIndices = await options.metricsClient.getMetricIndices({ savedObjectsClient: options.savedObjectsClient, }); + const filters: QueryDslQueryContainer[] = []; + + if (options.filters?.ean) { + const ean = Array.isArray(options.filters.ean) ? options.filters.ean[0] : options.filters.ean; + const { kind, id } = parseEan(ean); + + // if EAN filter isn't targeting a host asset, we don't need to do this query + if (kind !== 'host') { + return { + hosts: [], + }; + } + + filters.push({ + term: { + 'host.hostname': id, + }, + }); + } + + if (options.filters?.id) { + const fn = options.filters.id.includes('*') ? 'wildcard' : 'term'; + filters.push({ + [fn]: { + 'host.hostname': options.filters.id, + }, + }); + } + + if (options.filters?.['cloud.provider']) { + filters.push({ + term: { + 'cloud.provider': options.filters['cloud.provider'], + }, + }); + } + + if (options.filters?.['cloud.region']) { + filters.push({ + term: { + 'cloud.region': options.filters['cloud.region'], + }, + }); + } + const { assets } = await collectHosts({ client: options.elasticsearchClient, from: options.from, to: options.to || 'now', + filters, sourceIndices: { metrics: metricsIndices, logs: options.sourceIndices.logs, }, }); + return { hosts: assets, }; diff --git a/x-pack/plugins/asset_manager/server/lib/accessors/services/get_services.ts b/x-pack/plugins/asset_manager/server/lib/accessors/services/get_services.ts index 2df13930e2ed7..2831c5d58987f 100644 --- a/x-pack/plugins/asset_manager/server/lib/accessors/services/get_services.ts +++ b/x-pack/plugins/asset_manager/server/lib/accessors/services/get_services.ts @@ -13,6 +13,7 @@ import { AssetClientDependencies, AssetClientOptionsWithInjectedValues, } from '../../asset_client_types'; +import { validateStringDateRange } from '../../validators/validate_date_range'; export type GetServicesOptions = GetServicesOptionsPublic & AssetClientDependencies; export type GetServicesOptionsInjected = AssetClientOptionsWithInjectedValues; @@ -20,6 +21,8 @@ export type GetServicesOptionsInjected = AssetClientOptionsWithInjectedValues { + validateStringDateRange(options.from, options.to); + const filters = []; if (options.parent) { diff --git a/x-pack/plugins/asset_manager/server/lib/asset_client.test.ts b/x-pack/plugins/asset_manager/server/lib/asset_client.test.ts index a9bd5791bc51a..9ed5fb536251c 100644 --- a/x-pack/plugins/asset_manager/server/lib/asset_client.test.ts +++ b/x-pack/plugins/asset_manager/server/lib/asset_client.test.ts @@ -16,41 +16,7 @@ import { SearchRequest } from '@elastic/elasticsearch/lib/api/types'; import { SavedObjectsClientContract } from '@kbn/core-saved-objects-api-server'; import { AssetsValidationError } from './validators/validation_error'; import { GetApmIndicesMethod } from './asset_client_types'; - -// Helper function allows test to verify error was thrown, -// verify error is of the right class type, and error has -// the expected metadata such as statusCode on it -function expectToThrowValidationErrorWithStatusCode( - testFn: () => Promise, - expectedError: Partial = {} -) { - return expect(async () => { - try { - return await testFn(); - } catch (error: any) { - if (error instanceof AssetsValidationError) { - if (expectedError.statusCode) { - expect(error.statusCode).toEqual(expectedError.statusCode); - } - if (expectedError.message) { - expect(error.message).toEqual(expect.stringContaining(expectedError.message)); - } - } - throw error; - } - }).rejects.toThrow(AssetsValidationError); -} - -function createGetApmIndicesMock(): jest.Mocked { - return jest.fn(async (client: SavedObjectsClientContract) => ({ - transaction: 'apm-mock-transaction-indices', - span: 'apm-mock-span-indices', - error: 'apm-mock-error-indices', - metric: 'apm-mock-metric-indices', - onboarding: 'apm-mock-onboarding-indices', - sourcemap: 'apm-mock-sourcemap-indices', - })); -} +import { createGetApmIndicesMock, expectToThrowValidationErrorWithStatusCode } from '../test_utils'; function createAssetClient( metricsDataClient: MetricsDataClient, @@ -100,112 +66,7 @@ describe('Server assets client', () => { }); }); - describe('getHosts', () => { - it('should query Elasticsearch correctly', async () => { - const client = createAssetClient(metricsDataClientMock, getApmIndicesMock); - - await client.getHosts({ - from: 'now-5d', - to: 'now-3d', - elasticsearchClient: esClientMock, - savedObjectsClient: soClientMock, - }); - - expect(metricsDataClientMock.getMetricIndices).toHaveBeenCalledTimes(1); - expect(metricsDataClientMock.getMetricIndices).toHaveBeenCalledWith({ - savedObjectsClient: soClientMock, - }); - - const dsl = esClientMock.search.mock.lastCall?.[0] as SearchRequest | undefined; - const { bool } = dsl?.query || {}; - expect(bool).toBeDefined(); - - expect(bool?.filter).toEqual([ - { - range: { - '@timestamp': { - gte: 'now-5d', - lte: 'now-3d', - }, - }, - }, - ]); - - expect(bool?.must).toEqual([ - { - exists: { - field: 'host.hostname', - }, - }, - ]); - - expect(bool?.should).toEqual([ - { exists: { field: 'kubernetes.node.name' } }, - { exists: { field: 'kubernetes.pod.uid' } }, - { exists: { field: 'container.id' } }, - ]); - }); - - it('should reject with 400 for invalid "from" date', () => { - const client = createAssetClient(metricsDataClientMock, getApmIndicesMock); - - return expectToThrowValidationErrorWithStatusCode( - () => - client.getHosts({ - from: 'now-1zz', - to: 'now-3d', - elasticsearchClient: esClientMock, - savedObjectsClient: soClientMock, - }), - { statusCode: 400 } - ); - }); - - it('should reject with 400 for invalid "to" date', () => { - const client = createAssetClient(metricsDataClientMock, getApmIndicesMock); - - return expectToThrowValidationErrorWithStatusCode( - () => - client.getHosts({ - from: 'now-5d', - to: 'now-3fe', - elasticsearchClient: esClientMock, - savedObjectsClient: soClientMock, - }), - { statusCode: 400 } - ); - }); - - it('should reject with 400 when "from" is a date that is after "to"', () => { - const client = createAssetClient(metricsDataClientMock, getApmIndicesMock); - - return expectToThrowValidationErrorWithStatusCode( - () => - client.getHosts({ - from: 'now', - to: 'now-5d', - elasticsearchClient: esClientMock, - savedObjectsClient: soClientMock, - }), - { statusCode: 400 } - ); - }); - - it('should reject with 400 when "from" is in the future', () => { - const client = createAssetClient(metricsDataClientMock, getApmIndicesMock); - - return expectToThrowValidationErrorWithStatusCode( - () => - client.getHosts({ - from: 'now+1d', - elasticsearchClient: esClientMock, - savedObjectsClient: soClientMock, - }), - { statusCode: 400 } - ); - }); - }); - + // TODO: Move this block to the get_services accessor folder describe('getServices', () => { it('should query Elasticsearch correctly', async () => { const client = createAssetClient(metricsDataClientMock, getApmIndicesMock); diff --git a/x-pack/plugins/asset_manager/server/lib/asset_client.ts b/x-pack/plugins/asset_manager/server/lib/asset_client.ts index 0349d50b7fd21..a7aad8f6a01c4 100644 --- a/x-pack/plugins/asset_manager/server/lib/asset_client.ts +++ b/x-pack/plugins/asset_manager/server/lib/asset_client.ts @@ -6,10 +6,10 @@ */ import { Asset } from '../../common/types_api'; +import { getContainers, GetContainersOptions } from './accessors/containers/get_containers'; import { getHosts, GetHostsOptions } from './accessors/hosts/get_hosts'; import { getServices, GetServicesOptions } from './accessors/services/get_services'; import { AssetClientBaseOptions, AssetClientOptionsWithInjectedValues } from './asset_client_types'; -import { validateStringDateRange } from './validators/validate_date_range'; export class AssetClient { constructor(private baseOptions: AssetClientBaseOptions) {} @@ -22,14 +22,17 @@ export class AssetClient { } async getHosts(options: GetHostsOptions): Promise<{ hosts: Asset[] }> { - validateStringDateRange(options.from, options.to); const withInjected = this.injectOptions(options); return await getHosts(withInjected); } async getServices(options: GetServicesOptions): Promise<{ services: Asset[] }> { - validateStringDateRange(options.from, options.to); const withInjected = this.injectOptions(options); return await getServices(withInjected); } + + async getContainers(options: GetContainersOptions): Promise<{ containers: Asset[] }> { + const withInjected = this.injectOptions(options); + return await getContainers(withInjected); + } } diff --git a/x-pack/plugins/asset_manager/server/lib/collectors/containers.ts b/x-pack/plugins/asset_manager/server/lib/collectors/containers.ts index a96a89ea8a399..c9d0e8379dbdd 100644 --- a/x-pack/plugins/asset_manager/server/lib/collectors/containers.ts +++ b/x-pack/plugins/asset_manager/server/lib/collectors/containers.ts @@ -14,12 +14,15 @@ export async function collectContainers({ from, to, sourceIndices, + filters = [], afterKey, }: CollectorOptions) { if (!sourceIndices?.metrics || !sourceIndices?.logs) { throw new Error('missing required metrics/logs indices'); } + const musts = [...filters, { exists: { field: 'container.id' } }]; + const { metrics, logs } = sourceIndices; const dsl: estypes.SearchRequest = { index: [metrics, logs], @@ -48,6 +51,7 @@ export async function collectContainers({ }, }, ], + must: musts, should: [ { exists: { field: 'kubernetes.container.id' } }, { exists: { field: 'kubernetes.pod.uid' } }, diff --git a/x-pack/plugins/asset_manager/server/lib/collectors/hosts.ts b/x-pack/plugins/asset_manager/server/lib/collectors/hosts.ts index 750c9fdac21b9..a082cafc8546c 100644 --- a/x-pack/plugins/asset_manager/server/lib/collectors/hosts.ts +++ b/x-pack/plugins/asset_manager/server/lib/collectors/hosts.ts @@ -15,12 +15,15 @@ export async function collectHosts({ to, sourceIndices, afterKey, + filters = [], }: CollectorOptions) { if (!sourceIndices?.metrics || !sourceIndices?.logs) { throw new Error('missing required metrics/logs indices'); } const { metrics, logs } = sourceIndices; + + const musts = [...filters, { exists: { field: 'host.hostname' } }]; const dsl: estypes.SearchRequest = { index: [metrics, logs], size: QUERY_MAX_SIZE, @@ -47,11 +50,12 @@ export async function collectHosts({ }, }, ], - must: [{ exists: { field: 'host.hostname' } }], + must: musts, should: [ { exists: { field: 'kubernetes.node.name' } }, { exists: { field: 'kubernetes.pod.uid' } }, { exists: { field: 'container.id' } }, + { exists: { field: 'cloud.provider' } }, ], }, }, diff --git a/x-pack/plugins/asset_manager/server/lib/get_all_related_assets.test.ts b/x-pack/plugins/asset_manager/server/lib/get_all_related_assets.test.ts deleted file mode 100644 index 47006590a9238..0000000000000 --- a/x-pack/plugins/asset_manager/server/lib/get_all_related_assets.test.ts +++ /dev/null @@ -1,570 +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. - */ - -jest.mock('./get_assets', () => ({ getAssets: jest.fn() })); -jest.mock('./get_indirectly_related_assets', () => ({ getIndirectlyRelatedAssets: jest.fn() })); - -import { elasticsearchClientMock } from '@kbn/core-elasticsearch-client-server-mocks'; -import { v4 as uuid } from 'uuid'; -import { AssetWithoutTimestamp } from '../../common/types_api'; -import { getAssets } from './get_assets'; // Mocked -import { getIndirectlyRelatedAssets } from './get_indirectly_related_assets'; // Mocked -import { getAllRelatedAssets } from './get_all_related_assets'; - -const esClientMock = elasticsearchClientMock.createScopedClusterClient().asCurrentUser; - -describe('getAllRelatedAssets', () => { - beforeEach(() => { - (getAssets as jest.Mock).mockReset(); - (getIndirectlyRelatedAssets as jest.Mock).mockReset(); - }); - - it('throws if it cannot find the primary asset', async () => { - const primaryAsset: AssetWithoutTimestamp = { - 'asset.ean': 'primary-which-does-not-exist', - 'asset.type': 'k8s.pod', - 'asset.kind': 'pod', - 'asset.id': uuid(), - }; - - // Mock that we cannot find the primary - (getAssets as jest.Mock).mockResolvedValueOnce([]); - // Ensure maxDistance is respected - (getAssets as jest.Mock).mockRejectedValueOnce(new Error('Should respect maxDistance')); - (getIndirectlyRelatedAssets as jest.Mock).mockRejectedValueOnce( - new Error('Should respect maxDistance') - ); - - await expect( - getAllRelatedAssets(esClientMock, { - ean: primaryAsset['asset.ean'], - relation: 'ancestors', - from: new Date().toISOString(), - maxDistance: 1, - size: 10, - }) - ).rejects.toThrow( - `Asset with ean (${primaryAsset['asset.ean']}) not found in the provided time range` - ); - }); - - it('returns only the primary if it does not have any ancestors', async () => { - const primaryAssetWithoutParents: AssetWithoutTimestamp = { - 'asset.ean': 'primary-ean', - 'asset.type': 'k8s.pod', - 'asset.kind': 'pod', - 'asset.id': uuid(), - 'asset.parents': [], - }; - - (getAssets as jest.Mock).mockResolvedValueOnce([primaryAssetWithoutParents]); - // Distance 1 - (getIndirectlyRelatedAssets as jest.Mock).mockResolvedValueOnce([]); - // Ensure maxDistance is respected - (getAssets as jest.Mock).mockRejectedValueOnce(new Error('Should respect maxDistance')); - (getIndirectlyRelatedAssets as jest.Mock).mockRejectedValueOnce( - new Error('Should respect maxDistance') - ); - - await expect( - getAllRelatedAssets(esClientMock, { - ean: primaryAssetWithoutParents['asset.ean'], - from: new Date().toISOString(), - relation: 'ancestors', - maxDistance: 1, - size: 10, - }) - ).resolves.toStrictEqual({ - primary: primaryAssetWithoutParents, - ancestors: [], - }); - }); - - it('returns the primary and a directly referenced parent', async () => { - const parentAsset: AssetWithoutTimestamp = { - 'asset.ean': 'parent-ean', - 'asset.type': 'k8s.pod', - 'asset.kind': 'pod', - 'asset.id': uuid(), - }; - - const primaryAssetWithDirectParent: AssetWithoutTimestamp = { - 'asset.ean': 'primary-ean', - 'asset.type': 'k8s.pod', - 'asset.kind': 'pod', - 'asset.id': uuid(), - 'asset.parents': [parentAsset['asset.ean']], - }; - - // Primary - (getAssets as jest.Mock).mockResolvedValueOnce([primaryAssetWithDirectParent]); - // Distance 1 - (getAssets as jest.Mock).mockResolvedValueOnce([parentAsset]); - (getIndirectlyRelatedAssets as jest.Mock).mockResolvedValueOnce([]); - // Ensure maxDistance is respected - (getAssets as jest.Mock).mockRejectedValueOnce(new Error('Should respect maxDistance')); - (getIndirectlyRelatedAssets as jest.Mock).mockRejectedValueOnce( - new Error('Should respect maxDistance') - ); - - await expect( - getAllRelatedAssets(esClientMock, { - ean: primaryAssetWithDirectParent['asset.ean'], - from: new Date().toISOString(), - relation: 'ancestors', - maxDistance: 1, - size: 10, - }) - ).resolves.toStrictEqual({ - primary: primaryAssetWithDirectParent, - ancestors: [ - { - ...parentAsset, - distance: 1, - }, - ], - }); - }); - - it('returns the primary and an indirectly referenced parent', async () => { - const primaryAssetWithIndirectParent: AssetWithoutTimestamp = { - 'asset.ean': 'primary-ean', - 'asset.type': 'k8s.pod', - 'asset.kind': 'pod', - 'asset.id': uuid(), - 'asset.parents': [], - }; - - const parentAsset: AssetWithoutTimestamp = { - 'asset.ean': 'primary-ean', - 'asset.type': 'k8s.pod', - 'asset.kind': 'pod', - 'asset.id': uuid(), - 'asset.children': [primaryAssetWithIndirectParent['asset.ean']], - }; - - // Primary - (getAssets as jest.Mock).mockResolvedValueOnce([primaryAssetWithIndirectParent]); - // Distance 1 - (getAssets as jest.Mock).mockResolvedValueOnce([]); - (getIndirectlyRelatedAssets as jest.Mock).mockResolvedValueOnce([parentAsset]); - // Ensure maxDistance is respected - (getAssets as jest.Mock).mockRejectedValueOnce(new Error('Should respect maxDistance')); - (getIndirectlyRelatedAssets as jest.Mock).mockRejectedValueOnce( - new Error('Should respect maxDistance') - ); - - await expect( - getAllRelatedAssets(esClientMock, { - ean: primaryAssetWithIndirectParent['asset.ean'], - from: new Date().toISOString(), - relation: 'ancestors', - maxDistance: 1, - size: 10, - }) - ).resolves.toStrictEqual({ - primary: primaryAssetWithIndirectParent, - ancestors: [ - { - ...parentAsset, - distance: 1, - }, - ], - }); - }); - - it('returns the primary and all distance 1 parents', async () => { - const directlyReferencedParent: AssetWithoutTimestamp = { - 'asset.ean': 'directly-referenced-parent-ean', - 'asset.type': 'k8s.pod', - 'asset.kind': 'pod', - 'asset.id': uuid(), - 'asset.children': [], - }; - - const primaryAsset: AssetWithoutTimestamp = { - 'asset.ean': 'primary-ean', - 'asset.type': 'k8s.pod', - 'asset.kind': 'pod', - 'asset.id': uuid(), - 'asset.parents': [directlyReferencedParent['asset.ean']], - }; - - const indirectlyReferencedParent: AssetWithoutTimestamp = { - 'asset.ean': 'indirectly-referenced-parent-ean', - 'asset.type': 'k8s.pod', - 'asset.kind': 'pod', - 'asset.id': uuid(), - 'asset.children': [primaryAsset['asset.ean']], - }; - - // Primary - (getAssets as jest.Mock).mockResolvedValueOnce([primaryAsset]); - // Distance 1 - (getAssets as jest.Mock).mockResolvedValueOnce([directlyReferencedParent]); - (getIndirectlyRelatedAssets as jest.Mock).mockResolvedValueOnce([indirectlyReferencedParent]); - // Ensure maxDistance is respected - (getAssets as jest.Mock).mockRejectedValueOnce(new Error('Should respect maxDistance')); - (getIndirectlyRelatedAssets as jest.Mock).mockRejectedValueOnce( - new Error('Should respect maxDistance') - ); - - await expect( - getAllRelatedAssets(esClientMock, { - ean: primaryAsset['asset.ean'], - from: new Date().toISOString(), - relation: 'ancestors', - maxDistance: 1, - size: 10, - }) - ).resolves.toStrictEqual({ - primary: primaryAsset, - ancestors: [ - { - ...directlyReferencedParent, - distance: 1, - }, - { - ...indirectlyReferencedParent, - distance: 1, - }, - ], - }); - }); - - it('returns the primary and one parent even with a two way relation defined', async () => { - const parentAsset: AssetWithoutTimestamp = { - 'asset.ean': 'parent-ean', - 'asset.type': 'k8s.pod', - 'asset.kind': 'pod', - 'asset.id': uuid(), - }; - - const primaryAsset: AssetWithoutTimestamp = { - 'asset.ean': 'primary-ean', - 'asset.type': 'k8s.pod', - 'asset.kind': 'pod', - 'asset.id': uuid(), - }; - - primaryAsset['asset.parents'] = [parentAsset['asset.ean']]; - parentAsset['asset.children'] = [primaryAsset['asset.ean']]; - - // Primary - (getAssets as jest.Mock).mockResolvedValueOnce([primaryAsset]); - // Distance 1 - (getAssets as jest.Mock).mockResolvedValueOnce([parentAsset]); - // Code should filter out any directly referenced parent from the indirectly referenced parents query - (getIndirectlyRelatedAssets as jest.Mock).mockResolvedValueOnce([]); - // Ensure maxDistance is respected - (getAssets as jest.Mock).mockRejectedValueOnce(new Error('Should respect maxDistance')); - (getIndirectlyRelatedAssets as jest.Mock).mockRejectedValueOnce( - new Error('Should respect maxDistance') - ); - - await expect( - getAllRelatedAssets(esClientMock, { - ean: primaryAsset['asset.ean'], - from: new Date().toISOString(), - relation: 'ancestors', - maxDistance: 1, - size: 10, - }) - ).resolves.toStrictEqual({ - primary: primaryAsset, - ancestors: [ - { - ...parentAsset, - distance: 1, - }, - ], - }); - }); - - it('returns relations from 5 jumps', async () => { - const distance6Parent: AssetWithoutTimestamp = { - 'asset.ean': 'parent-5-ean', - 'asset.type': 'k8s.pod', - 'asset.kind': 'pod', - 'asset.id': uuid(), - }; - - const distance5Parent: AssetWithoutTimestamp = { - 'asset.ean': 'parent-5-ean', - 'asset.type': 'k8s.pod', - 'asset.kind': 'pod', - 'asset.id': uuid(), - 'asset.parents': [distance6Parent['asset.ean']], - }; - - const distance4Parent: AssetWithoutTimestamp = { - 'asset.ean': 'parent-4-ean', - 'asset.type': 'k8s.pod', - 'asset.kind': 'pod', - 'asset.id': uuid(), - 'asset.parents': [distance5Parent['asset.ean']], - }; - - const distance3Parent: AssetWithoutTimestamp = { - 'asset.ean': 'parent-3-ean', - 'asset.type': 'k8s.pod', - 'asset.kind': 'pod', - 'asset.id': uuid(), - 'asset.parents': [distance4Parent['asset.ean']], - }; - - const distance2Parent: AssetWithoutTimestamp = { - 'asset.ean': 'parent-2-ean', - 'asset.type': 'k8s.pod', - 'asset.kind': 'pod', - 'asset.id': uuid(), - 'asset.parents': [distance3Parent['asset.ean']], - }; - - const distance1Parent: AssetWithoutTimestamp = { - 'asset.ean': 'parent-1-ean', - 'asset.type': 'k8s.pod', - 'asset.kind': 'pod', - 'asset.id': uuid(), - 'asset.parents': [distance2Parent['asset.ean']], - }; - - const primaryAsset: AssetWithoutTimestamp = { - 'asset.ean': 'primary-ean', - 'asset.type': 'k8s.pod', - 'asset.kind': 'pod', - 'asset.id': uuid(), - 'asset.parents': [distance1Parent['asset.ean']], - }; - - // Only using directly referenced parents - (getIndirectlyRelatedAssets as jest.Mock).mockResolvedValue([]); - - // Primary - (getAssets as jest.Mock).mockResolvedValueOnce([primaryAsset]); - // Distance 1 - (getAssets as jest.Mock).mockResolvedValueOnce([distance1Parent]); - // Distance 2 - (getAssets as jest.Mock).mockResolvedValueOnce([distance2Parent]); - // Distance 3 - (getAssets as jest.Mock).mockResolvedValueOnce([distance3Parent]); - // Distance 4 - (getAssets as jest.Mock).mockResolvedValueOnce([distance4Parent]); - // Distance 5 - (getAssets as jest.Mock).mockResolvedValueOnce([distance5Parent]); - // Should not exceed maxDistance - (getAssets as jest.Mock).mockRejectedValueOnce(new Error('Should respect maxDistance')); - - await expect( - getAllRelatedAssets(esClientMock, { - ean: primaryAsset['asset.ean'], - from: new Date().toISOString(), - relation: 'ancestors', - maxDistance: 5, - size: 10, - }) - ).resolves.toStrictEqual({ - primary: primaryAsset, - ancestors: [ - { - ...distance1Parent, - distance: 1, - }, - { - ...distance2Parent, - distance: 2, - }, - { - ...distance3Parent, - distance: 3, - }, - { - ...distance4Parent, - distance: 4, - }, - { - ...distance5Parent, - distance: 5, - }, - ], - }); - }); - - it('returns relations from only 3 jumps if there are no more parents', async () => { - const distance3Parent: AssetWithoutTimestamp = { - 'asset.ean': 'parent-3-ean', - 'asset.type': 'k8s.pod', - 'asset.kind': 'pod', - 'asset.id': uuid(), - }; - - const distance2Parent: AssetWithoutTimestamp = { - 'asset.ean': 'parent-2-ean', - 'asset.type': 'k8s.pod', - 'asset.kind': 'pod', - 'asset.id': uuid(), - 'asset.parents': [distance3Parent['asset.ean']], - }; - - const distance1Parent: AssetWithoutTimestamp = { - 'asset.ean': 'parent-1-ean', - 'asset.type': 'k8s.pod', - 'asset.kind': 'pod', - 'asset.id': uuid(), - 'asset.parents': [distance2Parent['asset.ean']], - }; - - const primaryAsset: AssetWithoutTimestamp = { - 'asset.ean': 'primary-ean', - 'asset.type': 'k8s.pod', - 'asset.kind': 'pod', - 'asset.id': uuid(), - 'asset.parents': [distance1Parent['asset.ean']], - }; - - // Only using directly referenced parents - (getIndirectlyRelatedAssets as jest.Mock).mockResolvedValue([]); - - // Primary - (getAssets as jest.Mock).mockResolvedValueOnce([primaryAsset]); - // Distance 1 - (getAssets as jest.Mock).mockResolvedValueOnce([distance1Parent]); - // Distance 2 - (getAssets as jest.Mock).mockResolvedValueOnce([distance2Parent]); - // Distance 3 - (getAssets as jest.Mock).mockResolvedValueOnce([distance3Parent]); - - await expect( - getAllRelatedAssets(esClientMock, { - ean: primaryAsset['asset.ean'], - from: new Date().toISOString(), - relation: 'ancestors', - maxDistance: 5, - size: 10, - }) - ).resolves.toStrictEqual({ - primary: primaryAsset, - ancestors: [ - { - ...distance1Parent, - distance: 1, - }, - { - ...distance2Parent, - distance: 2, - }, - { - ...distance3Parent, - distance: 3, - }, - ], - }); - }); - - it('returns relations by distance even if there are multiple parents in each jump', async () => { - const distance2ParentA: AssetWithoutTimestamp = { - 'asset.ean': 'parent-2-ean-a', - 'asset.type': 'k8s.pod', - 'asset.kind': 'pod', - 'asset.id': uuid(), - }; - - const distance2ParentB: AssetWithoutTimestamp = { - 'asset.ean': 'parent-2-ean-b', - 'asset.type': 'k8s.pod', - 'asset.kind': 'pod', - 'asset.id': uuid(), - }; - - const distance2ParentC: AssetWithoutTimestamp = { - 'asset.ean': 'parent-2-ean-c', - 'asset.type': 'k8s.pod', - 'asset.kind': 'pod', - 'asset.id': uuid(), - }; - - const distance2ParentD: AssetWithoutTimestamp = { - 'asset.ean': 'parent-2-ean-d', - 'asset.type': 'k8s.pod', - 'asset.kind': 'pod', - 'asset.id': uuid(), - }; - - const distance1ParentA: AssetWithoutTimestamp = { - 'asset.ean': 'parent-1-ean-a', - 'asset.type': 'k8s.pod', - 'asset.kind': 'pod', - 'asset.id': uuid(), - 'asset.parents': [distance2ParentA['asset.ean'], distance2ParentB['asset.ean']], - }; - - const distance1ParentB: AssetWithoutTimestamp = { - 'asset.ean': 'parent-1-ean-b', - 'asset.type': 'k8s.pod', - 'asset.kind': 'pod', - 'asset.id': uuid(), - 'asset.parents': [distance2ParentC['asset.ean'], distance2ParentD['asset.ean']], - }; - - const primaryAsset: AssetWithoutTimestamp = { - 'asset.ean': 'primary-ean', - 'asset.type': 'k8s.pod', - 'asset.kind': 'pod', - 'asset.id': uuid(), - 'asset.parents': [distance1ParentA['asset.ean'], distance1ParentB['asset.ean']], - }; - - // Only using directly referenced parents - (getIndirectlyRelatedAssets as jest.Mock).mockResolvedValue([]); - - // Primary - (getAssets as jest.Mock).mockResolvedValueOnce([primaryAsset]); - // Distance 1 - (getAssets as jest.Mock).mockResolvedValueOnce([distance1ParentA, distance1ParentB]); - // Distance 2 (the order matters) - (getAssets as jest.Mock).mockResolvedValueOnce([distance2ParentA, distance2ParentB]); - (getAssets as jest.Mock).mockResolvedValueOnce([distance2ParentC, distance2ParentD]); - - await expect( - getAllRelatedAssets(esClientMock, { - ean: primaryAsset['asset.ean'], - from: new Date().toISOString(), - relation: 'ancestors', - maxDistance: 5, - size: 10, - }) - ).resolves.toStrictEqual({ - primary: primaryAsset, - ancestors: [ - { - ...distance1ParentA, - distance: 1, - }, - { - ...distance1ParentB, - distance: 1, - }, - { - ...distance2ParentA, - distance: 2, - }, - { - ...distance2ParentB, - distance: 2, - }, - { - ...distance2ParentC, - distance: 2, - }, - { - ...distance2ParentD, - distance: 2, - }, - ], - }); - }); -}); diff --git a/x-pack/plugins/asset_manager/server/lib/get_all_related_assets.ts b/x-pack/plugins/asset_manager/server/lib/get_all_related_assets.ts deleted file mode 100644 index dddbb792b0979..0000000000000 --- a/x-pack/plugins/asset_manager/server/lib/get_all_related_assets.ts +++ /dev/null @@ -1,155 +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 { ElasticsearchClient } from '@kbn/core/server'; -import { flatten, without } from 'lodash'; -import { debug } from '../../common/debug_log'; -import { Asset, AssetType, AssetKind, Relation, RelationField } from '../../common/types_api'; -import { getAssets } from './get_assets'; -import { getIndirectlyRelatedAssets } from './get_indirectly_related_assets'; -import { AssetNotFoundError } from './errors'; -import { toArray } from './utils'; - -interface GetAllRelatedAssetsOptions { - ean: string; - from: string; - to?: string; - relation: Relation; - type?: AssetType[]; - kind?: AssetKind[]; - maxDistance: number; - size: number; -} - -export async function getAllRelatedAssets( - elasticsearchClient: ElasticsearchClient, - options: GetAllRelatedAssetsOptions -) { - // How to put size into this? - const { ean, from, to, relation, maxDistance, kind = [] } = options; - - const primary = await findPrimary(elasticsearchClient, { ean, from, to }); - - let assetsToFetch = [primary]; - let currentDistance = 1; - const relatedAssets = []; - while (currentDistance <= maxDistance) { - const queryOptions: FindRelatedAssetsOptions = { - relation, - from, - to, - visitedEans: [primary['asset.ean'], ...relatedAssets.map((asset) => asset['asset.ean'])], - }; - // if we enforce the kind filter before the last query we'll miss nodes with - // possible edges to the requested kind values - if (currentDistance === maxDistance && kind.length) { - queryOptions.kind = kind; - } - - const results = flatten( - await Promise.all( - assetsToFetch.map((asset) => findRelatedAssets(elasticsearchClient, asset, queryOptions)) - ) - ); - - if (results.length === 0) { - break; - } - - relatedAssets.push(...results.map(withDistance(currentDistance))); - - assetsToFetch = results; - currentDistance++; - } - - return { - primary, - [relation]: kind.length - ? relatedAssets.filter((asset) => asset['asset.kind'] && kind.includes(asset['asset.kind'])) - : relatedAssets, - }; -} - -async function findPrimary( - elasticsearchClient: ElasticsearchClient, - { ean, from, to }: Pick -): Promise { - const primaryResults = await getAssets({ - elasticsearchClient, - size: 1, - filters: { ean, from, to }, - }); - - if (primaryResults.length === 0) { - throw new AssetNotFoundError(ean); - } - - if (primaryResults.length > 1) { - throw new Error(`Illegal state: Found more than one asset with the same ean (ean=${ean}).`); - } - - return primaryResults[0]; -} - -type FindRelatedAssetsOptions = Pick< - GetAllRelatedAssetsOptions, - 'relation' | 'kind' | 'from' | 'to' -> & { visitedEans: string[] }; - -async function findRelatedAssets( - elasticsearchClient: ElasticsearchClient, - primary: Asset, - { relation, from, to, kind, visitedEans }: FindRelatedAssetsOptions -): Promise { - const relationField = relationToDirectField(relation); - const directlyRelatedEans = toArray(primary[relationField]); - - debug('Directly Related EAN values found on primary asset', directlyRelatedEans); - - let directlyRelatedAssets: Asset[] = []; - - // get the directly related assets we haven't visited already - const remainingEansToFind = without(directlyRelatedEans, ...visitedEans); - if (remainingEansToFind.length > 0) { - directlyRelatedAssets = await getAssets({ - elasticsearchClient, - filters: { ean: remainingEansToFind, from, to, kind }, - }); - } - - debug('Directly related assets found:', JSON.stringify(directlyRelatedAssets)); - - const indirectlyRelatedAssets = await getIndirectlyRelatedAssets({ - elasticsearchClient, - ean: primary['asset.ean'], - excludeEans: visitedEans.concat(directlyRelatedEans), - relation, - from, - to, - kind, - }); - - debug('Indirectly related assets found:', JSON.stringify(indirectlyRelatedAssets)); - - return [...directlyRelatedAssets, ...indirectlyRelatedAssets]; -} - -function relationToDirectField(relation: Relation): RelationField { - if (relation === 'ancestors') { - return 'asset.parents'; - } else if (relation === 'descendants') { - return 'asset.children'; - } else { - return 'asset.references'; - } -} - -function withDistance( - distance: number -): (value: Asset, index: number, array: Asset[]) => Asset & { distance: number } { - return (asset: Asset) => ({ ...asset, distance }); -} diff --git a/x-pack/plugins/asset_manager/server/lib/get_assets.ts b/x-pack/plugins/asset_manager/server/lib/get_assets.ts deleted file mode 100644 index e3630f92f26e9..0000000000000 --- a/x-pack/plugins/asset_manager/server/lib/get_assets.ts +++ /dev/null @@ -1,130 +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'; -import { debug } from '../../common/debug_log'; -import { Asset, AssetFilters } from '../../common/types_api'; -import { ASSETS_INDEX_PREFIX } from '../constants'; -import { ElasticsearchAccessorOptions } from '../types'; -import { isStringOrNonEmptyArray } from './utils'; - -interface GetAssetsOptions extends ElasticsearchAccessorOptions { - size?: number; - filters?: AssetFilters; - from?: string; - to?: string; -} - -export async function getAssets({ - elasticsearchClient, - size = 100, - filters = {}, -}: GetAssetsOptions): Promise { - // Maybe it makes the most sense to validate the filters here? - debug('Get Assets Filters:', JSON.stringify(filters)); - - const { from = 'now-24h', to = 'now' } = filters; - const must: QueryDslQueryContainer[] = []; - - if (filters && Object.keys(filters).length > 0) { - if (typeof filters.collectionVersion === 'number') { - must.push({ - term: { - ['asset.collection_version']: filters.collectionVersion, - }, - }); - } - - if (isStringOrNonEmptyArray(filters.type)) { - must.push({ - terms: { - ['asset.type']: Array.isArray(filters.type) ? filters.type : [filters.type], - }, - }); - } - - if (isStringOrNonEmptyArray(filters.kind)) { - must.push({ - terms: { - ['asset.kind']: Array.isArray(filters.kind) ? filters.kind : [filters.kind], - }, - }); - } - - if (isStringOrNonEmptyArray(filters.ean)) { - must.push({ - terms: { - ['asset.ean']: Array.isArray(filters.ean) ? filters.ean : [filters.ean], - }, - }); - } - - if (filters.id) { - must.push({ - term: { - ['asset.id']: filters.id, - }, - }); - } - - if (filters.typeLike) { - must.push({ - wildcard: { - ['asset.type']: filters.typeLike, - }, - }); - } - - if (filters.kindLike) { - must.push({ - wildcard: { - ['asset.kind']: filters.kindLike, - }, - }); - } - - if (filters.eanLike) { - must.push({ - wildcard: { - ['asset.ean']: filters.eanLike, - }, - }); - } - } - - const dsl = { - index: ASSETS_INDEX_PREFIX + '*', - size, - query: { - bool: { - filter: [ - { - range: { - '@timestamp': { - gte: from, - lte: to, - }, - }, - }, - ], - must, - }, - }, - collapse: { - field: 'asset.ean', - }, - sort: { - '@timestamp': { - order: 'desc', - }, - }, - }; - - debug('Performing Get Assets Query', '\n\n', JSON.stringify(dsl, null, 2)); - - const response = await elasticsearchClient.search(dsl); - return response.hits.hits.map((hit) => hit._source).filter((asset): asset is Asset => !!asset); -} diff --git a/x-pack/plugins/asset_manager/server/lib/get_indirectly_related_assets.ts b/x-pack/plugins/asset_manager/server/lib/get_indirectly_related_assets.ts deleted file mode 100644 index b91242f4aba1b..0000000000000 --- a/x-pack/plugins/asset_manager/server/lib/get_indirectly_related_assets.ts +++ /dev/null @@ -1,106 +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, SearchRequest } from '@elastic/elasticsearch/lib/api/types'; -import { debug } from '../../common/debug_log'; -import { Asset, AssetKind, Relation, RelationField } from '../../common/types_api'; -import { ASSETS_INDEX_PREFIX } from '../constants'; -import { ElasticsearchAccessorOptions } from '../types'; -import { isStringOrNonEmptyArray } from './utils'; - -interface GetRelatedAssetsOptions extends ElasticsearchAccessorOptions { - size?: number; - ean: string; - excludeEans?: string[]; - from?: string; - to?: string; - relation: Relation; - kind?: AssetKind | AssetKind[]; -} - -export async function getIndirectlyRelatedAssets({ - elasticsearchClient, - size = 100, - from = 'now-24h', - to = 'now', - ean, - excludeEans, - relation, - kind, -}: GetRelatedAssetsOptions): Promise { - const relationField = relationToIndirectField(relation); - const must: QueryDslQueryContainer[] = [ - { - terms: { - [relationField]: [ean], - }, - }, - ]; - - if (isStringOrNonEmptyArray(kind)) { - must.push({ - terms: { - ['asset.kind']: Array.isArray(kind) ? kind : [kind], - }, - }); - } - - const mustNot: QueryDslQueryContainer[] = - excludeEans && excludeEans.length - ? [ - { - terms: { - 'asset.ean': excludeEans, - }, - }, - ] - : []; - - const dsl: SearchRequest = { - index: ASSETS_INDEX_PREFIX + '*', - size, - query: { - bool: { - filter: [ - { - range: { - '@timestamp': { - gte: from, - lte: to, - }, - }, - }, - ], - must, - must_not: mustNot, - }, - }, - collapse: { - field: 'asset.ean', - }, - sort: { - '@timestamp': { - order: 'desc', - }, - }, - }; - - debug('Performing Indirectly Related Asset Query', '\n\n', JSON.stringify(dsl, null, 2)); - - const response = await elasticsearchClient.search(dsl); - return response.hits.hits.map((hit) => hit._source).filter((asset): asset is Asset => !!asset); -} - -function relationToIndirectField(relation: Relation): RelationField { - if (relation === 'ancestors') { - return 'asset.children'; - } else if (relation === 'descendants') { - return 'asset.parents'; - } else { - return 'asset.references'; - } -} diff --git a/x-pack/plugins/asset_manager/server/lib/parse_ean.test.ts b/x-pack/plugins/asset_manager/server/lib/parse_ean.test.ts new file mode 100644 index 0000000000000..b7dc5e592dabd --- /dev/null +++ b/x-pack/plugins/asset_manager/server/lib/parse_ean.test.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 { parseEan } from './parse_ean'; + +describe('parseEan function', () => { + it('should parse a valid EAN and return the kind and id as separate values', () => { + const ean = 'host:some-id-123'; + const { kind, id } = parseEan(ean); + expect(kind).toBe('host'); + expect(id).toBe('some-id-123'); + }); + + it('should throw an error when the provided EAN does not have enough segments', () => { + expect(() => parseEan('invalid-ean')).toThrowError('not a valid EAN'); + expect(() => parseEan('invalid-ean:')).toThrowError('not a valid EAN'); + expect(() => parseEan(':invalid-ean')).toThrowError('not a valid EAN'); + }); + + it('should throw an error when the provided EAN has too many segments', () => { + const ean = 'host:invalid:segments'; + expect(() => parseEan(ean)).toThrowError('not a valid EAN'); + }); + + it('should throw an error when the provided EAN includes an unsupported "kind" value', () => { + const ean = 'unsupported_kind:some-id-123'; + expect(() => parseEan(ean)).toThrowError('not a valid EAN'); + }); +}); diff --git a/x-pack/plugins/asset_manager/server/lib/parse_ean.ts b/x-pack/plugins/asset_manager/server/lib/parse_ean.ts index e466549a1830f..6be17f40de005 100644 --- a/x-pack/plugins/asset_manager/server/lib/parse_ean.ts +++ b/x-pack/plugins/asset_manager/server/lib/parse_ean.ts @@ -5,10 +5,12 @@ * 2.0. */ +import { assetKindRT } from '../../common/types_api'; + export function parseEan(ean: string) { const [kind, id, ...rest] = ean.split(':'); - if (!kind || !id || rest.length > 0) { + if (!assetKindRT.is(kind) || !kind || !id || rest.length > 0) { throw new Error(`${ean} is not a valid EAN`); } diff --git a/x-pack/plugins/asset_manager/server/routes/assets/containers.ts b/x-pack/plugins/asset_manager/server/routes/assets/containers.ts new file mode 100644 index 0000000000000..05c6d7264465b --- /dev/null +++ b/x-pack/plugins/asset_manager/server/routes/assets/containers.ts @@ -0,0 +1,73 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { createRouteValidationFunction } from '@kbn/io-ts-utils'; +import { RequestHandlerContext } from '@kbn/core-http-request-handler-context-server'; +import { + GetContainerAssetsQueryOptions, + getContainerAssetsQueryOptionsRT, +} from '../../../common/types_api'; +import { debug } from '../../../common/debug_log'; +import { SetupRouteOptions } from '../types'; +import * as routePaths from '../../../common/constants_routes'; +import { getClientsFromContext, validateStringAssetFilters } from '../utils'; +import { AssetsValidationError } from '../../lib/validators/validation_error'; + +export function containersRoutes({ + router, + assetClient, +}: SetupRouteOptions) { + const validate = createRouteValidationFunction(getContainerAssetsQueryOptionsRT); + router.get( + { + path: routePaths.GET_CONTAINERS, + validate: { + query: (q, res) => { + const [invalidResponse, validatedFilters] = validateStringAssetFilters(q, res); + if (invalidResponse) { + return invalidResponse; + } + if (validatedFilters) { + q.filters = validatedFilters; + } + return validate(q, res); + }, + }, + }, + async (context, req, res) => { + const { from = 'now-24h', to = 'now', filters } = req.query || {}; + const { elasticsearchClient, savedObjectsClient } = await getClientsFromContext(context); + + try { + const response = await assetClient.getContainers({ + from, + to, + filters, // safe due to route validation, are there better ways to do this? + elasticsearchClient, + savedObjectsClient, + }); + + return res.ok({ body: response }); + } catch (error: unknown) { + debug('Error while looking up CONTAINER asset records', error); + + if (error instanceof AssetsValidationError) { + return res.customError({ + statusCode: error.statusCode, + body: { + message: `Error while looking up container asset records - ${error.message}`, + }, + }); + } + return res.customError({ + statusCode: 500, + body: { message: 'Error while looking up container asset records - ' + `${error}` }, + }); + } + } + ); +} diff --git a/x-pack/plugins/asset_manager/server/routes/assets/hosts.ts b/x-pack/plugins/asset_manager/server/routes/assets/hosts.ts index b260193647b4f..f38d33d2b65f3 100644 --- a/x-pack/plugins/asset_manager/server/routes/assets/hosts.ts +++ b/x-pack/plugins/asset_manager/server/routes/assets/hosts.ts @@ -11,28 +11,39 @@ import { GetHostAssetsQueryOptions, getHostAssetsQueryOptionsRT } from '../../.. import { debug } from '../../../common/debug_log'; import { SetupRouteOptions } from '../types'; import * as routePaths from '../../../common/constants_routes'; -import { getClientsFromContext } from '../utils'; +import { getClientsFromContext, validateStringAssetFilters } from '../utils'; import { AssetsValidationError } from '../../lib/validators/validation_error'; export function hostsRoutes({ router, assetClient, }: SetupRouteOptions) { + const validate = createRouteValidationFunction(getHostAssetsQueryOptionsRT); router.get( { path: routePaths.GET_HOSTS, validate: { - query: createRouteValidationFunction(getHostAssetsQueryOptionsRT), + query: (q, res) => { + const [invalidResponse, validatedFilters] = validateStringAssetFilters(q, res); + if (invalidResponse) { + return invalidResponse; + } + if (validatedFilters) { + q.filters = validatedFilters; + } + return validate(q, res); + }, }, }, async (context, req, res) => { - const { from = 'now-24h', to = 'now' } = req.query || {}; + const { from = 'now-24h', to = 'now', filters } = req.query || {}; const { elasticsearchClient, savedObjectsClient } = await getClientsFromContext(context); try { const response = await assetClient.getHosts({ from, to, + filters, // safe due to route validation, are there better ways to do this? elasticsearchClient, savedObjectsClient, }); diff --git a/x-pack/plugins/asset_manager/server/routes/assets/index.ts b/x-pack/plugins/asset_manager/server/routes/assets/index.ts deleted file mode 100644 index 8d9eaff170d30..0000000000000 --- a/x-pack/plugins/asset_manager/server/routes/assets/index.ts +++ /dev/null @@ -1,230 +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 { RequestHandlerContext } from '@kbn/core/server'; -import { differenceBy, intersectionBy } from 'lodash'; -import * as rt from 'io-ts'; -import { - dateRt, - inRangeFromStringRt, - datemathStringRt, - createRouteValidationFunction, - createLiteralValueFromUndefinedRT, -} from '@kbn/io-ts-utils'; -import { debug } from '../../../common/debug_log'; -import { assetTypeRT, assetKindRT, relationRT } from '../../../common/types_api'; -import { GET_ASSETS, GET_RELATED_ASSETS, GET_ASSETS_DIFF } from '../../../common/constants_routes'; -import { getAssets } from '../../lib/get_assets'; -import { getAllRelatedAssets } from '../../lib/get_all_related_assets'; -import { SetupRouteOptions } from '../types'; -import { getClientsFromContext } from '../utils'; -import { AssetNotFoundError } from '../../lib/errors'; -import { isValidRange } from '../../lib/utils'; - -function maybeArrayRT(t: rt.Mixed) { - return rt.union([rt.array(t), t]); -} - -const sizeRT = rt.union([inRangeFromStringRt(1, 100), createLiteralValueFromUndefinedRT(10)]); -const assetDateRT = rt.union([dateRt, datemathStringRt]); -const getAssetsQueryOptionsRT = rt.exact( - rt.partial({ - from: assetDateRT, - to: assetDateRT, - type: maybeArrayRT(assetTypeRT), - kind: maybeArrayRT(assetKindRT), - ean: maybeArrayRT(rt.string), - size: sizeRT, - }) -); - -const getAssetsDiffQueryOptionsRT = rt.exact( - rt.intersection([ - rt.type({ - aFrom: assetDateRT, - aTo: assetDateRT, - bFrom: assetDateRT, - bTo: assetDateRT, - }), - rt.partial({ - type: maybeArrayRT(assetTypeRT), - kind: maybeArrayRT(assetKindRT), - }), - ]) -); - -const getRelatedAssetsQueryOptionsRT = rt.exact( - rt.intersection([ - rt.type({ - from: assetDateRT, - ean: rt.string, - relation: relationRT, - size: sizeRT, - maxDistance: rt.union([inRangeFromStringRt(1, 5), createLiteralValueFromUndefinedRT(1)]), - }), - rt.partial({ - to: assetDateRT, - type: maybeArrayRT(assetTypeRT), - kind: maybeArrayRT(assetKindRT), - }), - ]) -); - -export type GetAssetsQueryOptions = rt.TypeOf; -export type GetRelatedAssetsQueryOptions = rt.TypeOf; -export type GetAssetsDiffQueryOptions = rt.TypeOf; - -export function assetsRoutes({ router }: SetupRouteOptions) { - // GET /assets - router.get( - { - path: GET_ASSETS, - validate: { - query: createRouteValidationFunction(getAssetsQueryOptionsRT), - }, - }, - async (context, req, res) => { - const { size, ...filters } = req.query || {}; - - if (filters.type && filters.ean) { - return res.badRequest({ - body: 'Filters "type" and "ean" are mutually exclusive but found both.', - }); - } - - if (filters.kind && filters.ean) { - return res.badRequest({ - body: 'Filters "kind" and "ean" are mutually exclusive but found both.', - }); - } - - const { elasticsearchClient } = await getClientsFromContext(context); - - try { - const results = await getAssets({ elasticsearchClient, size, filters }); - return res.ok({ body: { results } }); - } catch (error: unknown) { - debug('error looking up asset records', error); - return res.customError({ - statusCode: 500, - body: { message: 'Error while looking up asset records - ' + `${error}` }, - }); - } - } - ); - - // GET assets/related - router.get( - { - path: GET_RELATED_ASSETS, - validate: { - query: createRouteValidationFunction(getRelatedAssetsQueryOptionsRT), - }, - }, - async (context, req, res) => { - // Add references into sample data and write integration tests - - const { from, to, ean, relation, maxDistance, size, type, kind } = req.query || {}; - const { elasticsearchClient } = await getClientsFromContext(context); - - if (to && !isValidRange(from, to)) { - return res.badRequest({ - body: `Time range cannot move backwards in time. "to" (${to}) is before "from" (${from}).`, - }); - } - - try { - return res.ok({ - body: { - results: await getAllRelatedAssets(elasticsearchClient, { - ean, - from, - to, - type, - kind, - maxDistance, - size, - relation, - }), - }, - }); - } catch (error: any) { - debug('error looking up asset records', error); - if (error instanceof AssetNotFoundError) { - return res.customError({ statusCode: 404, body: error.message }); - } - return res.customError({ statusCode: 500, body: error.message }); - } - } - ); - - // GET /assets/diff - router.get( - { - path: GET_ASSETS_DIFF, - validate: { - query: createRouteValidationFunction(getAssetsDiffQueryOptionsRT), - }, - }, - async (context, req, res) => { - const { aFrom, aTo, bFrom, bTo, type, kind } = req.query; - // const type = toArray(req.query.type); - // const kind = toArray(req.query.kind); - - if (!isValidRange(aFrom, aTo)) { - return res.badRequest({ - body: `Time range cannot move backwards in time. "aTo" (${aTo}) is before "aFrom" (${aFrom}).`, - }); - } - - if (!isValidRange(bFrom, bTo)) { - return res.badRequest({ - body: `Time range cannot move backwards in time. "bTo" (${bTo}) is before "bFrom" (${bFrom}).`, - }); - } - - const { elasticsearchClient } = await getClientsFromContext(context); - - try { - const resultsForA = await getAssets({ - elasticsearchClient, - filters: { - from: aFrom, - to: aTo, - type, - kind, - }, - }); - - const resultsForB = await getAssets({ - elasticsearchClient, - filters: { - from: bFrom, - to: bTo, - type, - kind, - }, - }); - - const onlyInA = differenceBy(resultsForA, resultsForB, 'asset.ean'); - const onlyInB = differenceBy(resultsForB, resultsForA, 'asset.ean'); - const inBoth = intersectionBy(resultsForA, resultsForB, 'asset.ean'); - - return res.ok({ - body: { - onlyInA, - onlyInB, - inBoth, - }, - }); - } catch (error: unknown) { - debug('error looking up asset records', error); - return res.customError({ statusCode: 500 }); - } - } - ); -} diff --git a/x-pack/plugins/asset_manager/server/routes/index.ts b/x-pack/plugins/asset_manager/server/routes/index.ts index 30064a8562b6f..20f5abf889e78 100644 --- a/x-pack/plugins/asset_manager/server/routes/index.ts +++ b/x-pack/plugins/asset_manager/server/routes/index.ts @@ -8,18 +8,18 @@ import { RequestHandlerContext } from '@kbn/core/server'; import { SetupRouteOptions } from './types'; import { pingRoute } from './ping'; -import { assetsRoutes } from './assets'; import { sampleAssetsRoutes } from './sample_assets'; import { hostsRoutes } from './assets/hosts'; import { servicesRoutes } from './assets/services'; +import { containersRoutes } from './assets/containers'; export function setupRoutes({ router, assetClient, }: SetupRouteOptions) { pingRoute({ router, assetClient }); - assetsRoutes({ router, assetClient }); sampleAssetsRoutes({ router, assetClient }); hostsRoutes({ router, assetClient }); servicesRoutes({ router, assetClient }); + containersRoutes({ router, assetClient }); } diff --git a/x-pack/plugins/asset_manager/server/routes/utils.ts b/x-pack/plugins/asset_manager/server/routes/utils.ts index 665adc0917fa0..3eb2a855e4854 100644 --- a/x-pack/plugins/asset_manager/server/routes/utils.ts +++ b/x-pack/plugins/asset_manager/server/routes/utils.ts @@ -5,7 +5,12 @@ * 2.0. */ -import { RequestHandlerContext } from '@kbn/core/server'; +import { + RequestHandlerContext, + RouteValidationError, + RouteValidationResultFactory, +} from '@kbn/core/server'; +import { AssetFilters, assetFiltersSingleKindRT } from '../../common/types_api'; export async function getClientsFromContext(context: T) { const coreContext = await context.core; @@ -16,3 +21,26 @@ export async function getClientsFromContext(con savedObjectsClient: coreContext.savedObjects.client, }; } + +type ValidateStringAssetFiltersReturn = + | [{ error: RouteValidationError }] + | [null, AssetFilters | undefined]; + +export function validateStringAssetFilters( + q: any, + res: RouteValidationResultFactory +): ValidateStringAssetFiltersReturn { + if (typeof q.stringFilters === 'string') { + try { + const parsedFilters = JSON.parse(q.stringFilters); + if (assetFiltersSingleKindRT.is(parsedFilters)) { + return [null, parsedFilters]; + } else { + return [res.badRequest(new Error(`Invalid asset filters - ${q.filters}`))]; + } + } catch (err: any) { + return [res.badRequest(err)]; + } + } + return [null, undefined]; +} diff --git a/x-pack/plugins/asset_manager/server/test_utils.ts b/x-pack/plugins/asset_manager/server/test_utils.ts new file mode 100644 index 0000000000000..8e07f201b1599 --- /dev/null +++ b/x-pack/plugins/asset_manager/server/test_utils.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. + */ + +// Helper function allows test to verify error was thrown, +// verify error is of the right class type, and error has + +import { SavedObjectsClientContract } from '@kbn/core-saved-objects-api-server'; +import { GetApmIndicesMethod } from './lib/asset_client_types'; +import { AssetsValidationError } from './lib/validators/validation_error'; + +// the expected metadata such as statusCode on it +export function expectToThrowValidationErrorWithStatusCode( + testFn: () => Promise, + expectedError: Partial = {} +) { + return expect(async () => { + try { + return await testFn(); + } catch (error: any) { + if (error instanceof AssetsValidationError) { + if (expectedError.statusCode) { + expect(error.statusCode).toEqual(expectedError.statusCode); + } + if (expectedError.message) { + expect(error.message).toEqual(expect.stringContaining(expectedError.message)); + } + } + throw error; + } + }).rejects.toThrow(AssetsValidationError); +} + +export function createGetApmIndicesMock(): jest.Mocked { + return jest.fn(async (client: SavedObjectsClientContract) => ({ + transaction: 'apm-mock-transaction-indices', + span: 'apm-mock-span-indices', + error: 'apm-mock-error-indices', + metric: 'apm-mock-metric-indices', + onboarding: 'apm-mock-onboarding-indices', + sourcemap: 'apm-mock-sourcemap-indices', + })); +} diff --git a/x-pack/plugins/cases/docs/openapi/bundled.json b/x-pack/plugins/cases/docs/openapi/bundled.json index ad498a328dd44..80cdefd30e957 100644 --- a/x-pack/plugins/cases/docs/openapi/bundled.json +++ b/x-pack/plugins/cases/docs/openapi/bundled.json @@ -5549,7 +5549,7 @@ }, "alert_identifiers": { "title": "Alert identifiers", - "description": "The alert identifiers. It is required only when `type` is `alert`. You can use an array of strings to add multiple alerts to a case, provided that they all relate to the same rule; `index` must also be an array with the same length or number of elements. Adding multiple alerts in this manner is recommended rather than calling the API multiple times. 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", + "description": "The alert identifiers. It is required only when `type` is `alert`. You can use an array of strings to add multiple alerts to a case, provided that they all relate to the same rule; `index` must also be an array with the same length or number of elements. Adding multiple alerts in this manner is recommended rather than calling the API multiple times. This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features.\n", "oneOf": [ { "type": "string" @@ -5567,7 +5567,7 @@ }, "alert_indices": { "title": "Alert indices", - "description": "The alert indices. It is required only when `type` is `alert`. If you are adding multiple alerts to a case, use an array of strings; the position of each index name in the array must match the position of the corresponding alert identifier in the `alertId` array. 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", + "description": "The alert indices. It is required only when `type` is `alert`. If you are adding multiple alerts to a case, use an array of strings; the position of each index name in the array must match the position of the corresponding alert identifier in the `alertId` array. This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features.\n", "oneOf": [ { "type": "string" @@ -5584,7 +5584,7 @@ }, "rule": { "title": "Alerting rule", - "description": "The rule that is associated with the alerts. It is required only when `type` is `alert`. 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", + "description": "The rule that is associated with the alerts. It is required only when `type` is `alert`. This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features.\n", "type": "object", "x-technical-preview": true, "properties": { diff --git a/x-pack/plugins/cases/docs/openapi/bundled.yaml b/x-pack/plugins/cases/docs/openapi/bundled.yaml index 3f4cce541b581..ec5c1db337f29 100644 --- a/x-pack/plugins/cases/docs/openapi/bundled.yaml +++ b/x-pack/plugins/cases/docs/openapi/bundled.yaml @@ -3760,7 +3760,7 @@ components: alert_identifiers: title: Alert identifiers description: | - The alert identifiers. It is required only when `type` is `alert`. You can use an array of strings to add multiple alerts to a case, provided that they all relate to the same rule; `index` must also be an array with the same length or number of elements. Adding multiple alerts in this manner is recommended rather than calling the API multiple times. 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. + The alert identifiers. It is required only when `type` is `alert`. You can use an array of strings to add multiple alerts to a case, provided that they all relate to the same rule; `index` must also be an array with the same length or number of elements. Adding multiple alerts in this manner is recommended rather than calling the API multiple times. This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. oneOf: - type: string - type: array @@ -3772,7 +3772,7 @@ components: alert_indices: title: Alert indices description: | - The alert indices. It is required only when `type` is `alert`. If you are adding multiple alerts to a case, use an array of strings; the position of each index name in the array must match the position of the corresponding alert identifier in the `alertId` array. 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. + The alert indices. It is required only when `type` is `alert`. If you are adding multiple alerts to a case, use an array of strings; the position of each index name in the array must match the position of the corresponding alert identifier in the `alertId` array. This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. oneOf: - type: string - type: array @@ -3783,7 +3783,7 @@ components: rule: title: Alerting rule description: | - The rule that is associated with the alerts. It is required only when `type` is `alert`. 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. + The rule that is associated with the alerts. It is required only when `type` is `alert`. This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. type: object x-technical-preview: true properties: diff --git a/x-pack/plugins/cases/docs/openapi/components/schemas/alert_identifiers.yaml b/x-pack/plugins/cases/docs/openapi/components/schemas/alert_identifiers.yaml index 0f56441b7ff90..cca8eb74f5019 100644 --- a/x-pack/plugins/cases/docs/openapi/components/schemas/alert_identifiers.yaml +++ b/x-pack/plugins/cases/docs/openapi/components/schemas/alert_identifiers.yaml @@ -1,11 +1,11 @@ title: Alert identifiers description: > - The alert identifiers. It is required only when `type` is `alert`. You can use - an array of strings to add multiple alerts to a case, provided that they all - relate to the same rule; `index` must also be an array with the same length or number of elements. Adding multiple alerts in this manner is recommended - rather than calling the API multiple times. 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. + The alert identifiers. + It is required only when `type` is `alert`. + You can use an array of strings to add multiple alerts to a case, provided that they all relate to the same rule; `index` must also be an array with the same length or number of elements. + Adding multiple alerts in this manner is recommended rather than calling the API multiple times. + This functionality is in technical preview and may be changed or removed in a future release. + Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. oneOf: - type: string - type: array diff --git a/x-pack/plugins/cases/docs/openapi/components/schemas/alert_indices.yaml b/x-pack/plugins/cases/docs/openapi/components/schemas/alert_indices.yaml index f82bb1762ee32..5c741e9601c44 100644 --- a/x-pack/plugins/cases/docs/openapi/components/schemas/alert_indices.yaml +++ b/x-pack/plugins/cases/docs/openapi/components/schemas/alert_indices.yaml @@ -1,12 +1,10 @@ title: Alert indices description: > - The alert indices. It is required only when `type` is `alert`. If you are - adding multiple alerts to a case, use an array of strings; the position of - each index name in the array must match the position of the corresponding - alert identifier in the `alertId` array. 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. + The alert indices. + It is required only when `type` is `alert`. + If you are adding multiple alerts to a case, use an array of strings; the position of each index name in the array must match the position of the corresponding alert identifier in the `alertId` array. + This functionality is in technical preview and may be changed or removed in a future release. + Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. oneOf: - type: string - type: array diff --git a/x-pack/plugins/cases/docs/openapi/components/schemas/rule.yaml b/x-pack/plugins/cases/docs/openapi/components/schemas/rule.yaml index 4722f43246de8..09712b57ce138 100644 --- a/x-pack/plugins/cases/docs/openapi/components/schemas/rule.yaml +++ b/x-pack/plugins/cases/docs/openapi/components/schemas/rule.yaml @@ -1,10 +1,9 @@ title: Alerting rule description: > - The rule that is associated with the alerts. It is required only when - `type` is `alert`. 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. + The rule that is associated with the alerts. + It is required only when `type` is `alert`. + This functionality is in technical preview and may be changed or removed in a future release. + Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. type: object x-technical-preview: true properties: @@ -12,7 +11,7 @@ properties: description: The rule identifier. type: string example: 94d80550-aaf4-11ec-985f-97e55adae8b9 - name: + name: description: The rule name. type: string example: security_rule \ No newline at end of file diff --git a/x-pack/plugins/cases/public/common/translations.ts b/x-pack/plugins/cases/public/common/translations.ts index 7295a08cfd51a..eab026897e3bf 100644 --- a/x-pack/plugins/cases/public/common/translations.ts +++ b/x-pack/plugins/cases/public/common/translations.ts @@ -383,5 +383,5 @@ export const EXPERIMENTAL_LABEL = i18n.translate('xpack.cases.badge.experimental export const EXPERIMENTAL_DESC = i18n.translate('xpack.cases.badge.experimentalDesc', { defaultMessage: - 'This functionality is in technical preview and may be changed or removed completely in a future release. Elastic will take a best effort approach to fix any issues, but features in technical preview are not subject to the support SLA of official GA features.', + 'This functionality is in technical preview and may be changed or removed completely in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features.', }); diff --git a/x-pack/plugins/cases/public/components/add_comment/index.test.tsx b/x-pack/plugins/cases/public/components/add_comment/index.test.tsx index 7239ea8be0e7a..6a3806036904a 100644 --- a/x-pack/plugins/cases/public/components/add_comment/index.test.tsx +++ b/x-pack/plugins/cases/public/components/add_comment/index.test.tsx @@ -14,7 +14,7 @@ import { noCreateCasesPermissions, TestProviders, createAppMockRenderer } from ' import { AttachmentType } from '../../../common/types/domain'; import { SECURITY_SOLUTION_OWNER, MAX_COMMENT_LENGTH } from '../../../common/constants'; -import { useCreateAttachments } from '../../containers/use_create_attachments'; +import { createAttachments } from '../../containers/api'; import type { AddCommentProps, AddCommentRefObject } from '.'; import { AddComment } from '.'; import { CasesTimelineIntegrationProvider } from '../timeline_context'; @@ -22,12 +22,13 @@ import { timelineIntegrationMock } from '../__mock__/timeline'; import type { CaseAttachmentWithoutOwner } from '../../types'; import type { AppMockRenderer } from '../../common/mock'; -jest.mock('../../containers/use_create_attachments'); +jest.mock('../../containers/api', () => ({ + createAttachments: jest.fn(), +})); -const useCreateAttachmentsMock = useCreateAttachments as jest.Mock; +const createAttachmentsMock = createAttachments as jest.Mock; const onCommentSaving = jest.fn(); const onCommentPosted = jest.fn(); -const createAttachments = jest.fn(); const addCommentProps: AddCommentProps = { id: 'newComment', @@ -51,18 +52,13 @@ const sampleData: CaseAttachmentWithoutOwner = { const appId = 'testAppId'; const draftKey = `cases.${appId}.${addCommentProps.caseId}.${addCommentProps.id}.markdownEditor`; -// FLAKY: https://github.com/elastic/kibana/issues/168505 -// FLAKY: https://github.com/elastic/kibana/issues/168506 -// FLAKY: https://github.com/elastic/kibana/issues/168507 -// FLAKY: https://github.com/elastic/kibana/issues/168508 -// FLAKY: https://github.com/elastic/kibana/issues/168509 -describe.skip('AddComment ', () => { +describe('AddComment ', () => { let appMockRender: AppMockRenderer; beforeEach(() => { jest.clearAllMocks(); appMockRender = createAppMockRenderer(); - useCreateAttachmentsMock.mockImplementation(() => defaultResponse); + createAttachmentsMock.mockImplementation(() => defaultResponse); }); afterEach(() => { @@ -75,19 +71,21 @@ describe.skip('AddComment ', () => { expect(screen.getByTestId('add-comment')).toBeInTheDocument(); }); - it('should render spinner and disable submit when loading', () => { - useCreateAttachmentsMock.mockImplementation(() => ({ - ...defaultResponse, - isLoading: true, - })); + it('should render spinner and disable submit when loading', async () => { appMockRender.render(); - expect(screen.getByTestId('loading-spinner')).toBeInTheDocument(); + fireEvent.change(screen.getByLabelText('caseComment'), { + target: { value: sampleData.comment }, + }); + + fireEvent.click(screen.getByTestId('submit-comment')); + + expect(await screen.findByTestId('loading-spinner')).toBeInTheDocument(); expect(screen.getByTestId('submit-comment')).toHaveAttribute('disabled'); }); it('should hide the component when the user does not have create permissions', () => { - useCreateAttachmentsMock.mockImplementation(() => ({ + createAttachmentsMock.mockImplementation(() => ({ ...defaultResponse, isLoading: true, })); @@ -105,27 +103,23 @@ describe.skip('AddComment ', () => { appMockRender.render(); const markdown = screen.getByTestId('euiMarkdownEditorTextArea'); - userEvent.type(markdown, sampleData.comment); userEvent.click(screen.getByTestId('submit-comment')); - await waitFor(() => { - expect(onCommentSaving).toBeCalled(); - expect(createAttachments).toBeCalledWith( - { - caseId: addCommentProps.caseId, - caseOwner: SECURITY_SOLUTION_OWNER, - attachments: [sampleData], - }, - { onSuccess: expect.anything() } - ); - }); - - act(() => { - createAttachments.mock.calls[0][1].onSuccess(); - }); - + await waitFor(() => expect(onCommentSaving).toBeCalled()); + await waitFor(() => + expect(createAttachmentsMock).toBeCalledWith({ + caseId: addCommentProps.caseId, + attachments: [ + { + comment: sampleData.comment, + owner: SECURITY_SOLUTION_OWNER, + type: AttachmentType.user, + }, + ], + }) + ); await waitFor(() => { expect(screen.getByTestId('euiMarkdownEditorTextArea')).toHaveTextContent(''); }); @@ -250,11 +244,7 @@ describe.skip('AddComment ', () => { }); }); -// Depends on useCreateAttachmentsMock.mockImplementation -// in describe.skip('AddComment') -// https://github.com/elastic/kibana/issues/169875 -// FLAKY: https://github.com/elastic/kibana/issues/169876 -describe.skip('draft comment ', () => { +describe('draft comment ', () => { let appMockRenderer: AppMockRenderer; beforeEach(() => { @@ -293,18 +283,16 @@ describe.skip('draft comment ', () => { await waitFor(() => { expect(onCommentSaving).toBeCalled(); - expect(createAttachments).toBeCalledWith( - { - caseId: addCommentProps.caseId, - caseOwner: SECURITY_SOLUTION_OWNER, - attachments: [sampleData], - }, - { onSuccess: expect.anything() } - ); - }); - - act(() => { - createAttachments.mock.calls[0][1].onSuccess(); + expect(createAttachmentsMock).toBeCalledWith({ + caseId: addCommentProps.caseId, + attachments: [ + { + comment: sampleData.comment, + owner: SECURITY_SOLUTION_OWNER, + type: AttachmentType.user, + }, + ], + }); }); await waitFor(() => { diff --git a/x-pack/plugins/cases/public/components/case_view/components/case_view_activity.test.tsx b/x-pack/plugins/cases/public/components/case_view/components/case_view_activity.test.tsx index 5d5f3c2c742ec..d648fc2b6faee 100644 --- a/x-pack/plugins/cases/public/components/case_view/components/case_view_activity.test.tsx +++ b/x-pack/plugins/cases/public/components/case_view/components/case_view_activity.test.tsx @@ -179,6 +179,7 @@ describe('Case View Page activity tab', () => { expect(await screen.findByTestId('case-view-activity')).toBeInTheDocument(); expect(await screen.findAllByTestId('user-actions-list')).toHaveLength(2); + expect(await screen.findByTestId('description')).toBeInTheDocument(); expect(await screen.findByTestId('case-tags')).toBeInTheDocument(); expect(await screen.findByTestId('cases-categories')).toBeInTheDocument(); expect(await screen.findByTestId('connector-edit-header')).toBeInTheDocument(); @@ -417,38 +418,7 @@ describe('Case View Page activity tab', () => { }); }); - // FLAKY: https://github.com/elastic/kibana/issues/151981 - describe.skip('User actions', () => { - it('renders the description correctly', async () => { - appMockRender = createAppMockRenderer(); - appMockRender.render(); - - const description = within(await screen.findByTestId('description')); - - expect(await description.findByText(caseData.description)).toBeInTheDocument(); - }); - - it('renders edit description user action correctly', async () => { - useFindCaseUserActionsMock.mockReturnValue({ - ...defaultUseFindCaseUserActions, - data: { - userActions: [ - getUserAction('description', 'create'), - getUserAction('description', 'update'), - ], - }, - }); - - appMockRender = createAppMockRenderer(); - appMockRender.render(); - - const userActions = within((await screen.findAllByTestId('user-actions-list'))[1]); - - expect( - userActions.getByTestId('description-update-action-description-update') - ).toBeInTheDocument(); - }); - + describe('User actions', () => { it('renders the unassigned users correctly', async () => { useFindCaseUserActionsMock.mockReturnValue({ ...defaultUseFindCaseUserActions, diff --git a/x-pack/plugins/cases/public/components/description/index.test.tsx b/x-pack/plugins/cases/public/components/description/index.test.tsx index 33145c711493d..386d6b6e7154f 100644 --- a/x-pack/plugins/cases/public/components/description/index.test.tsx +++ b/x-pack/plugins/cases/public/components/description/index.test.tsx @@ -56,9 +56,7 @@ describe('Description', () => { userEvent.click(res.getByTestId('description-collapse-icon')); - await waitFor(() => { - expect(screen.getByText('Security banana Issue')).toBeInTheDocument(); - }); + expect(await screen.findByText('Security banana Issue')).toBeInTheDocument(); }); it('shows textarea on edit click', async () => { @@ -68,9 +66,7 @@ describe('Description', () => { userEvent.click(res.getByTestId('description-edit-icon')); - await waitFor(() => { - expect(screen.getByTestId('euiMarkdownEditorTextArea')).toBeInTheDocument(); - }); + expect(await screen.findByTestId('euiMarkdownEditorTextArea')).toBeInTheDocument(); }); it('edits the description correctly when saved', async () => { @@ -82,12 +78,15 @@ describe('Description', () => { userEvent.click(res.getByTestId('description-edit-icon')); userEvent.clear(screen.getByTestId('euiMarkdownEditorTextArea')); - userEvent.type(screen.getByTestId('euiMarkdownEditorTextArea'), editedDescription); + userEvent.paste(screen.getByTestId('euiMarkdownEditorTextArea'), editedDescription); userEvent.click(screen.getByTestId('editable-save-markdown')); await waitFor(() => { - expect(onUpdateField).toHaveBeenCalledWith({ key: 'description', value: editedDescription }); + expect(onUpdateField).toHaveBeenCalledWith({ + key: 'description', + value: editedDescription, + }); }); }); @@ -100,20 +99,21 @@ describe('Description', () => { userEvent.click(res.getByTestId('description-edit-icon')); userEvent.clear(screen.getByTestId('euiMarkdownEditorTextArea')); - userEvent.type(screen.getByTestId('euiMarkdownEditorTextArea'), editedDescription); + userEvent.paste(screen.getByTestId('euiMarkdownEditorTextArea'), editedDescription); + + expect(screen.getByText(editedDescription)).toBeInTheDocument(); userEvent.click(screen.getByTestId('editable-cancel-markdown')); await waitFor(() => { expect(onUpdateField).not.toHaveBeenCalled(); - expect(screen.getByText('Security banana Issue')).toBeInTheDocument(); }); + + expect(screen.getByText('Security banana Issue')).toBeInTheDocument(); }); it('shows an error when description is too long', async () => { - const longDescription = Array(MAX_DESCRIPTION_LENGTH / 2 + 1) - .fill('a') - .toString(); + const longDescription = 'a'.repeat(MAX_DESCRIPTION_LENGTH + 1); const res = appMockRender.render( @@ -124,14 +124,13 @@ describe('Description', () => { userEvent.clear(screen.getByTestId('euiMarkdownEditorTextArea')); userEvent.paste(screen.getByTestId('euiMarkdownEditorTextArea'), longDescription); - await waitFor(() => { - expect( - screen.getByText( - 'The length of the description is too long. The maximum length is 30000 characters.' - ) - ).toBeInTheDocument(); - expect(screen.getByTestId('editable-save-markdown')).toHaveAttribute('disabled'); - }); + expect( + await screen.findByText( + 'The length of the description is too long. The maximum length is 30000 characters.' + ) + ).toBeInTheDocument(); + + expect(await screen.findByTestId('editable-save-markdown')).toHaveAttribute('disabled'); }); it('should hide the edit button when the user does not have update permissions', () => { diff --git a/x-pack/plugins/cases/public/components/user_actions/index.test.tsx b/x-pack/plugins/cases/public/components/user_actions/index.test.tsx index 8032ce26480d8..69d7c07340e42 100644 --- a/x-pack/plugins/cases/public/components/user_actions/index.test.tsx +++ b/x-pack/plugins/cases/public/components/user_actions/index.test.tsx @@ -6,7 +6,7 @@ */ import React from 'react'; -import { waitFor, screen, within, fireEvent } from '@testing-library/react'; +import { screen, within, fireEvent } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { waitForEuiPopoverOpen } from '@elastic/eui/lib/test/rtl'; // eslint-disable-next-line @kbn/eslint/module_migration @@ -17,14 +17,10 @@ import { basicCase, caseUserActions, getUserAction } from '../../containers/mock import { UserActions } from '.'; import type { AppMockRenderer } from '../../common/mock'; import { createAppMockRenderer } from '../../common/mock'; -import { UserActionActions } from '../../../common/types/domain'; import { getCaseConnectorsMockResponse } from '../../common/mock/connectors'; import type { UserActivityParams } from '../user_actions_activity_bar/types'; import { useFindCaseUserActions } from '../../containers/use_find_case_user_actions'; -import { - defaultInfiniteUseFindCaseUserActions, - defaultUseFindCaseUserActions, -} from '../case_view/mocks'; +import { defaultUseFindCaseUserActions } from '../case_view/mocks'; import { waitForComponentToUpdate } from '../../common/test_utils'; import { useInfiniteFindCaseUserActions } from '../../containers/use_infinite_find_case_user_actions'; import { getMockBuilderArgs } from './mock'; @@ -88,7 +84,7 @@ describe(`UserActions`, () => { mutate: patchComment, }); useFindCaseUserActionsMock.mockReturnValue(defaultUseFindCaseUserActions); - useInfiniteFindCaseUserActionsMock.mockReturnValue(defaultInfiniteUseFindCaseUserActions); + useInfiniteFindCaseUserActionsMock.mockReturnValue({ isLoading: false, data: undefined }); jest.spyOn(routeData, 'useParams').mockReturnValue({ detailName: 'case-id' }); appMockRender = createAppMockRenderer(); @@ -116,10 +112,8 @@ describe(`UserActions`, () => { await waitForComponentToUpdate(); - await waitFor(() => { - expect(screen.getByTestId('top-footer')).toBeInTheDocument(); - expect(screen.getByTestId('bottom-footer')).toBeInTheDocument(); - }); + expect(await screen.findByTestId('top-footer')).toBeInTheDocument(); + expect(await screen.findByTestId('bottom-footer')).toBeInTheDocument(); }); it('Renders service now update line with top only when push is up to date', async () => { @@ -135,106 +129,81 @@ describe(`UserActions`, () => { }); appMockRender.render(); - await waitFor(() => { - expect(screen.getByTestId('top-footer')).toBeInTheDocument(); - expect(screen.queryByTestId('bottom-footer')).not.toBeInTheDocument(); - }); + + expect(await screen.findByTestId('top-footer')).toBeInTheDocument(); + expect(screen.queryByTestId('bottom-footer')).not.toBeInTheDocument(); }); it('Switches to markdown when edit is clicked and back to panel when canceled', async () => { - const ourActions = [getUserAction('comment', UserActionActions.create)]; - - useFindCaseUserActionsMock.mockReturnValue({ - ...defaultUseFindCaseUserActions, - data: { userActions: ourActions }, - }); - appMockRender.render(); userEvent.click( - within( - screen.getAllByTestId(`comment-create-action-${defaultProps.data.comments[0].id}`)[1] - ).getByTestId('property-actions-user-action-ellipses') + await within( + await screen.findByTestId(`comment-create-action-${defaultProps.data.comments[0].id}`) + ).findByTestId('property-actions-user-action-ellipses') ); await waitForEuiPopoverOpen(); - userEvent.click(screen.getByTestId('property-actions-user-action-pencil')); + userEvent.click(await screen.findByTestId('property-actions-user-action-pencil')); userEvent.click( - within( - screen.getAllByTestId(`comment-create-action-${defaultProps.data.comments[0].id}`)[1] - ).getByTestId('editable-cancel-markdown') + await within( + await screen.findByTestId(`comment-create-action-${defaultProps.data.comments[0].id}`) + ).findByTestId('editable-cancel-markdown') ); - await waitFor(() => { - expect( - within( - screen.getAllByTestId(`comment-create-action-${defaultProps.data.comments[0].id}`)[1] - ).queryByTestId('editable-markdown-form') - ).not.toBeInTheDocument(); - }); + expect( + within( + await screen.findByTestId(`comment-create-action-${defaultProps.data.comments[0].id}`) + ).queryByTestId('editable-markdown-form') + ).not.toBeInTheDocument(); }); it('calls update comment when comment markdown is saved', async () => { - const ourActions = [getUserAction('comment', UserActionActions.create)]; - - useFindCaseUserActionsMock.mockReturnValue({ - ...defaultUseFindCaseUserActions, - data: { userActions: ourActions }, - }); - appMockRender.render(); userEvent.click( - within( - screen.getAllByTestId(`comment-create-action-${defaultProps.data.comments[0].id}`)[1] - ).getByTestId('property-actions-user-action-ellipses') + await within( + await screen.findByTestId(`comment-create-action-${defaultProps.data.comments[0].id}`) + ).findByTestId('property-actions-user-action-ellipses') ); await waitForEuiPopoverOpen(); - userEvent.click(screen.getByTestId('property-actions-user-action-pencil')); + userEvent.click(await screen.findByTestId('property-actions-user-action-pencil')); await waitForComponentToUpdate(); - fireEvent.change(screen.getAllByTestId(`euiMarkdownEditorTextArea`)[0], { + fireEvent.change((await screen.findAllByTestId(`euiMarkdownEditorTextArea`))[0], { target: { value: sampleData.content }, }); userEvent.click( within( - screen.getAllByTestId(`comment-create-action-${defaultProps.data.comments[0].id}`)[1] + screen.getByTestId(`comment-create-action-${defaultProps.data.comments[0].id}`) ).getByTestId('editable-save-markdown') ); - await waitFor(() => { - expect( - within( - screen.getAllByTestId(`comment-create-action-${defaultProps.data.comments[0].id}`)[1] - ).queryByTestId('editable-markdown-form') - ).not.toBeInTheDocument(); - - expect(patchComment).toBeCalledWith( - { - commentUpdate: sampleData.content, - caseId: 'case-id', - commentId: defaultProps.data.comments[0].id, - version: defaultProps.data.comments[0].version, - }, - { onSuccess: expect.anything(), onError: expect.anything() } - ); - }); + expect( + within( + await screen.findByTestId(`comment-create-action-${defaultProps.data.comments[0].id}`) + ).queryByTestId('editable-markdown-form') + ).not.toBeInTheDocument(); + + expect(patchComment).toBeCalledWith( + { + commentUpdate: sampleData.content, + caseId: 'case-id', + commentId: defaultProps.data.comments[0].id, + version: defaultProps.data.comments[0].version, + }, + { onSuccess: expect.anything(), onError: expect.anything() } + ); }); it('shows quoted text in last MarkdownEditorTextArea', async () => { const quoteableText = `> Solve this fast! \n\n`; - const ourActions = [getUserAction('comment', UserActionActions.create)]; - - useFindCaseUserActionsMock.mockReturnValue({ - ...defaultUseFindCaseUserActions, - data: { userActions: ourActions }, - }); appMockRender.render(); @@ -243,18 +212,16 @@ describe(`UserActions`, () => { ); userEvent.click( - within( - screen.getAllByTestId(`comment-create-action-${defaultProps.data.comments[0].id}`)[1] - ).getByTestId('property-actions-user-action-ellipses') + await within( + await screen.findByTestId(`comment-create-action-${defaultProps.data.comments[0].id}`) + ).findByTestId('property-actions-user-action-ellipses') ); await waitForEuiPopoverOpen(); - userEvent.click(screen.getByTestId('property-actions-user-action-quote')); + userEvent.click(await screen.findByTestId('property-actions-user-action-quote')); - await waitFor(() => { - expect(screen.getAllByTestId('add-comment')[0].textContent).toContain(quoteableText); - }); + expect((await screen.findAllByTestId('add-comment'))[0].textContent).toContain(quoteableText); }); it('does not show add comment markdown when history filter is selected', async () => { @@ -265,8 +232,6 @@ describe(`UserActions`, () => { /> ); - await waitFor(() => { - expect(screen.queryByTestId('add-comment')).not.toBeInTheDocument(); - }); + expect(screen.queryByTestId('add-comment')).not.toBeInTheDocument(); }); }); diff --git a/x-pack/plugins/cases/public/containers/configure/use_get_case_configuration.tsx b/x-pack/plugins/cases/public/containers/configure/use_get_case_configuration.tsx index 9cb839587d2a1..3a7656ca051ea 100644 --- a/x-pack/plugins/cases/public/containers/configure/use_get_case_configuration.tsx +++ b/x-pack/plugins/cases/public/containers/configure/use_get_case_configuration.tsx @@ -42,7 +42,7 @@ export const useGetCaseConfiguration = () => { const { showErrorToast } = useCasesToast(); return useQuery( - casesQueriesKeys.configuration(), + casesQueriesKeys.configuration({ owner }), ({ signal }) => getCaseConfigure({ owner, signal }), { select: transformConfiguration, diff --git a/x-pack/plugins/cases/public/containers/configure/use_persist_configuration.test.tsx b/x-pack/plugins/cases/public/containers/configure/use_persist_configuration.test.tsx index b8a4ee93be1f8..a5eed1e41a007 100644 --- a/x-pack/plugins/cases/public/containers/configure/use_persist_configuration.test.tsx +++ b/x-pack/plugins/cases/public/containers/configure/use_persist_configuration.test.tsx @@ -12,7 +12,7 @@ import * as api from './api'; import { useToasts } from '../../common/lib/kibana'; import type { AppMockRenderer } from '../../common/mock'; import { createAppMockRenderer } from '../../common/mock'; -import { ConnectorTypes } from '../../../common'; +import { ConnectorTypes, SECURITY_SOLUTION_OWNER } from '../../../common'; import { casesQueriesKeys } from '../constants'; jest.mock('./api'); @@ -130,7 +130,9 @@ describe('useCreateAttachments', () => { await waitForNextUpdate(); - expect(queryClientSpy).toHaveBeenCalledWith(casesQueriesKeys.configuration()); + expect(queryClientSpy).toHaveBeenCalledWith( + casesQueriesKeys.configuration({ owner: [SECURITY_SOLUTION_OWNER] }) + ); }); it('shows the success toaster', async () => { diff --git a/x-pack/plugins/cases/public/containers/configure/use_persist_configuration.tsx b/x-pack/plugins/cases/public/containers/configure/use_persist_configuration.tsx index 85615f07954ad..65f2c63800cde 100644 --- a/x-pack/plugins/cases/public/containers/configure/use_persist_configuration.tsx +++ b/x-pack/plugins/cases/public/containers/configure/use_persist_configuration.tsx @@ -47,7 +47,7 @@ export const usePersistConfiguration = () => { { mutationKey: casesMutationsKeys.persistCaseConfiguration, onSuccess: () => { - queryClient.invalidateQueries(casesQueriesKeys.configuration()); + queryClient.invalidateQueries(casesQueriesKeys.configuration({ owner })); showSuccessToast(i18n.SUCCESS_CONFIGURE); }, onError: (error: ServerError) => { diff --git a/x-pack/plugins/cases/public/containers/constants.ts b/x-pack/plugins/cases/public/containers/constants.ts index 7c39e76590fb4..148885362a0c4 100644 --- a/x-pack/plugins/cases/public/containers/constants.ts +++ b/x-pack/plugins/cases/public/containers/constants.ts @@ -47,7 +47,7 @@ export const casesQueriesKeys = { categories: () => [...casesQueriesKeys.all, 'categories'] as const, alertFeatureIds: (alertRegistrationContexts: string[]) => [...casesQueriesKeys.alerts, 'features', alertRegistrationContexts] as const, - configuration: () => [...casesQueriesKeys.all, 'configuration'] as const, + configuration: (params: unknown) => [...casesQueriesKeys.all, 'configuration', params] as const, }; export const casesMutationsKeys = { diff --git a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/eks_credentials_form.tsx b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/eks_credentials_form.tsx index 80ffaf39c4197..41f4b857e13f8 100644 --- a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/eks_credentials_form.tsx +++ b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/eks_credentials_form.tsx @@ -128,6 +128,7 @@ type AwsOptions = Record< label: string; info: React.ReactNode; fields: Record; + testId: string; } >; @@ -144,6 +145,7 @@ const options: AwsOptions = { }), }, }, + testId: 'assumeRoleTestId', }, direct_access_keys: { label: i18n.translate('xpack.csp.eksIntegration.directAccessKeyLabel', { @@ -154,6 +156,7 @@ const options: AwsOptions = { access_key_id: { label: AWS_FIELD_LABEL.access_key_id }, secret_access_key: { label: AWS_FIELD_LABEL.secret_access_key, type: 'password' }, }, + testId: 'directAccessKeyTestId', }, temporary_keys: { info: TemporaryKeysDescription, @@ -169,6 +172,7 @@ const options: AwsOptions = { }), }, }, + testId: 'temporaryKeyTestId', }, shared_credentials: { label: i18n.translate('xpack.csp.eksIntegration.sharedCredentialLabel', { @@ -187,6 +191,7 @@ const options: AwsOptions = { }), }, }, + testId: 'sharedCredentialsTestId', }, }; @@ -195,6 +200,7 @@ export const DEFAULT_EKS_VARS_GROUP: AwsCredentialsType = 'assume_role'; const AWS_CREDENTIALS_OPTIONS = Object.keys(options).map((value) => ({ id: value as AwsCredentialsType, label: options[value as keyof typeof options].label, + testId: options[value as keyof typeof options].testId, })); interface Props { 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 e9457cdee850a..b1880eeb0c7ef 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 @@ -547,7 +547,34 @@ describe('', () => { }); }); + describe('K8S', () => { + it('K8S or KSPM Vanilla should not render any Setup Access option', () => { + const policy = getMockPolicyK8s(); + + const { queryByTestId } = render(); + + expect(queryByTestId('assumeRoleTestId')).not.toBeInTheDocument(); + expect(queryByTestId('directAccessKeyTestId')).not.toBeInTheDocument(); + expect(queryByTestId('temporaryKeyTestId')).not.toBeInTheDocument(); + expect(queryByTestId('sharedCredentialsTestId')).not.toBeInTheDocument(); + }); + }); + describe('EKS Credentials input fields', () => { + it(`documentation Hyperlink should have correct URL to redirect users to AWS page`, () => { + let policy = getMockPolicyEKS(); + policy = getPosturePolicy(policy, CLOUDBEAT_EKS, { + 'aws.credentials.type': { value: 'assume_role' }, + 'aws.setup.format': { value: 'manual' }, + }); + + const { getByText } = render(); + + expect(getByText('documentation')).toHaveAttribute( + 'href', + 'https://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html' + ); + }); it(`renders ${CLOUDBEAT_EKS} Assume Role fields`, () => { let policy = getMockPolicyEKS(); policy = getPosturePolicy(policy, CLOUDBEAT_EKS, { @@ -782,6 +809,55 @@ describe('', () => { expect(getByLabelText('AWS Organization')).toBeEnabled(); }); + it(`Getting started Hyperlink should have correct URL to redirect users to elastic page`, () => { + let policy = getMockPolicyAWS(); + policy = getPosturePolicy(policy, CLOUDBEAT_AWS, { + 'aws.credentials.type': { value: 'assume_role' }, + 'aws.setup.format': { value: 'manual' }, + }); + + const { getByText } = render(); + + expect(getByText('Getting Started')).toHaveAttribute( + 'href', + 'https://ela.st/cspm-get-started' + ); + }); + + it(`documentation Hyperlink should have correct URL to redirect users to elastic page if user chose Manual`, () => { + let policy = getMockPolicyAWS(); + policy = getPosturePolicy(policy, CLOUDBEAT_AWS, { + 'aws.credentials.type': { value: 'assume_role' }, + 'aws.setup.format': { value: 'manual' }, + }); + + const { getByTestId } = render( + + ); + + expect(getByTestId('externalLink')).toHaveAttribute( + 'href', + 'https://ela.st/cspm-get-started' + ); + }); + + it(`documentation Hyperlink should have correct URL to redirect users to AWS page if user chose Cloudformation`, () => { + let policy = getMockPolicyAWS(); + policy = getPosturePolicy(policy, CLOUDBEAT_AWS, { + 'aws.credentials.type': { value: 'cloud_formation' }, + 'aws.account_type': { value: 'single-account' }, + }); + + const { getByTestId } = render( + + ); + + expect(getByTestId('externalLink')).toHaveAttribute( + 'href', + 'https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cfn-whatis-howdoesitwork.html' + ); + }); + it(`renders ${CLOUDBEAT_AWS} Assume Role fields`, () => { let policy = getMockPolicyAWS(); policy = getPosturePolicy(policy, CLOUDBEAT_AWS, { @@ -964,6 +1040,17 @@ describe('', () => { it('Update Agent Policy CloudFormation template from vars', () => { const policy = getMockPolicyVulnMgmtAWS(); + const packageInfo = getMockPackageInfoVulnMgmtAWS(); + const { getByTestId } = render( + + ); + + expect(getByTestId('additionalChargeCalloutTestSubj')).toBeInTheDocument(); + }); + + it('Additional Charge Callout message should be rendered', () => { + const policy = getMockPolicyVulnMgmtAWS(); + const packageInfo = getMockPackageInfoVulnMgmtAWS(); render(); @@ -1010,6 +1097,20 @@ describe('', () => { ).toBeInTheDocument(); }); + it(`documentation Hyperlink should have correct URL to redirect users to elastic page`, () => { + let policy = getMockPolicyGCP(); + policy = getPosturePolicy(policy, CLOUDBEAT_GCP, { + credentials_type: { value: 'credentials-file' }, + setup_access: { value: 'manual' }, + }); + + const { getByText } = render( + + ); + + expect(getByText('documentation')).toHaveAttribute('href', 'https://ela.st/cspm-get-started'); + }); + it(`renders Google Cloud Shell forms when Setup Access is set to Google Cloud Shell`, () => { let policy = getMockPolicyGCP(); policy = getPosturePolicy(policy, CLOUDBEAT_GCP, { diff --git a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/policy_template_selectors.tsx b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/policy_template_selectors.tsx index 01d7fdcfc1891..ef21868dd404d 100644 --- a/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/policy_template_selectors.tsx +++ b/x-pack/plugins/cloud_security_posture/public/components/fleet_extensions/policy_template_selectors.tsx @@ -114,6 +114,7 @@ export const PolicyTemplateInfo = ({ postureType }: PolicyTemplateInfoProps) => ct !== STACK_COMPONENT_TEMPLATE_LOGS_SETTINGS), }); logger.info(`Updated index template successfully [Name: ${indexTemplateName}]`); diff --git a/x-pack/plugins/enterprise_search/public/applications/__mocks__/kea_logic/http_logic.mock.ts b/x-pack/plugins/enterprise_search/public/applications/__mocks__/kea_logic/http_logic.mock.ts index ba8ed14a7ba35..a6b238a1d3dc2 100644 --- a/x-pack/plugins/enterprise_search/public/applications/__mocks__/kea_logic/http_logic.mock.ts +++ b/x-pack/plugins/enterprise_search/public/applications/__mocks__/kea_logic/http_logic.mock.ts @@ -8,8 +8,8 @@ import { httpServiceMock } from '@kbn/core/public/mocks'; export const mockHttpValues = { - http: httpServiceMock.createSetupContract(), errorConnectingMessage: '', + http: httpServiceMock.createSetupContract(), readOnlyMode: false, }; diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/connector/start_access_control_sync_api_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/connector/start_access_control_sync_api_logic.test.ts new file mode 100644 index 0000000000000..da4d6dc0516ba --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/connector/start_access_control_sync_api_logic.test.ts @@ -0,0 +1,34 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { mockHttpValues } from '../../../__mocks__/kea_logic'; + +import { nextTick } from '@kbn/test-jest-helpers'; + +import { startAccessControlSync } from './start_access_control_sync_api_logic'; + +describe('startAccessControlSyncApiLogic', () => { + describe('startAccessControlSync', () => { + const { http } = mockHttpValues; + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('calls correct api', async () => { + const promise = Promise.resolve('result'); + http.post.mockReturnValue(promise); + const connectorId = 'test-connector-id-123'; + + const result = startAccessControlSync({ connectorId }); + await nextTick(); + expect(http.post).toHaveBeenCalledWith( + `/internal/enterprise_search/connectors/${connectorId}/start_access_control_sync` + ); + await expect(result).resolves.toEqual('result'); + }); + }); +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/settings/settings.test.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/settings/settings.test.tsx new file mode 100644 index 0000000000000..212425ddb874b --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/settings/settings.test.tsx @@ -0,0 +1,45 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; + +import { screen } from '@testing-library/react'; + +import '@testing-library/jest-dom'; + +import { HttpSetupMock } from '@kbn/core-http-browser-mocks'; + +import { HttpLogic } from '../../../shared/http'; +import { TestHelper } from '../../../test_helpers/test_utils.test_helper'; +import { FetchDefaultPipelineApiLogic } from '../../api/connector/get_default_pipeline_api_logic'; + +import { Settings } from './settings'; + +test('displays Settings Save-Reset buttons disabled by default', async () => { + TestHelper.prepare(); + TestHelper.mountLogic(FetchDefaultPipelineApiLogic); + TestHelper.appendCallback(() => { + const http = HttpLogic.values.http as HttpSetupMock; + http.get.mockImplementationOnce(() => + Promise.resolve({ + extract_binary_content: true, + name: 'test', + reduce_whitespace: true, + run_ml_inference: true, + }) + ); + }); + TestHelper.render(); + + const saveButton = screen.getByTestId('entSearchContentSettingsSaveButton'); + const resetButton = screen.getByTestId('entSearchContentSettingsResetButton'); + + expect(saveButton).toHaveTextContent('Save'); + expect(saveButton).toBeDisabled(); + expect(resetButton).toHaveTextContent('Reset'); + expect(resetButton).toBeDisabled(); +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/settings/settings.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/settings/settings.tsx index 83d5143968780..6c4e9c3c1178a 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/settings/settings.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/settings/settings.tsx @@ -23,7 +23,6 @@ import { SettingsPanel } from './settings_panel'; export const Settings: React.FC = () => { const { makeRequest, setPipeline } = useActions(SettingsLogic); const { defaultPipeline, hasNoChanges, isLoading, pipelineState } = useValues(SettingsLogic); - const { extract_binary_content: extractBinaryContent, reduce_whitespace: reduceWhitespace, @@ -62,6 +61,7 @@ export const Settings: React.FC = () => { disabled={hasNoChanges} isLoading={isLoading} onClick={() => makeRequest(pipelineState)} + data-test-subj={'entSearchContentSettingsSaveButton'} > {i18n.translate('xpack.enterpriseSearch.content.settings.saveButtonLabel', { defaultMessage: 'Save', @@ -71,6 +71,7 @@ export const Settings: React.FC = () => { disabled={hasNoChanges} isLoading={isLoading} onClick={() => setPipeline(defaultPipeline)} + data-test-subj={'entSearchContentSettingsResetButton'} > {i18n.translate('xpack.enterpriseSearch.content.settings.resetButtonLabel', { defaultMessage: 'Reset', diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/http/http_logic.ts b/x-pack/plugins/enterprise_search/public/applications/shared/http/http_logic.ts index f9b3a758885cc..483ea83d1fb08 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/http/http_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/shared/http/http_logic.ts @@ -7,14 +7,14 @@ import { kea, MakeLogicType } from 'kea'; -import { HttpSetup, HttpInterceptorResponseError, HttpResponse } from '@kbn/core/public'; +import { HttpInterceptorResponseError, HttpResponse, HttpSetup } from '@kbn/core/public'; import { ERROR_CONNECTING_HEADER, READ_ONLY_MODE_HEADER } from '../../../../common/constants'; export interface HttpValues { + errorConnectingMessage: string; http: HttpSetup; httpInterceptors: Function[]; - errorConnectingMessage: string; readOnlyMode: boolean; } @@ -26,33 +26,21 @@ interface HttpActions { } export const HttpLogic = kea>({ - path: ['enterprise_search', 'http_logic'], actions: { initializeHttpInterceptors: () => null, onConnectionError: (errorConnectingMessage) => ({ errorConnectingMessage }), setHttpInterceptors: (httpInterceptors) => ({ httpInterceptors }), setReadOnlyMode: (readOnlyMode) => ({ readOnlyMode }), }, - reducers: ({ props }) => ({ - http: [props.http, {}], - httpInterceptors: [ - [], - { - setHttpInterceptors: (_, { httpInterceptors }) => httpInterceptors, - }, - ], - errorConnectingMessage: [ - props.errorConnectingMessage || '', - { - onConnectionError: (_, { errorConnectingMessage }) => errorConnectingMessage, - }, - ], - readOnlyMode: [ - props.readOnlyMode || false, - { - setReadOnlyMode: (_, { readOnlyMode }) => readOnlyMode, - }, - ], + events: ({ values, actions }) => ({ + afterMount: () => { + actions.initializeHttpInterceptors(); + }, + beforeUnmount: () => { + values.httpInterceptors.forEach((removeInterceptorFn?: Function) => { + if (removeInterceptorFn) removeInterceptorFn(); + }); + }, }), listeners: ({ values, actions }) => ({ initializeHttpInterceptors: () => { @@ -94,15 +82,27 @@ export const HttpLogic = kea>({ actions.setHttpInterceptors(httpInterceptors); }, }), - events: ({ values, actions }) => ({ - afterMount: () => { - actions.initializeHttpInterceptors(); - }, - beforeUnmount: () => { - values.httpInterceptors.forEach((removeInterceptorFn?: Function) => { - if (removeInterceptorFn) removeInterceptorFn(); - }); - }, + path: ['enterprise_search', 'http_logic'], + reducers: ({ props }) => ({ + errorConnectingMessage: [ + props.errorConnectingMessage || '', + { + onConnectionError: (_, { errorConnectingMessage }) => errorConnectingMessage, + }, + ], + http: [props.http, {}], + httpInterceptors: [ + [], + { + setHttpInterceptors: (_, { httpInterceptors }) => httpInterceptors, + }, + ], + readOnlyMode: [ + props.readOnlyMode || false, + { + setReadOnlyMode: (_, { readOnlyMode }) => readOnlyMode, + }, + ], }), }); @@ -110,14 +110,14 @@ export const HttpLogic = kea>({ * Mount/props helper */ interface HttpLogicProps { - http: HttpSetup; errorConnectingMessage?: string; + http: HttpSetup; readOnlyMode?: boolean; } + export const mountHttpLogic = (props: HttpLogicProps) => { HttpLogic(props); - const unmount = HttpLogic.mount(); - return unmount; + return HttpLogic.mount(); }; /** diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/kibana/index.ts b/x-pack/plugins/enterprise_search/public/applications/shared/kibana/index.ts index f8915e42eda4b..09c25dc14a558 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/kibana/index.ts +++ b/x-pack/plugins/enterprise_search/public/applications/shared/kibana/index.ts @@ -6,3 +6,4 @@ */ export { KibanaLogic, mountKibanaLogic } from './kibana_logic'; +export type { KibanaLogicProps } from './kibana_logic'; diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/kibana/kibana_logic.ts b/x-pack/plugins/enterprise_search/public/applications/shared/kibana/kibana_logic.ts index 67f605ea350f4..7bb064a18041a 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/kibana/kibana_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/shared/kibana/kibana_logic.ts @@ -33,7 +33,7 @@ import { createHref, CreateHrefOptions } from '../react_router_helpers'; type RequiredFieldsOnly = { [K in keyof T as T[K] extends Required[K] ? K : never]: T[K]; }; -interface KibanaLogicProps { +export interface KibanaLogicProps { application: ApplicationStart; capabilities: Capabilities; charts: ChartsPluginStart; diff --git a/x-pack/plugins/enterprise_search/public/applications/test_helpers/test_utils.test_helper.tsx b/x-pack/plugins/enterprise_search/public/applications/test_helpers/test_utils.test_helper.tsx new file mode 100644 index 0000000000000..492a1b1c83a44 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/test_helpers/test_utils.test_helper.tsx @@ -0,0 +1,142 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import { mockHistory } from '../__mocks__/react_router'; + +import React from 'react'; + +import { render as testingLibraryRender } from '@testing-library/react'; + +import { LogicWrapper, Provider, resetContext } from 'kea'; + +import { chartPluginMock } from '@kbn/charts-plugin/public/mocks'; +import { cloudMock } from '@kbn/cloud-plugin/public/mocks'; +import { ApplicationStart } from '@kbn/core-application-browser'; +import { Capabilities } from '@kbn/core-capabilities-common'; +import { httpServiceMock } from '@kbn/core-http-browser-mocks'; +import { uiSettingsServiceMock } from '@kbn/core-ui-settings-browser-mocks'; +import { dataPluginMock } from '@kbn/data-plugin/public/mocks'; +import { I18nProvider } from '@kbn/i18n-react'; +import { LensPublicStart } from '@kbn/lens-plugin/public'; +import { mlPluginMock } from '@kbn/ml-plugin/public/mocks'; +import { securityMock } from '@kbn/security-plugin/public/mocks'; +import { sharePluginMock } from '@kbn/share-plugin/public/mocks'; + +import { mountHttpLogic } from '../shared/http'; +import { mountKibanaLogic, KibanaLogicProps } from '../shared/kibana'; + +export const mockKibanaProps: KibanaLogicProps = { + application: { + getUrlForApp: jest.fn( + (appId: string, options?: { path?: string }) => `/app/${appId}${options?.path}` + ), + } as unknown as ApplicationStart, + capabilities: {} as Capabilities, + charts: chartPluginMock.createStartContract(), + cloud: { + ...cloudMock.createSetup(), + isCloudEnabled: false, + }, + config: { + canDeployEntSearch: true, + host: 'http://localhost:3002', + ui: { + enabled: true, + }, + }, + data: dataPluginMock.createStartContract(), + guidedOnboarding: {}, + history: mockHistory, + isSidebarEnabled: true, + lens: { + EmbeddableComponent: jest.fn(), + stateHelperApi: jest.fn().mockResolvedValue({ + formula: jest.fn(), + }), + } as unknown as LensPublicStart, + ml: mlPluginMock.createStartContract(), + navigateToUrl: jest.fn(), + productAccess: { + hasAppSearchAccess: true, + hasWorkplaceSearchAccess: true, + }, + productFeatures: { + hasConnectors: true, + hasDefaultIngestPipeline: true, + hasDocumentLevelSecurityEnabled: true, + hasIncrementalSyncEnabled: true, + hasNativeConnectors: true, + hasWebCrawler: true, + }, + renderHeaderActions: jest.fn(), + security: securityMock.createStart(), + setBreadcrumbs: jest.fn(), + setChromeIsVisible: jest.fn(), + setDocTitle: jest.fn(), + share: sharePluginMock.createStartContract(), + uiSettings: uiSettingsServiceMock.createStartContract(), +}; + +type LogicFile = LogicWrapper; +const DEFAULT_VALUES = { + httpLogicValues: { + http: httpServiceMock.createSetupContract(), + }, + kibanaLogicValues: mockKibanaProps, +}; + +interface PrepareOptions { + mockValues: typeof DEFAULT_VALUES; + noDefaultActions: boolean; +} + +interface TestHelper { + actionsToRun: Array<() => void>; + appendCallback: (callback: () => void) => void; + defaultActions: () => TestHelper['actionsToRun']; + defaultMockValues: typeof DEFAULT_VALUES; + mountLogic: (logicFile: LogicFile, props?: object) => void; + prepare: (options?: PrepareOptions) => void; + render: (children: JSX.Element) => void; +} + +export const TestHelper: TestHelper = { + actionsToRun: [], + appendCallback: (callback) => { + TestHelper.actionsToRun.push(callback); + }, + defaultActions: () => { + return [ + () => { + resetContext(); + }, + () => { + mountHttpLogic(TestHelper.defaultMockValues.httpLogicValues); + mountKibanaLogic(TestHelper.defaultMockValues.kibanaLogicValues); + }, + ]; + }, + defaultMockValues: DEFAULT_VALUES, + mountLogic: (logicFile, props?) => { + TestHelper.actionsToRun.push(() => logicFile.call(logicFile, props || undefined)); + }, + prepare: (options?) => { + TestHelper.defaultMockValues = { ...DEFAULT_VALUES, ...(options?.mockValues || {}) }; + if (!options || !options.noDefaultActions) { + TestHelper.actionsToRun = TestHelper.defaultActions(); + } + }, + render: (children) => { + TestHelper.actionsToRun.forEach((action) => { + action(); + }); + testingLibraryRender( + + {children} + + ); + }, +}; diff --git a/x-pack/plugins/enterprise_search/tsconfig.json b/x-pack/plugins/enterprise_search/tsconfig.json index 4f94a636d2b6d..380889ae63960 100644 --- a/x-pack/plugins/enterprise_search/tsconfig.json +++ b/x-pack/plugins/enterprise_search/tsconfig.json @@ -60,6 +60,9 @@ "@kbn/share-plugin", "@kbn/search-api-panels", "@kbn/search-connectors", - "@kbn/logs-shared-plugin" + "@kbn/logs-shared-plugin", + "@kbn/core-http-browser-mocks", + "@kbn/core-application-browser", + "@kbn/core-capabilities-common" ] } diff --git a/x-pack/plugins/fleet/common/constants/output.ts b/x-pack/plugins/fleet/common/constants/output.ts index 59f3ceff36a0f..fdf2075c541a3 100644 --- a/x-pack/plugins/fleet/common/constants/output.ts +++ b/x-pack/plugins/fleet/common/constants/output.ts @@ -13,6 +13,7 @@ export const outputType = { Elasticsearch: 'elasticsearch', Logstash: 'logstash', Kafka: 'kafka', + RemoteElasticsearch: 'remote_elasticsearch', } as const; export const DEFAULT_OUTPUT_ID = 'fleet-default-output'; diff --git a/x-pack/plugins/fleet/common/experimental_features.ts b/x-pack/plugins/fleet/common/experimental_features.ts index 89a5282199b75..233173263c129 100644 --- a/x-pack/plugins/fleet/common/experimental_features.ts +++ b/x-pack/plugins/fleet/common/experimental_features.ts @@ -24,6 +24,7 @@ export const allowedExperimentalValues = Object.freeze>( secretsStorage: true, kafkaOutput: true, outputSecretsStorage: false, + remoteESOutput: false, }); type ExperimentalConfigKeys = Array; diff --git a/x-pack/plugins/fleet/common/types/models/epm.ts b/x-pack/plugins/fleet/common/types/models/epm.ts index c05acb3de8b9f..d8400a8a61b9b 100644 --- a/x-pack/plugins/fleet/common/types/models/epm.ts +++ b/x-pack/plugins/fleet/common/types/models/epm.ts @@ -615,6 +615,7 @@ export interface IndexTemplate { }; data_stream: { hidden?: boolean }; composed_of: string[]; + ignore_missing_component_templates?: string[]; _meta: object; } diff --git a/x-pack/plugins/fleet/common/types/models/output.ts b/x-pack/plugins/fleet/common/types/models/output.ts index 5bed131be8d56..3283f4d01e540 100644 --- a/x-pack/plugins/fleet/common/types/models/output.ts +++ b/x-pack/plugins/fleet/common/types/models/output.ts @@ -58,11 +58,20 @@ export interface NewElasticsearchOutput extends NewBaseOutput { type: OutputType['Elasticsearch']; } +export interface NewRemoteElasticsearchOutput extends NewBaseOutput { + type: OutputType['RemoteElasticsearch']; + service_token?: string; +} + export interface NewLogstashOutput extends NewBaseOutput { type: OutputType['Logstash']; } -export type NewOutput = NewElasticsearchOutput | NewLogstashOutput | KafkaOutput; +export type NewOutput = + | NewElasticsearchOutput + | NewRemoteElasticsearchOutput + | NewLogstashOutput + | KafkaOutput; export type Output = NewOutput & { id: string; diff --git a/x-pack/plugins/fleet/dev_docs/diagrams/secrets/secret_storage_architecture.png b/x-pack/plugins/fleet/dev_docs/diagrams/secrets/secret_storage_architecture.png new file mode 100644 index 0000000000000..1c6034a62f45b Binary files /dev/null and b/x-pack/plugins/fleet/dev_docs/diagrams/secrets/secret_storage_architecture.png differ diff --git a/x-pack/plugins/fleet/dev_docs/secrets.md b/x-pack/plugins/fleet/dev_docs/secrets.md new file mode 100644 index 0000000000000..77c5f8521a4c5 --- /dev/null +++ b/x-pack/plugins/fleet/dev_docs/secrets.md @@ -0,0 +1,104 @@ +### Secrets + +Fleet users often need to provide sensitive information as part of their output and integration config, for example API keys or credentials. Originally these were value were not treated in any special way, but the requirement cae to store these more securely. + +## Solution Design + +When it came to designing secrets storage, our goals were: + +- 1. Kibana System and Fleet users should not be able to read any secrets once they are written for the first time +- 2. A malicious actor who gains authorization access to Kibana or Elasticsearch, or exploits an RCE in Kibana should not be able to read plaintext secret values. +- 3. Secrets in integration policies and outputs should be able to utilize secrets +- 4. When upgrading an integration policy, the policies secrets should be mapped across to the new version without user intervention +- 5. The design will use elastic as the secret store, however it should not prevent new secret stores from being added in the future. + + +## Architecture + +![secret storage architecture](./diagrams/secrets/secret_storage_architecture.png) + +Here is an overview of the integration policy flow: +- 1. A package identifies a field as secret using a new package spec +- 2. On creating an integration policy with a secret field, the secret is sent from the UI in plaintext +- 3. Kibana extracts secrets from the package policy using the package manifest to know which fields are secret +- 4. Kibana stores the secrets in the new `.secrets` system index +- 5. Kibana stores the policy with references to the secrets instead of the secrets +- 6. Fleet server reads the policy and retrieves the secrets +- 7. The fleet server inserts the secrets into the policy and passes the policy to the agent + +### What is a secret reference? +A secret reference replaces a plain text value, and refers to a record in the .fleet-secrets system index (or other secret store in the future). In the .fleet-secrets system index we only store the value itself. + +_example document from the .fleet-secrets index_ +```jsonc +{ + "_id": "abcd1234", + "_source": { + "value": "abcd12345678", + } +} +``` + +Kibana system user only has write and delete privileges for the .fleet-secrets system index. Fleet server user has read access. + +The secret reference is then stored in the package policy in a format to let us know it is a secret reference: + +_ingest-package-policies saved object in inputs.0.vars for example.._ +```jsonc +"password": { + "type": "password", + "value": { + "isSecretRef": true + "id": "12345678" + } +} +``` + +We then track all secrets contained in a policy at the top level of the package policy saved object, this removes the need for us to ever recurse over a policy to find all the secrets it uses: +_ingest-package-policies saved object at the top level_ +```jsonc + secret_refs: [{ + id: "abcd1234", + // in the future we may also have + // encrypted: true + // source: "elastic" + }] +``` + +We then need to have the secret ID in the compiled package policy for the fleet server to replace with the value. For this we have a known scheme to refer to a secret reference. We use “$co.elastic.secret\{\\}” scheme. For example the above secret would then be stored in the compiled package policy as follows: + +```jsonc +{ +"password": "$co.elastic.secret{abcd1234}", +// or in the case of a secret nested within a field... +"header": "Authorization Basic: $co.elastic.secret{abcd1234}", +} +``` + +### How does Fleet Server replace the secret references with the secrets? +Fleet server has read access to the .fleet-secrets index. Upon receiving a new policy update, Fleet Server first retrieves the secrets referenced in the policy, to accommodate this we have a block at the top of the agent policy that lists all secrets used within the policy: +```jsonc +{ + //at the top level of the policy sent to fleet server + secret_refs: [{ + id: "abcd12345", + // this is an object so that we can add attributes to the secret in the future, e.g a source or if it is encrypted + }, + { + // this may be an integration secret or an output secret + id: "defg56789" + }] +} +``` + +Having gathered the secrets, fleet server then performs templating on the policy replacing the integration or output secret references with the secret value. + +### How is Fleet server backwards compatibility handled? + +Integration secrets are only supported by Fleet server 8.10.0 or greater, output secrets 8.12.0. + +For integration secrets, when performing CRUD on a package policy, we first check the global settings saved object to see if secrets are enabled, if so then secret storage is used. + +If secret storage s not enabled, we check all flee tserver versions, if they meet the minimum spec, then we enable secret storage on the global settings saved object and the check is never performed again. + +For output secrets, we do not perform this check as outputs offer a plain text alternative for all secret fields. Instead we warn the user about the version requirements and let them decide. diff --git a/x-pack/plugins/fleet/public/applications/fleet/components/fleet_server_instructions/hooks/index.ts b/x-pack/plugins/fleet/public/applications/fleet/components/fleet_server_instructions/hooks/index.ts index 6c702d5433ce0..8896551583909 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/components/fleet_server_instructions/hooks/index.ts +++ b/x-pack/plugins/fleet/public/applications/fleet/components/fleet_server_instructions/hooks/index.ts @@ -14,5 +14,4 @@ export * from './use_quick_start_form'; // but exported here to support individual usage. export * from './use_wait_for_fleet_server'; export * from './use_select_fleet_server_policy'; -export * from './use_service_token'; export * from './use_fleet_server_host'; diff --git a/x-pack/plugins/fleet/public/applications/fleet/components/fleet_server_instructions/hooks/use_advanced_form.ts b/x-pack/plugins/fleet/public/applications/fleet/components/fleet_server_instructions/hooks/use_advanced_form.ts index 122f7045ac84c..aef485d6401b8 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/components/fleet_server_instructions/hooks/use_advanced_form.ts +++ b/x-pack/plugins/fleet/public/applications/fleet/components/fleet_server_instructions/hooks/use_advanced_form.ts @@ -9,9 +9,10 @@ import { useState } from 'react'; import type { DeploymentMode } from '../steps'; +import { useServiceToken } from '../../../hooks/use_service_token'; + import { useFleetServerHost } from './use_fleet_server_host'; import { useSelectFleetServerPolicy } from './use_select_fleet_server_policy'; -import { useServiceToken } from './use_service_token'; import { useWaitForFleetServer } from './use_wait_for_fleet_server'; /** diff --git a/x-pack/plugins/fleet/public/applications/fleet/components/fleet_server_instructions/hooks/use_quick_start_form.ts b/x-pack/plugins/fleet/public/applications/fleet/components/fleet_server_instructions/hooks/use_quick_start_form.ts index b2b8110f1e74b..b760282c80337 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/components/fleet_server_instructions/hooks/use_quick_start_form.ts +++ b/x-pack/plugins/fleet/public/applications/fleet/components/fleet_server_instructions/hooks/use_quick_start_form.ts @@ -15,8 +15,9 @@ import type { NewAgentPolicy } from '../../../types'; import type { FleetServerHost } from '../../../types'; +import { useServiceToken } from '../../../hooks/use_service_token'; + import { useSelectFleetServerPolicy } from './use_select_fleet_server_policy'; -import { useServiceToken } from './use_service_token'; import { useFleetServerHost } from './use_fleet_server_host'; const QUICK_START_FLEET_SERVER_POLICY_FIELDS: NewAgentPolicy = { diff --git a/x-pack/plugins/fleet/public/applications/fleet/components/fleet_server_instructions/hooks/use_service_token.ts b/x-pack/plugins/fleet/public/applications/fleet/components/fleet_server_instructions/hooks/use_service_token.ts deleted file mode 100644 index 3b729a6776b52..0000000000000 --- a/x-pack/plugins/fleet/public/applications/fleet/components/fleet_server_instructions/hooks/use_service_token.ts +++ /dev/null @@ -1,37 +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 { useState, useCallback } from 'react'; -import { i18n } from '@kbn/i18n'; - -import { useStartServices, sendGenerateServiceToken } from '../../../hooks'; - -export const useServiceToken = () => { - const { notifications } = useStartServices(); - const [serviceToken, setServiceToken] = useState(); - const [isLoadingServiceToken, setIsLoadingServiceToken] = useState(false); - - const generateServiceToken = useCallback(async () => { - setIsLoadingServiceToken(true); - try { - const { data } = await sendGenerateServiceToken(); - if (data?.value) { - setServiceToken(data?.value); - } - } catch (err) { - notifications.toasts.addError(err, { - title: i18n.translate('xpack.fleet.fleetServerSetup.errorGeneratingTokenTitleText', { - defaultMessage: 'Error generating token', - }), - }); - } finally { - setIsLoadingServiceToken(false); - } - }, [notifications.toasts]); - - return { serviceToken, isLoadingServiceToken, generateServiceToken }; -}; diff --git a/x-pack/plugins/fleet/public/applications/fleet/components/fleet_server_instructions/steps/create_service_token.tsx b/x-pack/plugins/fleet/public/applications/fleet/components/fleet_server_instructions/steps/create_service_token.tsx index fe211fded7ee4..bdf8add8ed2ca 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/components/fleet_server_instructions/steps/create_service_token.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/components/fleet_server_instructions/steps/create_service_token.tsx @@ -9,22 +9,10 @@ import React from 'react'; import styled from 'styled-components'; import type { EuiStepProps } from '@elastic/eui'; -import { - EuiButton, - EuiCallOut, - EuiCodeBlock, - EuiFlexGroup, - EuiFlexItem, - EuiSpacer, - EuiText, -} from '@elastic/eui'; +import { EuiFlexGroup } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { FormattedMessage } from '@kbn/i18n-react'; -const FlexItemWithMinWidth = styled(EuiFlexItem)` - min-width: 0px; - max-width: 100%; -`; +import { GenerateServiceTokenComponent } from '../../generate_service_token'; export const ContentWrapper = styled(EuiFlexGroup)` height: 100%; @@ -32,15 +20,6 @@ export const ContentWrapper = styled(EuiFlexGroup)` max-width: 800px; `; -// Otherwise the copy button is over the text -const CommandCode = styled.div.attrs(() => { - return { - className: 'eui-textBreakAll', - }; -})` - margin-right: ${(props) => props.theme.eui.euiSizeM}; -`; - export const getGenerateServiceTokenStep = ({ disabled = false, serviceToken, @@ -58,7 +37,7 @@ export const getGenerateServiceTokenStep = ({ }), status: disabled ? 'disabled' : undefined, children: !disabled && ( - void; - isLoadingServiceToken: boolean; -}> = ({ serviceToken, generateServiceToken, isLoadingServiceToken }) => { - return ( - <> - - - - - {!serviceToken ? ( - - - { - generateServiceToken(); - }} - data-test-subj="fleetServerGenerateServiceTokenBtn" - > - - - - - ) : ( - <> - - } - /> - - - - - - - - - - {serviceToken} - - - - - )} - - ); -}; diff --git a/x-pack/plugins/fleet/public/applications/fleet/components/generate_service_token.tsx b/x-pack/plugins/fleet/public/applications/fleet/components/generate_service_token.tsx new file mode 100644 index 0000000000000..7a59715329405 --- /dev/null +++ b/x-pack/plugins/fleet/public/applications/fleet/components/generate_service_token.tsx @@ -0,0 +1,138 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import styled from 'styled-components'; + +import { EuiLink, EuiToolTip } from '@elastic/eui'; +import { + EuiButton, + EuiCallOut, + EuiCodeBlock, + EuiFlexGroup, + EuiFlexItem, + EuiSpacer, + EuiText, +} from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n-react'; + +import { useStartServices } from '../../../hooks'; +import { useCheckPermissions } from '../hooks'; + +const FlexItemWithMinWidth = styled(EuiFlexItem)` + min-width: 0px; + max-width: 100%; +`; + +// Otherwise the copy button is over the text +const CommandCode = styled.div.attrs(() => { + return { + className: 'eui-textBreakAll', + }; +})` + margin-right: ${(props) => props.theme.eui.euiSizeM}; +`; + +export const GenerateServiceTokenComponent: React.FunctionComponent<{ + serviceToken?: string; + generateServiceToken: (remote?: boolean) => void; + isLoadingServiceToken: boolean; + isRemote?: boolean; +}> = ({ serviceToken, generateServiceToken, isLoadingServiceToken, isRemote = false }) => { + const { docLinks } = useStartServices(); + const { permissionsError, isPermissionsLoading } = useCheckPermissions(); + + return ( + <> + + {isRemote ? ( + + {i18n.translate('xpack.fleet.settings.editOutputFlyout.fleetUserGuideLabel', { + defaultMessage: 'Fleet User Guide', + })} + + ), + }} + /> + ) : ( + + )} + + + {!serviceToken ? ( + + + + ) : null + } + > + { + generateServiceToken(isRemote); + }} + data-test-subj="fleetServerGenerateServiceTokenBtn" + > + + + + + + ) : ( + <> + + } + /> + + + + + + + + + + {serviceToken} + + + + + )} + + ); +}; diff --git a/x-pack/plugins/fleet/public/applications/fleet/components/index.ts b/x-pack/plugins/fleet/public/applications/fleet/components/index.ts index a299013ab547e..e09be7a2d1927 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/components/index.ts +++ b/x-pack/plugins/fleet/public/applications/fleet/components/index.ts @@ -9,3 +9,4 @@ export * from '../../../components'; export * from './search_bar'; export * from './fleet_server_instructions'; +export * from './generate_service_token'; diff --git a/x-pack/plugins/fleet/public/applications/fleet/hooks/index.ts b/x-pack/plugins/fleet/public/applications/fleet/hooks/index.ts index 4d3056924d881..887ecdcff74d5 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/hooks/index.ts +++ b/x-pack/plugins/fleet/public/applications/fleet/hooks/index.ts @@ -9,3 +9,5 @@ export * from '../../../hooks'; export * from './use_breadcrumbs'; export * from './use_apm_service_href'; +export * from './use_service_token'; +export * from './use_check_permissions'; diff --git a/x-pack/plugins/fleet/public/applications/fleet/hooks/use_check_permissions.ts b/x-pack/plugins/fleet/public/applications/fleet/hooks/use_check_permissions.ts new file mode 100644 index 0000000000000..32f7ea44378e7 --- /dev/null +++ b/x-pack/plugins/fleet/public/applications/fleet/hooks/use_check_permissions.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 { useQuery } from '@tanstack/react-query'; + +import { sendGetPermissionsCheck } from '../../../hooks'; + +async function checkPermissions() { + let permissionsError; + + try { + const permissionsResponse = await sendGetPermissionsCheck(true); + + if (!permissionsResponse.data?.success) { + permissionsError = permissionsResponse.data?.error || 'REQUEST_ERROR'; + } + } catch (err) { + permissionsError = 'REQUEST_ERROR'; + } + return permissionsError; +} + +export const useCheckPermissions = () => { + const { data: permissionsError, status } = useQuery( + ['fetch-check-permissions'], + checkPermissions + ); + return { isPermissionsLoading: status === 'loading', permissionsError }; +}; diff --git a/x-pack/plugins/fleet/public/applications/fleet/hooks/use_service_token.ts b/x-pack/plugins/fleet/public/applications/fleet/hooks/use_service_token.ts new file mode 100644 index 0000000000000..7f1df8eebede9 --- /dev/null +++ b/x-pack/plugins/fleet/public/applications/fleet/hooks/use_service_token.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 { useState, useCallback } from 'react'; +import { i18n } from '@kbn/i18n'; + +import { useStartServices, sendGenerateServiceToken } from '.'; + +export const useServiceToken = () => { + const { notifications } = useStartServices(); + const [serviceToken, setServiceToken] = useState(); + const [isLoadingServiceToken, setIsLoadingServiceToken] = useState(false); + + const generateServiceToken = useCallback( + async (remote?: boolean) => { + setIsLoadingServiceToken(true); + try { + const { data } = await sendGenerateServiceToken(remote); + if (data?.value) { + setServiceToken(data?.value); + } + } catch (err) { + notifications.toasts.addError(err, { + title: i18n.translate('xpack.fleet.errorGeneratingTokenTitleText', { + defaultMessage: 'Error generating token', + }), + }); + } finally { + setIsLoadingServiceToken(false); + } + }, + [notifications.toasts] + ); + + return { serviceToken, isLoadingServiceToken, generateServiceToken }; +}; diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/components/agent_policy_advanced_fields/hooks.test.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/components/agent_policy_advanced_fields/hooks.test.tsx index 2d7eef6b864bf..e027317bf621a 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/components/agent_policy_advanced_fields/hooks.test.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/components/agent_policy_advanced_fields/hooks.test.tsx @@ -95,6 +95,31 @@ const mockApiCallsWithLogstashOutputs = (http: MockedFleetStartServices['http']) }); }; +const mockApiCallsWithRemoteESOutputs = (http: MockedFleetStartServices['http']) => { + http.get.mockImplementation(async (path) => { + if (typeof path !== 'string') { + throw new Error('Invalid request'); + } + if (path === '/api/fleet/outputs') { + return { + data: { + items: [ + { + id: 'remote1', + name: 'Remote1', + type: 'remote_elasticsearch', + is_default: false, + is_default_monitoring: false, + }, + ], + }, + }; + } + + return defaultHttpClientGetImplementation(path); + }); +}; + describe('useOutputOptions', () => { it('should generate enabled options if the licence is platinium', async () => { const testRenderer = createFleetTestRendererMock(); @@ -507,4 +532,21 @@ describe('useOutputOptions', () => { ] `); }); + + it('should only enable remote es output for monitoring output', async () => { + const testRenderer = createFleetTestRendererMock(); + mockedUseLicence.mockReturnValue({ + hasAtLeast: () => true, + } as unknown as LicenseService); + mockApiCallsWithRemoteESOutputs(testRenderer.startServices.http); + const { result, waitForNextUpdate } = testRenderer.renderHook(() => + useOutputOptions({} as AgentPolicy) + ); + expect(result.current.isLoading).toBeTruthy(); + + await waitForNextUpdate(); + expect(result.current.dataOutputOptions.length).toEqual(1); + expect(result.current.monitoringOutputOptions.length).toEqual(2); + expect(result.current.monitoringOutputOptions[1].value).toEqual('remote1'); + }); }); diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/components/agent_policy_advanced_fields/hooks.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/components/agent_policy_advanced_fields/hooks.tsx index 15681ea1dfbb6..9ee8b1f225735 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/components/agent_policy_advanced_fields/hooks.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/components/agent_policy_advanced_fields/hooks.tsx @@ -16,7 +16,7 @@ import { useGetDownloadSources, useGetFleetServerHosts, } from '../../../../hooks'; -import { LICENCE_FOR_PER_POLICY_OUTPUT } from '../../../../../../../common/constants'; +import { LICENCE_FOR_PER_POLICY_OUTPUT, outputType } from '../../../../../../../common/constants'; import { getAllowedOutputTypeForPolicy, policyHasFleetServer, @@ -99,26 +99,28 @@ export function useOutputOptions(agentPolicy: Partial { - const isOutputTypeUnsupported = !allowedOutputTypes.includes(item.type); + ...outputsRequest.data.items + .filter((item) => item.type !== outputType.RemoteElasticsearch) + .map((item) => { + const isOutputTypeUnsupported = !allowedOutputTypes.includes(item.type); - return { - value: item.id, - inputDisplay: getOutputLabel( - item.name, - isOutputTypeUnsupported ? ( - - ) : undefined - ), - disabled: !isPolicyPerOutputAllowed || isOutputTypeUnsupported, - }; - }), + return { + value: item.id, + inputDisplay: getOutputLabel( + item.name, + isOutputTypeUnsupported ? ( + + ) : undefined + ), + disabled: !isPolicyPerOutputAllowed || isOutputTypeUnsupported, + }; + }), ]; }, [outputsRequest, isPolicyPerOutputAllowed, allowedOutputTypes]); diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_requirements_page/fleet_server_requirement_page.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_requirements_page/fleet_server_requirement_page.tsx index fe089a6669c27..7d70e6969f789 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_requirements_page/fleet_server_requirement_page.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_requirements_page/fleet_server_requirement_page.tsx @@ -5,11 +5,11 @@ * 2.0. */ -import React, { useState, useEffect } from 'react'; +import React from 'react'; import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import styled from 'styled-components'; -import { useStartServices, sendGetPermissionsCheck } from '../../../hooks'; +import { useStartServices, useCheckPermissions } from '../../../hooks'; import { FleetServerMissingPrivileges } from '../components/fleet_server_callouts'; @@ -42,28 +42,7 @@ export const FleetServerRequirementPage: React.FunctionComponent< const startService = useStartServices(); const deploymentUrl = startService.cloud?.deploymentUrl; - const [isPermissionsLoading, setIsPermissionsLoading] = useState(false); - const [permissionsError, setPermissionsError] = useState(); - - useEffect(() => { - async function checkPermissions() { - setIsPermissionsLoading(false); - setPermissionsError(undefined); - - try { - setIsPermissionsLoading(true); - const permissionsResponse = await sendGetPermissionsCheck(true); - - setIsPermissionsLoading(false); - if (!permissionsResponse.data?.success) { - setPermissionsError(permissionsResponse.data?.error || 'REQUEST_ERROR'); - } - } catch (err) { - setPermissionsError('REQUEST_ERROR'); - } - } - checkPermissions(); - }, []); + const { permissionsError, isPermissionsLoading } = useCheckPermissions(); return ( <> diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/settings/components/edit_output_flyout/index.test.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/settings/components/edit_output_flyout/index.test.tsx index 46b367011395c..ddd68d8380419 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/settings/components/edit_output_flyout/index.test.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/settings/components/edit_output_flyout/index.test.tsx @@ -10,6 +10,7 @@ import React from 'react'; import type { Output } from '../../../../types'; import { createFleetTestRendererMock } from '../../../../../../mock'; import { useFleetStatus } from '../../../../../../hooks/use_fleet_status'; +import { ExperimentalFeaturesService } from '../../../../../../services'; import { EditOutputFlyout } from '.'; @@ -63,6 +64,8 @@ const kafkaSectionsLabels = [ 'Broker settings', ]; +const remoteEsOutputLabels = ['Hosts', 'Service Token']; + describe('EditOutputFlyout', () => { it('should render the flyout if there is not output provided', async () => { renderFlyout(); @@ -159,4 +162,20 @@ describe('EditOutputFlyout', () => { // Show logstash SSL inputs expect(utils.getByText('Additional setup required')).not.toBeNull(); }); + + it('should render the flyout if the output provided is a remote ES output', async () => { + jest.spyOn(ExperimentalFeaturesService, 'get').mockReturnValue({ remoteESOutput: true }); + const { utils } = renderFlyout({ + type: 'remote_elasticsearch', + name: 'remote es output', + id: 'outputR', + is_default: false, + is_default_monitoring: false, + }); + + remoteEsOutputLabels.forEach((label) => { + expect(utils.queryByLabelText(label)).not.toBeNull(); + }); + expect(utils.queryByTestId('serviceTokenCallout')).not.toBeNull(); + }); }); diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/settings/components/edit_output_flyout/index.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/settings/components/edit_output_flyout/index.tsx index bbf0ca39ffd41..b35162bc51667 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/settings/components/edit_output_flyout/index.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/settings/components/edit_output_flyout/index.tsx @@ -30,6 +30,7 @@ import { EuiComboBox, EuiBetaBadge, useEuiTheme, + EuiText, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; @@ -53,6 +54,8 @@ import { YamlCodeEditorWithPlaceholder } from './yaml_code_editor_with_placehold import { useOutputForm } from './use_output_form'; import { EncryptionKeyRequiredCallout } from './encryption_key_required_callout'; import { AdvancedOptionsSection } from './advanced_options_section'; +import { OutputFormRemoteEsSection } from './output_form_remote_es'; + export interface EditOutputFlyoutProps { output?: Output; onClose: () => void; @@ -81,10 +84,15 @@ export const EditOutputFlyout: React.FunctionComponent = [proxies] ); - const { kafkaOutput: isKafkaOutputEnabled } = ExperimentalFeaturesService.get(); + const { kafkaOutput: isKafkaOutputEnabled, remoteESOutput: isRemoteESOutputEnabled } = + ExperimentalFeaturesService.get(); + const isRemoteESOutput = inputs.typeInput.value === outputType.RemoteElasticsearch; const OUTPUT_TYPE_OPTIONS = [ { value: outputType.Elasticsearch, text: 'Elasticsearch' }, + ...(isRemoteESOutputEnabled + ? [{ value: outputType.RemoteElasticsearch, text: 'Remote Elasticsearch' }] + : []), { value: outputType.Logstash, text: 'Logstash' }, ...(isKafkaOutputEnabled ? [{ value: outputType.Kafka, text: 'Kafka' }] : []), ]; @@ -260,6 +268,13 @@ export const EditOutputFlyout: React.FunctionComponent = ); }; + const renderRemoteElasticsearchSection = () => { + if (isRemoteESOutputEnabled) { + return ; + } + return null; + }; + const renderKafkaSection = () => { if (isKafkaOutputEnabled) { return ( @@ -279,6 +294,8 @@ export const EditOutputFlyout: React.FunctionComponent = return renderLogstashSection(); case outputType.Kafka: return renderKafkaSection(); + case outputType.RemoteElasticsearch: + return renderRemoteElasticsearchSection(); case outputType.Elasticsearch: default: return renderElasticsearchSection(); @@ -288,7 +305,7 @@ export const EditOutputFlyout: React.FunctionComponent = const renderTypeSpecificWarning = () => { const isESOutput = inputs.typeInput.value === outputType.Elasticsearch; const isKafkaOutput = inputs.typeInput.value === outputType.Kafka; - if (!isKafkaOutput && !isESOutput) { + if (!isKafkaOutput && !isESOutput && !isRemoteESOutput) { return null; } @@ -303,11 +320,30 @@ export const EditOutputFlyout: React.FunctionComponent = case outputType.Elasticsearch: return i18n.translate('xpack.fleet.settings.editOutputFlyout.esOutputTypeCallout', { defaultMessage: - 'This output type currently does not support connectivity to a remote Elasticsearch cluster.', + 'This output type does not support connectivity to a remote Elasticsearch cluster, please the Remote Elasticsearch type for that.', }); } }; - return ( + return isRemoteESOutput ? ( + <> + + + + {i18n.translate('xpack.fleet.settings.editOutputFlyout.docLabel', { + defaultMessage: 'our documentation', + })} + + ), + }} + /> + + + ) : ( <> = {renderOutputTypeSection(inputs.typeInput.value)} - - } - > - inputs.proxyIdInput.setValue(options?.[0]?.value ?? '')} - selectedOptions={ - inputs.proxyIdInput.value !== '' - ? proxiesOptions.filter((option) => option.value === inputs.proxyIdInput.value) - : [] + label={ + } - options={proxiesOptions} - singleSelection={{ asPlainText: true }} - isDisabled={inputs.proxyIdInput.props.disabled} - isClearable={true} - placeholder={i18n.translate( - 'xpack.fleet.settings.editOutputFlyout.proxyIdPlaceholder', - { - defaultMessage: 'Select proxy', + > + inputs.proxyIdInput.setValue(options?.[0]?.value ?? '')} + selectedOptions={ + inputs.proxyIdInput.value !== '' + ? proxiesOptions.filter((option) => option.value === inputs.proxyIdInput.value) + : [] } - )} - /> - + options={proxiesOptions} + singleSelection={{ asPlainText: true }} + isDisabled={inputs.proxyIdInput.props.disabled} + isClearable={true} + placeholder={i18n.translate( + 'xpack.fleet.settings.editOutputFlyout.proxyIdPlaceholder', + { + defaultMessage: 'Select proxy', + } + )} + /> + + )} @@ -503,6 +541,7 @@ export const EditOutputFlyout: React.FunctionComponent = }} /> } + disabled={isRemoteESOutput} /> diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/settings/components/edit_output_flyout/output_form_remote_es.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/settings/components/edit_output_flyout/output_form_remote_es.tsx new file mode 100644 index 0000000000000..9b4c8f085af9a --- /dev/null +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/settings/components/edit_output_flyout/output_form_remote_es.tsx @@ -0,0 +1,82 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { EuiCallOut, EuiCodeBlock, EuiFieldText, EuiFormRow, EuiSpacer } from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n-react'; +import { i18n } from '@kbn/i18n'; + +import { MultiRowInput } from '../multi_row_input'; + +import type { OutputFormInputsType } from './use_output_form'; + +interface Props { + inputs: OutputFormInputsType; +} + +export const OutputFormRemoteEsSection: React.FunctionComponent = (props) => { + const { inputs } = props; + + return ( + <> + + + + } + {...inputs.serviceTokenInput.formRowProps} + > + + + + + } + data-test-subj="serviceTokenCallout" + > + + {`POST kbn:/api/fleet/service_tokens +{ + "remote": true +}`} + + + + + ); +}; diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/settings/components/edit_output_flyout/output_form_validators.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/settings/components/edit_output_flyout/output_form_validators.tsx index f163c5bd9950a..cee39bb1a0126 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/settings/components/edit_output_flyout/output_form_validators.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/settings/components/edit_output_flyout/output_form_validators.tsx @@ -260,6 +260,16 @@ export function validateCATrustedFingerPrint(value: string) { } } +export function validateServiceToken(value: string) { + if (!value || value === '') { + return [ + i18n.translate('xpack.fleet.settings.outputForm.serviceTokenRequiredErrorMessage', { + defaultMessage: 'Service Token is required', + }), + ]; + } +} + export function validateSSLCertificate(value: string) { if (!value || value === '') { return [ diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/settings/components/edit_output_flyout/use_output_form.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/settings/components/edit_output_flyout/use_output_form.tsx index 282b3433268ec..1a148105c50fa 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/settings/components/edit_output_flyout/use_output_form.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/settings/components/edit_output_flyout/use_output_form.tsx @@ -15,6 +15,7 @@ import type { NewElasticsearchOutput, NewLogstashOutput, NewOutput, + NewRemoteElasticsearchOutput, } from '../../../../../../../common/types/models'; import { @@ -53,6 +54,7 @@ import { validateLogstashHosts, validateYamlConfig, validateCATrustedFingerPrint, + validateServiceToken, validateSSLCertificate, validateSSLKey, validateSSLKeySecret, @@ -85,6 +87,7 @@ export interface OutputFormInputsType { defaultOutputInput: ReturnType; defaultMonitoringOutputInput: ReturnType; caTrustedFingerprintInput: ReturnType; + serviceTokenInput: ReturnType; sslCertificateInput: ReturnType; sslKeyInput: ReturnType; sslKeySecretInput: ReturnType; @@ -165,7 +168,9 @@ export function useOutputForm(onSucess: () => void, output?: Output) { const isPreconfigured = output?.is_preconfigured ?? false; const allowEdit = output?.allow_edit ?? []; - function isDisabled(field: keyof Output | keyof KafkaOutput) { + function isDisabled( + field: keyof Output | keyof KafkaOutput | keyof NewRemoteElasticsearchOutput + ) { if (!isPreconfigured) { return false; } @@ -203,6 +208,13 @@ export function useOutputForm(onSucess: () => void, output?: Output) { validateESHosts, isDisabled('hosts') ); + + // Remtote ES inputs + const serviceTokenInput = useInput( + (output as NewRemoteElasticsearchOutput)?.service_token ?? '', + validateServiceToken, + isDisabled('service_token') + ); /* Shipper feature flag - currently depends on the content of the yaml # Enables the shipper: @@ -473,6 +485,7 @@ export function useOutputForm(onSucess: () => void, output?: Output) { const isLogstash = typeInput.value === outputType.Logstash; const isKafka = typeInput.value === outputType.Kafka; + const isRemoteElasticsearch = typeInput.value === outputType.RemoteElasticsearch; const inputs: OutputFormInputsType = { nameInput, @@ -489,6 +502,7 @@ export function useOutputForm(onSucess: () => void, output?: Output) { defaultOutputInput, defaultMonitoringOutputInput, caTrustedFingerprintInput, + serviceTokenInput, sslCertificateInput, sslKeyInput, sslKeySecretInput, @@ -547,6 +561,7 @@ export function useOutputForm(onSucess: () => void, output?: Output) { const logstashHostsValid = logstashHostsInput.validate(); const additionalYamlConfigValid = additionalYamlConfigInput.validate(); const caTrustedFingerprintValid = caTrustedFingerprintInput.validate(); + const serviceTokenValid = serviceTokenInput.validate(); const sslCertificateValid = sslCertificateInput.validate(); const sslKeyValid = sslKeyInput.validate(); const sslKeySecretValid = sslKeySecretInput.validate(); @@ -589,6 +604,11 @@ export function useOutputForm(onSucess: () => void, output?: Output) { partitioningRandomGroupEventsValid && partitioningRoundRobinGroupEventsValid ); + } + if (isRemoteElasticsearch) { + return ( + elasticsearchUrlsValid && additionalYamlConfigValid && nameInputValid && serviceTokenValid + ); } else { // validate ES return ( @@ -616,6 +636,7 @@ export function useOutputForm(onSucess: () => void, output?: Output) { logstashHostsInput, additionalYamlConfigInput, caTrustedFingerprintInput, + serviceTokenInput, sslCertificateInput, sslKeyInput, sslKeySecretInput, @@ -624,6 +645,7 @@ export function useOutputForm(onSucess: () => void, output?: Output) { kafkaPartitionTypeRoundRobinInput, isLogstash, isKafka, + isRemoteElasticsearch, ]); const submit = useCallback(async () => { @@ -821,6 +843,18 @@ export function useOutputForm(onSucess: () => void, output?: Output) { proxy_id: proxyIdValue, ...shipperParams, } as NewLogstashOutput; + case outputType.RemoteElasticsearch: + return { + name: nameInput.value, + type: outputType.RemoteElasticsearch, + hosts: elasticsearchUrlInput.value, + is_default: false, + is_default_monitoring: defaultMonitoringOutputInput.value, + config_yaml: additionalYamlConfigInput.value, + service_token: serviceTokenInput.value, + proxy_id: proxyIdValue, + ...shipperParams, + } as NewRemoteElasticsearchOutput; case outputType.Elasticsearch: default: return { @@ -923,6 +957,7 @@ export function useOutputForm(onSucess: () => void, output?: Output) { sslCertificateAuthoritiesInput.value, elasticsearchUrlInput.value, caTrustedFingerprintInput.value, + serviceTokenInput.value, confirm, notifications.toasts, ]); diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/settings/components/outputs_table/index.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/settings/components/outputs_table/index.tsx index 464c512ecf8e0..fe05e00f795d7 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/settings/components/outputs_table/index.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/settings/components/outputs_table/index.tsx @@ -36,6 +36,10 @@ function displayOutputType(type: string) { return i18n.translate('xpack.fleet.settings.outputsTable.elasticsearchTypeLabel', { defaultMessage: 'Elasticsearch', }); + case 'remote_elasticsearch': + return i18n.translate('xpack.fleet.settings.outputsTable.remoteElasticsearchTypeLabel', { + defaultMessage: 'Remote Elasticsearch', + }); default: return type; } diff --git a/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/cloud_formation_instructions.tsx b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/cloud_formation_instructions.tsx index daee7d9d8955c..88d129ab7909f 100644 --- a/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/cloud_formation_instructions.tsx +++ b/x-pack/plugins/fleet/public/components/agent_enrollment_flyout/cloud_formation_instructions.tsx @@ -58,6 +58,7 @@ export const CloudFormationInstructions: React.FunctionComponent = ({ /> = ({ { }); }; -export const sendGenerateServiceToken = () => { +export const sendGenerateServiceToken = (remote?: boolean) => { return sendRequest({ path: appRoutesService.getRegenerateServiceTokenPath(), method: 'post', + query: { remote }, version: API_VERSIONS.public.v1, }); }; diff --git a/x-pack/plugins/fleet/server/constants/fleet_es_assets.ts b/x-pack/plugins/fleet/server/constants/fleet_es_assets.ts index c33a53f4dd4a6..b90be40075d8e 100644 --- a/x-pack/plugins/fleet/server/constants/fleet_es_assets.ts +++ b/x-pack/plugins/fleet/server/constants/fleet_es_assets.ts @@ -11,7 +11,7 @@ import { getESAssetMetadata } from '../services/epm/elasticsearch/meta'; const meta = getESAssetMetadata(); -export const FLEET_INSTALL_FORMAT_VERSION = '1.0.0'; +export const FLEET_INSTALL_FORMAT_VERSION = '1.1.0'; export const FLEET_AGENT_POLICIES_SCHEMA_VERSION = '1.1.1'; @@ -81,6 +81,16 @@ export const FLEET_COMPONENT_TEMPLATES = [ }, ]; +export const STACK_COMPONENT_TEMPLATE_LOGS_SETTINGS = `logs@settings`; +export const STACK_COMPONENT_TEMPLATE_METRICS_SETTINGS = `metrics@settings`; +export const STACK_COMPONENT_TEMPLATE_METRICS_TSDB_SETTINGS = `metrics@tsdb-settings`; + +export const STACK_COMPONENT_TEMPLATES = [ + STACK_COMPONENT_TEMPLATE_LOGS_SETTINGS, + STACK_COMPONENT_TEMPLATE_METRICS_SETTINGS, + STACK_COMPONENT_TEMPLATE_METRICS_TSDB_SETTINGS, +]; + export const FLEET_FINAL_PIPELINE_VERSION = 4; // If the content is updated you probably need to update the FLEET_FINAL_PIPELINE_VERSION too to allow upgrade of the pipeline diff --git a/x-pack/plugins/fleet/server/constants/index.ts b/x-pack/plugins/fleet/server/constants/index.ts index 37e570648e392..7a03f7c33ab3d 100644 --- a/x-pack/plugins/fleet/server/constants/index.ts +++ b/x-pack/plugins/fleet/server/constants/index.ts @@ -95,6 +95,10 @@ export { FLEET_FINAL_PIPELINE_VERSION, FLEET_INSTALL_FORMAT_VERSION, FLEET_AGENT_POLICIES_SCHEMA_VERSION, + STACK_COMPONENT_TEMPLATE_LOGS_SETTINGS, + STACK_COMPONENT_TEMPLATE_METRICS_SETTINGS, + STACK_COMPONENT_TEMPLATE_METRICS_TSDB_SETTINGS, + STACK_COMPONENT_TEMPLATES, } from './fleet_es_assets'; export { FILE_STORAGE_DATA_AGENT_INDEX } from './fleet_es_assets'; export { FILE_STORAGE_METADATA_AGENT_INDEX } from './fleet_es_assets'; diff --git a/x-pack/plugins/fleet/server/plugin.ts b/x-pack/plugins/fleet/server/plugin.ts index e6310a0b0da59..0373971c664e2 100644 --- a/x-pack/plugins/fleet/server/plugin.ts +++ b/x-pack/plugins/fleet/server/plugin.ts @@ -473,6 +473,7 @@ export class FleetPlugin public start(core: CoreStart, plugins: FleetStartDeps): FleetStartContract { const messageSigningService = new MessageSigningService( + this.initializerContext.logger, plugins.encryptedSavedObjects.getClient({ includedHiddenTypes: [MESSAGE_SIGNING_KEYS_SAVED_OBJECT_TYPE], }) diff --git a/x-pack/plugins/fleet/server/routes/app/index.ts b/x-pack/plugins/fleet/server/routes/app/index.ts index cb7b5f284962d..8d8ae60ad0225 100644 --- a/x-pack/plugins/fleet/server/routes/app/index.ts +++ b/x-pack/plugins/fleet/server/routes/app/index.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { RequestHandler } from '@kbn/core/server'; +import type { RequestHandler, RouteValidationResultFactory } from '@kbn/core/server'; import type { TypeOf } from '@kbn/config-schema'; import type { FleetAuthzRouter } from '../../services/security'; @@ -16,7 +16,7 @@ import { API_VERSIONS, INTERNAL_API_ACCESS } from '../../../common/constants'; import { appContextService } from '../../services'; import type { CheckPermissionsResponse, GenerateServiceTokenResponse } from '../../../common/types'; import { defaultFleetErrorHandler, GenerateServiceTokenError } from '../../errors'; -import type { FleetRequestHandler } from '../../types'; +import type { FleetRequestHandler, GenerateServiceTokenRequestSchema } from '../../types'; import { CheckPermissionsRequestSchema } from '../../types'; export const getCheckPermissionsHandler: FleetRequestHandler< @@ -61,16 +61,24 @@ export const getCheckPermissionsHandler: FleetRequestHandler< } }; -export const generateServiceTokenHandler: RequestHandler = async (context, request, response) => { +export const generateServiceTokenHandler: RequestHandler< + null, + null, + TypeOf +> = async (context, request, response) => { // Generate the fleet server service token as the current user as the internal user do not have the correct permissions const esClient = (await context.core).elasticsearch.client.asCurrentUser; + const serviceAccount = request.body.remote ? 'fleet-server-remote' : 'fleet-server'; + appContextService + .getLogger() + .debug(`Creating service token for account elastic/${serviceAccount}`); try { const tokenResponse = await esClient.transport.request<{ created?: boolean; token?: GenerateServiceTokenResponse; }>({ method: 'POST', - path: `_security/service/elastic/fleet-server/credential/token/token-${Date.now()}`, + path: `_security/service/elastic/${serviceAccount}/credential/token/token-${Date.now()}`, }); if (tokenResponse.created && tokenResponse.token) { @@ -88,6 +96,15 @@ export const generateServiceTokenHandler: RequestHandler = async (context, reque } }; +const serviceTokenBodyValidation = (data: any, validationResult: RouteValidationResultFactory) => { + const { ok } = validationResult; + if (!data) { + return ok({ remote: false }); + } + const { remote } = data; + return ok({ remote }); +}; + export const registerRoutes = (router: FleetAuthzRouter) => { router.versioned .get({ @@ -111,9 +128,10 @@ export const registerRoutes = (router: FleetAuthzRouter) => { .addVersion( { version: API_VERSIONS.public.v1, - validate: {}, + validate: { + request: { body: serviceTokenBodyValidation }, + }, }, - generateServiceTokenHandler ); diff --git a/x-pack/plugins/fleet/server/saved_objects/index.ts b/x-pack/plugins/fleet/server/saved_objects/index.ts index 7458fad2459b6..7c68ab9105e49 100644 --- a/x-pack/plugins/fleet/server/saved_objects/index.ts +++ b/x-pack/plugins/fleet/server/saved_objects/index.ts @@ -176,6 +176,7 @@ const getSavedObjectTypes = (): { [key: string]: SavedObjectsType } => ({ hosts: { type: 'keyword' }, ca_sha256: { type: 'keyword', index: false }, ca_trusted_fingerprint: { type: 'keyword', index: false }, + service_token: { type: 'keyword', index: false }, config: { type: 'flattened' }, config_yaml: { type: 'text' }, is_preconfigured: { type: 'boolean', index: false }, @@ -291,6 +292,16 @@ const getSavedObjectTypes = (): { [key: string]: SavedObjectsType } => ({ forwardCompatibility: migrateOutputEvictionsFromV8100, }, }, + '2': { + changes: [ + { + type: 'mappings_addition', + addedMappings: { + service_token: { type: 'keyword', index: false }, + }, + }, + ], + }, }, migrations: { '7.13.0': migrateOutputToV7130, diff --git a/x-pack/plugins/fleet/server/services/agent_policies/full_agent_policy.ts b/x-pack/plugins/fleet/server/services/agent_policies/full_agent_policy.ts index ffa681fdf0d40..dcb9ac0d0b89f 100644 --- a/x-pack/plugins/fleet/server/services/agent_policies/full_agent_policy.ts +++ b/x-pack/plugins/fleet/server/services/agent_policies/full_agent_policy.ts @@ -206,7 +206,10 @@ export async function getFullAgentPolicy( NonNullable >((outputPermissions, outputId) => { const output = fullAgentPolicy.outputs[outputId]; - if (output && output.type === outputType.Elasticsearch) { + if ( + output && + (output.type === outputType.Elasticsearch || output.type === outputType.RemoteElasticsearch) + ) { const permissions: FullAgentPolicyOutputPermissions = {}; if (outputId === getOutputIdForAgentPolicy(monitoringOutput)) { Object.assign(permissions, monitoringPermissions); @@ -475,6 +478,10 @@ export function transformOutputToFullPolicyOutput( newOutput.password = '${ES_PASSWORD}'; } + if (output.type === outputType.RemoteElasticsearch) { + newOutput.service_token = output.service_token; + } + return newOutput; } diff --git a/x-pack/plugins/fleet/server/services/epm/elasticsearch/ingest_pipeline/helpers.test.ts b/x-pack/plugins/fleet/server/services/epm/elasticsearch/ingest_pipeline/helpers.test.ts index d43849d216810..ebffc0064b989 100644 --- a/x-pack/plugins/fleet/server/services/epm/elasticsearch/ingest_pipeline/helpers.test.ts +++ b/x-pack/plugins/fleet/server/services/epm/elasticsearch/ingest_pipeline/helpers.test.ts @@ -153,19 +153,16 @@ processors: `, extension: 'yml', nameForInstallation: 'logs-test-1.0.0', - customIngestPipelineNameForInstallation: 'logs-test@custom', + shouldInstallCustomPipelines: true, }); expect(pipelineInstall.contentForInstallation).toMatchInlineSnapshot(` - "--- + " processors: - set: field: test value: toto - - pipeline: - name: logs-test@custom - ignore_missing_pipeline: true - " + " `); }); @@ -183,11 +180,15 @@ processors: }`, extension: 'json', nameForInstallation: 'logs-test-1.0.0', - customIngestPipelineNameForInstallation: 'logs-test@custom', + dataStream: { + type: 'logs', + dataset: 'test', + } as any, + shouldInstallCustomPipelines: true, }); expect(pipelineInstall.contentForInstallation).toMatchInlineSnapshot( - `"{\\"processors\\":[{\\"set\\":{\\"field\\":\\"test\\",\\"value\\":\\"toto\\"}},{\\"pipeline\\":{\\"name\\":\\"logs-test@custom\\",\\"ignore_missing_pipeline\\":true}}]}"` + `"{\\"processors\\":[{\\"set\\":{\\"field\\":\\"test\\",\\"value\\":\\"toto\\"}},{\\"pipeline\\":{\\"name\\":\\"global@custom\\",\\"ignore_missing_pipeline\\":true}},{\\"pipeline\\":{\\"name\\":\\"logs@custom\\",\\"ignore_missing_pipeline\\":true}},{\\"pipeline\\":{\\"name\\":\\"logs-test@custom\\",\\"ignore_missing_pipeline\\":true}}]}"` ); }); @@ -202,12 +203,13 @@ processors: `, extension: 'yml', nameForInstallation: 'logs-test-1.0.0', - customIngestPipelineNameForInstallation: 'logs-test@custom', + shouldInstallCustomPipelines: true, dataStream: { - dataset: 'test', + type: 'logs', + dataset: 'test.access', routing_rules: [ { - source_dataset: 'test', + source_dataset: 'test.access', rules: [ { target_dataset: 'test.reroute', @@ -221,21 +223,27 @@ processors: }); expect(pipelineInstall.contentForInstallation).toMatchInlineSnapshot(` - "--- - processors: - - set: - field: test - value: toto - - pipeline: - name: logs-test@custom - ignore_missing_pipeline: true - - reroute: - tag: test - dataset: test.reroute - namespace: default - if: true == true - " - `); + "--- + processors: + - set: + field: test + value: toto + - pipeline: + name: global@custom + ignore_missing_pipeline: true + - pipeline: + name: logs@custom + ignore_missing_pipeline: true + - pipeline: + name: logs-test.access@custom + ignore_missing_pipeline: true + - reroute: + tag: test.access + dataset: test.reroute + namespace: default + if: true == true + " + `); }); it('add reroute processor after custom pipeline processor for json pipeline', () => { @@ -252,12 +260,13 @@ processors: }`, extension: 'json', nameForInstallation: 'logs-test-1.0.0', - customIngestPipelineNameForInstallation: 'logs-test@custom', + shouldInstallCustomPipelines: true, dataStream: { - dataset: 'test', + type: 'logs', + dataset: 'test.access', routing_rules: [ { - source_dataset: 'test', + source_dataset: 'test.access', rules: [ { target_dataset: 'test.reroute', @@ -271,7 +280,7 @@ processors: }); expect(pipelineInstall.contentForInstallation).toMatchInlineSnapshot( - `"{\\"processors\\":[{\\"set\\":{\\"field\\":\\"test\\",\\"value\\":\\"toto\\"}},{\\"pipeline\\":{\\"name\\":\\"logs-test@custom\\",\\"ignore_missing_pipeline\\":true}},{\\"reroute\\":{\\"tag\\":\\"test\\",\\"dataset\\":\\"test.reroute\\",\\"namespace\\":\\"default\\",\\"if\\":\\"true == true\\"}}]}"` + `"{\\"processors\\":[{\\"set\\":{\\"field\\":\\"test\\",\\"value\\":\\"toto\\"}},{\\"pipeline\\":{\\"name\\":\\"global@custom\\",\\"ignore_missing_pipeline\\":true}},{\\"pipeline\\":{\\"name\\":\\"logs@custom\\",\\"ignore_missing_pipeline\\":true}},{\\"pipeline\\":{\\"name\\":\\"logs-test.access@custom\\",\\"ignore_missing_pipeline\\":true}},{\\"reroute\\":{\\"tag\\":\\"test.access\\",\\"dataset\\":\\"test.reroute\\",\\"namespace\\":\\"default\\",\\"if\\":\\"true == true\\"}}]}"` ); }); }); diff --git a/x-pack/plugins/fleet/server/services/epm/elasticsearch/ingest_pipeline/helpers.ts b/x-pack/plugins/fleet/server/services/epm/elasticsearch/ingest_pipeline/helpers.ts index 1be2b2b895896..9c244821fd013 100644 --- a/x-pack/plugins/fleet/server/services/epm/elasticsearch/ingest_pipeline/helpers.ts +++ b/x-pack/plugins/fleet/server/services/epm/elasticsearch/ingest_pipeline/helpers.ts @@ -72,7 +72,7 @@ function mutatePipelineContentWithNewProcessor(jsonPipelineContent: any, process export function addCustomPipelineAndLocalRoutingRulesProcessor( pipeline: PipelineInstall ): PipelineInstall { - if (!pipeline.customIngestPipelineNameForInstallation) { + if (!pipeline.shouldInstallCustomPipelines || !pipeline.dataStream) { return pipeline; } @@ -80,13 +80,37 @@ export function addCustomPipelineAndLocalRoutingRulesProcessor( pipeline.dataStream?.routing_rules?.find( (rule) => rule.source_dataset === pipeline.dataStream?.dataset )?.rules ?? []; - - const customPipelineProcessor = { - pipeline: { - name: pipeline.customIngestPipelineNameForInstallation, - ignore_missing_pipeline: true, + const customPipelineProcessors = [ + { + pipeline: { + name: 'global@custom', + ignore_missing_pipeline: true, + }, }, - }; + { + pipeline: { + name: `${pipeline.dataStream.type}@custom`, + ignore_missing_pipeline: true, + }, + }, + ...(pipeline.dataStream.package + ? [ + { + pipeline: { + name: `${pipeline.dataStream.type}-${pipeline.dataStream.package}@custom`, + ignore_missing_pipeline: true, + }, + }, + ] + : []), + { + pipeline: { + name: `${pipeline.dataStream.type}-${pipeline.dataStream.dataset}@custom`, + ignore_missing_pipeline: true, + }, + }, + ]; + const rerouteProcessors = localRoutingRules.map((routingRule) => ({ reroute: { tag: pipeline.dataStream?.dataset, @@ -98,7 +122,9 @@ export function addCustomPipelineAndLocalRoutingRulesProcessor( if (pipeline.extension === 'yml') { const parsedPipelineContent = safeLoad(pipeline.contentForInstallation); - mutatePipelineContentWithNewProcessor(parsedPipelineContent, customPipelineProcessor); + customPipelineProcessors.forEach((processor) => + mutatePipelineContentWithNewProcessor(parsedPipelineContent, processor) + ); rerouteProcessors.forEach((processor) => mutatePipelineContentWithNewProcessor(parsedPipelineContent, processor) ); @@ -109,7 +135,9 @@ export function addCustomPipelineAndLocalRoutingRulesProcessor( } const parsedPipelineContent = JSON.parse(pipeline.contentForInstallation); - mutatePipelineContentWithNewProcessor(parsedPipelineContent, customPipelineProcessor); + customPipelineProcessors.forEach((processor) => + mutatePipelineContentWithNewProcessor(parsedPipelineContent, processor) + ); rerouteProcessors.forEach((processor) => mutatePipelineContentWithNewProcessor(parsedPipelineContent, processor) ); diff --git a/x-pack/plugins/fleet/server/services/epm/elasticsearch/ingest_pipeline/install.ts b/x-pack/plugins/fleet/server/services/epm/elasticsearch/ingest_pipeline/install.ts index 1ae0d8a9d67fa..e30bc5b32a771 100644 --- a/x-pack/plugins/fleet/server/services/epm/elasticsearch/ingest_pipeline/install.ts +++ b/x-pack/plugins/fleet/server/services/epm/elasticsearch/ingest_pipeline/install.ts @@ -22,10 +22,7 @@ import { FLEET_FINAL_PIPELINE_ID, FLEET_FINAL_PIPELINE_VERSION, } from '../../../../constants'; -import { - getCustomPipelineNameForDatastream, - getPipelineNameForDatastream, -} from '../../../../../common/services'; +import { getPipelineNameForDatastream } from '../../../../../common/services'; import { appendMetadataToIngestPipeline } from '../meta'; import { retryTransientEsErrors } from '../retry'; @@ -172,8 +169,7 @@ export async function installAllPipelines({ const content = getAsset(path).toString('utf-8'); pipelinesInfos.push({ nameForInstallation, - customIngestPipelineNameForInstallation: - dataStream && isMainPipeline ? getCustomPipelineNameForDatastream(dataStream) : undefined, + shouldInstallCustomPipelines: dataStream && isMainPipeline, dataStream, content, extension, @@ -200,7 +196,7 @@ export async function installAllPipelines({ pipelinesToInstall.push({ nameForInstallation, - customIngestPipelineNameForInstallation: getCustomPipelineNameForDatastream(dataStream), + shouldInstallCustomPipelines: true, dataStream, contentForInstallation: 'processors: []', extension: 'yml', diff --git a/x-pack/plugins/fleet/server/services/epm/elasticsearch/ingest_pipeline/types.ts b/x-pack/plugins/fleet/server/services/epm/elasticsearch/ingest_pipeline/types.ts index 329fc744320e1..c8146e940cf8c 100644 --- a/x-pack/plugins/fleet/server/services/epm/elasticsearch/ingest_pipeline/types.ts +++ b/x-pack/plugins/fleet/server/services/epm/elasticsearch/ingest_pipeline/types.ts @@ -10,7 +10,7 @@ import type { RegistryDataStream } from '../../../../types'; export interface PipelineInstall { nameForInstallation: string; contentForInstallation: string; - customIngestPipelineNameForInstallation?: string; + shouldInstallCustomPipelines?: boolean; extension: string; dataStream?: RegistryDataStream; } diff --git a/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/default_settings.test.ts b/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/default_settings.test.ts index 3f7fa91b6462c..6452671644763 100644 --- a/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/default_settings.test.ts +++ b/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/default_settings.test.ts @@ -65,13 +65,9 @@ describe('buildDefaultSettings', () => { expect(settings).toMatchInlineSnapshot(` Object { "index": Object { - "codec": "best_compression", "lifecycle": Object { "name": "logs", }, - "mapping": Object { - "ignore_malformed": true, - }, "query": Object { "default_field": Array [ "field1Keyword", diff --git a/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/default_settings.ts b/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/default_settings.ts index dc61f4fca9e5c..6d42f106464b4 100644 --- a/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/default_settings.ts +++ b/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/default_settings.ts @@ -73,16 +73,6 @@ export function buildDefaultSettings({ name: ilmPolicy ? ilmPolicy : type, }, }), - // What should be our default for the compression? - codec: 'best_compression', - // setting `ignore_malformed` only for data_stream for logs - ...(type === 'logs' - ? { - mapping: { - ignore_malformed: true, - }, - } - : {}), // All the default fields which should be queried have to be added here. // So far we add all keyword and text fields here if there are any, otherwise // this setting is skipped. diff --git a/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/install.test.ts b/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/install.test.ts index bf15db1151744..321e832115cf0 100644 --- a/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/install.test.ts +++ b/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/install.test.ts @@ -7,9 +7,9 @@ import { createAppContextStartContractMock } from '../../../../mocks'; import { appContextService } from '../../..'; import { loadFieldsFromYaml } from '../../fields/field'; -import type { RegistryDataStream } from '../../../../types'; +import type { ArchivePackage, RegistryDataStream } from '../../../../types'; -import { prepareTemplate } from './install'; +import { prepareTemplate, prepareToInstallTemplates } from './install'; jest.mock('../../fields/field', () => ({ ...jest.requireActual('../../fields/field'), @@ -455,4 +455,28 @@ describe('EPM index template install', () => { expect(packageTemplate).not.toHaveProperty('lifecycle'); }); + + test('test prepareToInstallTemplates does not include stack component templates in tracked assets', () => { + const dataStreamDatasetIsPrefixUnset = { + type: 'logs', + dataset: 'package.dataset', + title: 'test data stream', + release: 'experimental', + package: 'package', + path: 'path', + ingest_pipeline: 'default', + } as RegistryDataStream; + + const { assetsToAdd } = prepareToInstallTemplates( + { + name: 'package', + version: '0.0.1', + data_streams: [dataStreamDatasetIsPrefixUnset], + } as ArchivePackage, + [], + [] + ); + + expect(assetsToAdd).not.toContainEqual({ id: 'logs@settings', type: 'component_template' }); + }); }); diff --git a/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/install.ts b/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/install.ts index ea7ccc88f2a4f..d65d8de5a3828 100644 --- a/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/install.ts +++ b/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/install.ts @@ -38,6 +38,7 @@ import { FLEET_COMPONENT_TEMPLATES, PACKAGE_TEMPLATE_SUFFIX, USER_SETTINGS_TEMPLATE_SUFFIX, + STACK_COMPONENT_TEMPLATES, } from '../../../../constants'; import { getESAssetMetadata } from '../meta'; @@ -530,7 +531,7 @@ export function prepareTemplate({ const isIndexModeTimeSeries = dataStream.elasticsearch?.index_mode === 'time_series' || - experimentalDataStreamFeature?.features.tsdb; + !!experimentalDataStreamFeature?.features.tsdb; const validFields = processFields(fields); @@ -572,6 +573,7 @@ export function prepareTemplate({ registryElasticsearch: dataStream.elasticsearch, mappings, isIndexModeTimeSeries, + type: dataStream.type, }); return { @@ -616,6 +618,8 @@ export function getAllTemplateRefs(installedTemplates: IndexTemplateEntry[]) { .filter( (componentTemplateId) => !FLEET_COMPONENT_TEMPLATE_NAMES.includes(componentTemplateId) ) + // Filter stack component templates shared between integrations + .filter((componentTemplateId) => !STACK_COMPONENT_TEMPLATES.includes(componentTemplateId)) .map((componentTemplateId) => ({ id: componentTemplateId, type: ElasticsearchAssetType.componentTemplate, diff --git a/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/template.test.ts b/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/template.test.ts index f0459b10c8570..59e5c68fb7345 100644 --- a/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/template.test.ts +++ b/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/template.test.ts @@ -57,10 +57,12 @@ describe('EPM template', () => { const template = getTemplate({ templateIndexPattern, + type: 'logs', packageName: 'nginx', composedOfTemplates: [], templatePriority: 200, mappings: { properties: [] }, + isIndexModeTimeSeries: false, }); expect(template.index_patterns).toStrictEqual([templateIndexPattern]); }); @@ -69,13 +71,35 @@ describe('EPM template', () => { const composedOfTemplates = ['component1', 'component2']; const template = getTemplate({ - templateIndexPattern: 'name-*', + templateIndexPattern: 'logs-*', + type: 'logs', packageName: 'nginx', composedOfTemplates, templatePriority: 200, mappings: { properties: [] }, + isIndexModeTimeSeries: false, }); expect(template.composed_of).toStrictEqual([ + 'logs@settings', + ...composedOfTemplates, + ...FLEET_COMPONENT_TEMPLATES_NAMES, + ]); + }); + + it('supplies metrics@tsdb-settings for time series', () => { + const composedOfTemplates = ['component1', 'component2']; + + const template = getTemplate({ + templateIndexPattern: 'metrics-*', + type: 'metrics', + packageName: 'nginx', + composedOfTemplates, + templatePriority: 200, + mappings: { properties: [] }, + isIndexModeTimeSeries: true, + }); + expect(template.composed_of).toStrictEqual([ + 'metrics@tsdb-settings', ...composedOfTemplates, ...FLEET_COMPONENT_TEMPLATES_NAMES, ]); @@ -90,13 +114,16 @@ describe('EPM template', () => { const composedOfTemplates = ['component1', 'component2']; const template = getTemplate({ - templateIndexPattern: 'name-*', + templateIndexPattern: 'logs-*', + type: 'logs', packageName: 'nginx', composedOfTemplates, templatePriority: 200, mappings: { properties: [] }, + isIndexModeTimeSeries: false, }); expect(template.composed_of).toStrictEqual([ + 'logs@settings', ...composedOfTemplates, FLEET_GLOBALS_COMPONENT_TEMPLATE_NAME, ]); @@ -106,13 +133,18 @@ describe('EPM template', () => { const composedOfTemplates: string[] = []; const template = getTemplate({ - templateIndexPattern: 'name-*', + templateIndexPattern: 'logs-*', + type: 'logs', packageName: 'nginx', composedOfTemplates, templatePriority: 200, mappings: { properties: [] }, + isIndexModeTimeSeries: false, }); - expect(template.composed_of).toStrictEqual(FLEET_COMPONENT_TEMPLATES_NAMES); + expect(template.composed_of).toStrictEqual([ + 'logs@settings', + ...FLEET_COMPONENT_TEMPLATES_NAMES, + ]); }); it('adds hidden field correctly', () => { @@ -120,20 +152,24 @@ describe('EPM template', () => { const templateWithHidden = getTemplate({ templateIndexPattern, + type: 'logs', packageName: 'nginx', composedOfTemplates: [], templatePriority: 200, hidden: true, mappings: { properties: [] }, + isIndexModeTimeSeries: false, }); expect(templateWithHidden.data_stream.hidden).toEqual(true); const templateWithoutHidden = getTemplate({ templateIndexPattern, + type: 'logs', packageName: 'nginx', composedOfTemplates: [], templatePriority: 200, mappings: { properties: [] }, + isIndexModeTimeSeries: false, }); expect(templateWithoutHidden.data_stream.hidden).toEqual(undefined); }); @@ -143,6 +179,7 @@ describe('EPM template', () => { const templateWithGlobalAndDataStreamHidden = getTemplate({ templateIndexPattern, + type: 'logs', packageName: 'nginx', composedOfTemplates: [], templatePriority: 200, @@ -153,11 +190,13 @@ describe('EPM template', () => { hidden: true, }, }, + isIndexModeTimeSeries: false, }); expect(templateWithGlobalAndDataStreamHidden.data_stream.hidden).toEqual(true); const templateWithDataStreamHidden = getTemplate({ templateIndexPattern, + type: 'logs', packageName: 'nginx', composedOfTemplates: [], templatePriority: 200, @@ -167,21 +206,25 @@ describe('EPM template', () => { hidden: true, }, }, + isIndexModeTimeSeries: false, }); expect(templateWithDataStreamHidden.data_stream.hidden).toEqual(true); const templateWithoutDataStreamHidden = getTemplate({ templateIndexPattern, + type: 'logs', packageName: 'nginx', composedOfTemplates: [], templatePriority: 200, hidden: true, mappings: { properties: [] }, + isIndexModeTimeSeries: false, }); expect(templateWithoutDataStreamHidden.data_stream.hidden).toEqual(true); const templateWithGlobalHiddenTrueAndDataStreamHiddenFalse = getTemplate({ templateIndexPattern, + type: 'logs', packageName: 'nginx', composedOfTemplates: [], templatePriority: 200, @@ -192,15 +235,18 @@ describe('EPM template', () => { hidden: false, }, }, + isIndexModeTimeSeries: false, }); expect(templateWithGlobalHiddenTrueAndDataStreamHiddenFalse.data_stream.hidden).toEqual(true); const templateWithoutHidden = getTemplate({ templateIndexPattern, + type: 'logs', packageName: 'nginx', composedOfTemplates: [], templatePriority: 200, mappings: { properties: [] }, + isIndexModeTimeSeries: false, }); expect(templateWithoutHidden.data_stream.hidden).toEqual(undefined); }); diff --git a/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/template.ts b/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/template.ts index 36e13ae331f58..26c6926c0bbc4 100644 --- a/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/template.ts +++ b/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/template.ts @@ -27,6 +27,9 @@ import { getRegistryDataStreamAssetBaseName } from '../../../../../common/servic import { FLEET_GLOBALS_COMPONENT_TEMPLATE_NAME, FLEET_AGENT_ID_VERIFY_COMPONENT_TEMPLATE_NAME, + STACK_COMPONENT_TEMPLATE_LOGS_SETTINGS, + STACK_COMPONENT_TEMPLATE_METRICS_SETTINGS, + STACK_COMPONENT_TEMPLATE_METRICS_TSDB_SETTINGS, } from '../../../../constants'; import { getESAssetMetadata } from '../meta'; import { retryTransientEsErrors } from '../retry'; @@ -76,12 +79,14 @@ export function getTemplate({ registryElasticsearch, mappings, isIndexModeTimeSeries, + type, }: { templateIndexPattern: string; packageName: string; composedOfTemplates: string[]; templatePriority: number; mappings: IndexTemplateMappings; + type: string; hidden?: boolean; registryElasticsearch?: RegistryElasticsearch | undefined; isIndexModeTimeSeries?: boolean; @@ -100,7 +105,10 @@ export function getTemplate({ throw new Error(`Error template for ${templateIndexPattern} contains a final_pipeline`); } + const esBaseComponents = getBaseEsComponents(type, !!isIndexModeTimeSeries); + template.composed_of = [ + ...esBaseComponents, ...(template.composed_of || []), FLEET_GLOBALS_COMPONENT_TEMPLATE_NAME, ...(appContextService.getConfig()?.agentIdVerificationEnabled @@ -111,6 +119,20 @@ export function getTemplate({ return template; } +const getBaseEsComponents = (type: string, isIndexModeTimeSeries: boolean): string[] => { + if (type === 'metrics') { + if (isIndexModeTimeSeries) { + return [STACK_COMPONENT_TEMPLATE_METRICS_TSDB_SETTINGS]; + } + + return [STACK_COMPONENT_TEMPLATE_METRICS_SETTINGS]; + } else if (type === 'logs') { + return [STACK_COMPONENT_TEMPLATE_LOGS_SETTINGS]; + } + + return []; +}; + /** * Generate mapping takes the given nested fields array and creates the Elasticsearch * mapping properties out of it. diff --git a/x-pack/plugins/fleet/server/services/epm/kibana/assets/install.ts b/x-pack/plugins/fleet/server/services/epm/kibana/assets/install.ts index 1c804991cbeaf..20a0484c77a4a 100644 --- a/x-pack/plugins/fleet/server/services/epm/kibana/assets/install.ts +++ b/x-pack/plugins/fleet/server/services/epm/kibana/assets/install.ts @@ -140,15 +140,21 @@ export async function installKibanaAssets(options: { return []; } - // As we use `import` to create our saved objects, we have to install - // their references (the index patterns) at the same time - // to prevent a reference error + // Create index patterns separately with `overwrite: false` to prevent blowing away users' runtime fields. + // These don't get retried on conflict, because we expect that they exist once an integration has been installed. const indexPatternSavedObjects = getIndexPatternSavedObjects() as ArchiveAsset[]; + await savedObjectsImporter.import({ + overwrite: false, + readStream: createListStream(indexPatternSavedObjects), + createNewCopies: false, + refresh: false, + managed: true, + }); const installedAssets = await installKibanaSavedObjects({ logger, savedObjectsImporter, - kibanaAssets: [...indexPatternSavedObjects, ...assetsToInstall], + kibanaAssets: assetsToInstall, }); return installedAssets; diff --git a/x-pack/plugins/fleet/server/services/output.test.ts b/x-pack/plugins/fleet/server/services/output.test.ts index 744be302bddc0..03d43b130c4ea 100644 --- a/x-pack/plugins/fleet/server/services/output.test.ts +++ b/x-pack/plugins/fleet/server/services/output.test.ts @@ -702,6 +702,28 @@ describe('Output Service', () => { { id: 'output-1' } ); }); + + it('should throw when a remote es output is attempted to be created as default data output', async () => { + const soClient = getMockedSoClient({ + defaultOutputId: 'output-test', + }); + + await expect( + outputService.create( + soClient, + esClientMock, + { + is_default: true, + is_default_monitoring: false, + name: 'Test', + type: 'remote_elasticsearch', + }, + { id: 'output-1' } + ) + ).rejects.toThrow( + `Remote elasticsearch output cannot be set as default output for integration data. Please set "is_default" to false.` + ); + }); }); describe('update', () => { @@ -1501,6 +1523,23 @@ describe('Output Service', () => { { force: true } ); }); + + it('should throw when a remote es output is attempted to be updated as default data output', async () => { + const soClient = getMockedSoClient({ + defaultOutputId: 'output-test', + }); + + await expect( + outputService.update(soClient, esClientMock, 'output-test', { + is_default: true, + is_default_monitoring: false, + name: 'Test', + type: 'remote_elasticsearch', + }) + ).rejects.toThrow( + `Remote elasticsearch output cannot be set as default output for integration data. Please set "is_default" to false.` + ); + }); }); describe('delete', () => { diff --git a/x-pack/plugins/fleet/server/services/output.ts b/x-pack/plugins/fleet/server/services/output.ts index efbc35806e925..0cb1099b58ebb 100644 --- a/x-pack/plugins/fleet/server/services/output.ts +++ b/x-pack/plugins/fleet/server/services/output.ts @@ -25,6 +25,7 @@ import type { OutputSOAttributes, AgentPolicy, OutputSoKafkaAttributes, + OutputSoRemoteElasticsearchAttributes, PolicySecretReference, } from '../types'; import { @@ -421,6 +422,13 @@ class OutputService { options?: { id?: string; fromPreconfiguration?: boolean; overwrite?: boolean } ): Promise { const data: OutputSOAttributes = { ...omit(output, ['ssl', 'secrets']) }; + if (output.type === outputType.RemoteElasticsearch) { + if (data.is_default) { + throw new OutputInvalidError( + 'Remote elasticsearch output cannot be set as default output for integration data. Please set "is_default" to false.' + ); + } + } const defaultDataOutputId = await this.getDefaultDataOutputId(soClient); if (output.type === outputType.Logstash || output.type === outputType.Kafka) { @@ -466,7 +474,10 @@ class OutputService { } } - if (data.type === outputType.Elasticsearch && data.hosts) { + if ( + (data.type === outputType.Elasticsearch || data.type === outputType.RemoteElasticsearch) && + data.hosts + ) { data.hosts = data.hosts.map(normalizeHostsForAgents); } @@ -709,6 +720,14 @@ class OutputService { fromPreconfiguration: false, } ) { + if (data.type === outputType.RemoteElasticsearch) { + if (data.is_default) { + throw new OutputInvalidError( + 'Remote elasticsearch output cannot be set as default output for integration data. Please set "is_default" to false.' + ); + } + } + let secretsToDelete: PolicySecretReference[] = []; const originalOutput = await this.get(soClient, id); @@ -770,10 +789,7 @@ class OutputService { // If the output type changed if (data.type && data.type !== originalOutput.type) { - if ( - (data.type === outputType.Elasticsearch || data.type === outputType.Logstash) && - originalOutput.type === outputType.Kafka - ) { + if (data.type !== outputType.Kafka && originalOutput.type === outputType.Kafka) { removeKafkaFields(updateData as Nullable); } @@ -781,9 +797,10 @@ class OutputService { // remove ES specific field updateData.ca_trusted_fingerprint = null; updateData.ca_sha256 = null; + delete (updateData as Nullable).service_token; } - if (data.type === outputType.Elasticsearch) { + if (data.type !== outputType.Logstash) { // remove logstash specific field updateData.ssl = null; } @@ -889,7 +906,10 @@ class OutputService { } } - if (mergedType === outputType.Elasticsearch && updateData.hosts) { + if ( + (mergedType === outputType.Elasticsearch || mergedType === outputType.RemoteElasticsearch) && + updateData.hosts + ) { updateData.hosts = updateData.hosts.map(normalizeHostsForAgents); } diff --git a/x-pack/plugins/fleet/server/services/security/message_signing_service.test.ts b/x-pack/plugins/fleet/server/services/security/message_signing_service.test.ts index cb4288cd31488..6156021d517e5 100644 --- a/x-pack/plugins/fleet/server/services/security/message_signing_service.test.ts +++ b/x-pack/plugins/fleet/server/services/security/message_signing_service.test.ts @@ -11,6 +11,7 @@ import type { KibanaRequest } from '@kbn/core-http-server'; import type { SavedObjectsClientContract } from '@kbn/core/server'; import type { EncryptedSavedObjectsClient } from '@kbn/encrypted-saved-objects-plugin/server'; import { encryptedSavedObjectsMock } from '@kbn/encrypted-saved-objects-plugin/server/mocks'; +import { loggingSystemMock } from '@kbn/core/server/mocks'; import { MESSAGE_SIGNING_KEYS_SAVED_OBJECT_TYPE } from '../../constants'; import { createAppContextStartContractMock } from '../../mocks'; @@ -64,7 +65,7 @@ describe('MessageSigningService', () => { .getSavedObjects() .getScopedClient({} as unknown as KibanaRequest) as jest.Mocked; - messageSigningService = new MessageSigningService(esoClientMock); + messageSigningService = new MessageSigningService(loggingSystemMock.create(), esoClientMock); } describe('with encryption key configured', () => { @@ -208,6 +209,33 @@ describe('MessageSigningService', () => { expect(isVerified).toBe(true); expect(data).toBe(message); }); + + it('will retry getting keypair if ESO error', async () => { + esoClientMock.createPointInTimeFinderDecryptedAsInternalUser = jest + .fn() + .mockRejectedValueOnce(new Error('some error')) + .mockRejectedValueOnce(new Error('another error')) + .mockResolvedValueOnce({ + close: jest.fn(), + find: function* asyncGenerator() { + yield { saved_objects: [] }; + }, + }); + + const generateKeyPairResponse = await messageSigningService.generateKeyPair(); + expect(esoClientMock.createPointInTimeFinderDecryptedAsInternalUser).toBeCalledTimes(3); + expect(soClientMock.create).toHaveBeenLastCalledWith(MESSAGE_SIGNING_KEYS_SAVED_OBJECT_TYPE, { + private_key: expect.any(String), + public_key: expect.any(String), + passphrase: expect.any(String), + }); + + expect(generateKeyPairResponse).toEqual({ + passphrase: expect.any(String), + privateKey: expect.any(String), + publicKey: expect.any(String), + }); + }); }); describe('with NO encryption key configured', () => { diff --git a/x-pack/plugins/fleet/server/services/security/message_signing_service.ts b/x-pack/plugins/fleet/server/services/security/message_signing_service.ts index 6fcf92c0aebe8..77d2a2a272caf 100644 --- a/x-pack/plugins/fleet/server/services/security/message_signing_service.ts +++ b/x-pack/plugins/fleet/server/services/security/message_signing_service.ts @@ -5,8 +5,11 @@ * 2.0. */ +import { backOff } from 'exponential-backoff'; + import { generateKeyPairSync, createSign, randomBytes } from 'crypto'; +import type { LoggerFactory, Logger } from '@kbn/core/server'; import type { KibanaRequest } from '@kbn/core-http-server'; import type { SavedObjectsClientContract, @@ -39,8 +42,11 @@ export interface MessageSigningServiceInterface { export class MessageSigningService implements MessageSigningServiceInterface { private _soClient: SavedObjectsClientContract | undefined; + private logger: Logger; - constructor(private esoClient: EncryptedSavedObjectsClient) {} + constructor(loggerFactory: LoggerFactory, private esoClient: EncryptedSavedObjectsClient) { + this.logger = loggerFactory.get('messageSigningService'); + } public get isEncryptionAvailable(): MessageSigningServiceInterface['isEncryptionAvailable'] { return appContextService.getEncryptedSavedObjectsSetup()?.canEncrypt ?? false; @@ -188,6 +194,30 @@ export class MessageSigningService implements MessageSigningServiceInterface { return this._soClient; } + private async getCurrentKeyPairObjWithRetry() { + let soDoc: SavedObjectsFindResult | undefined; + + await backOff( + async () => { + soDoc = await this.getCurrentKeyPairObj(); + }, + { + maxDelay: 60 * 60 * 1000, // 1 hour in milliseconds + startingDelay: 1000, // 1 second + jitter: 'full', + numOfAttempts: Infinity, + retry: (_err: Error, attempt: number) => { + // not logging the error since we don't control what's in the error and it might contain sensitive data + // ESO already logs specific caught errors before passing the error along + this.logger.warn(`failed to get message signing key pair. retrying attempt: ${attempt}`); + return true; + }, + } + ); + + return soDoc; + } + private async getCurrentKeyPairObj(): Promise< SavedObjectsFindResult | undefined > { @@ -205,6 +235,10 @@ export class MessageSigningService implements MessageSigningServiceInterface { } finder.close(); + if (soDoc?.error) { + throw soDoc.error; + } + return soDoc; } @@ -216,7 +250,7 @@ export class MessageSigningService implements MessageSigningServiceInterface { } | undefined > { - const currentKeyPair = await this.getCurrentKeyPairObj(); + const currentKeyPair = await this.getCurrentKeyPairObjWithRetry(); if (!currentKeyPair) { return; } diff --git a/x-pack/plugins/fleet/server/types/models/output.ts b/x-pack/plugins/fleet/server/types/models/output.ts index 5bf4d22d8f188..d77663b65e784 100644 --- a/x-pack/plugins/fleet/server/types/models/output.ts +++ b/x-pack/plugins/fleet/server/types/models/output.ts @@ -123,6 +123,22 @@ const ElasticSearchUpdateSchema = { hosts: schema.maybe(schema.arrayOf(schema.uri({ scheme: ['http', 'https'] }), { minSize: 1 })), }; +/** + * Remote Elasticsearch schemas + */ + +export const RemoteElasticSearchSchema = { + ...ElasticSearchSchema, + type: schema.literal(outputType.RemoteElasticsearch), + service_token: schema.string(), +}; + +const RemoteElasticSearchUpdateSchema = { + ...ElasticSearchUpdateSchema, + type: schema.maybe(schema.literal(outputType.RemoteElasticsearch)), + service_token: schema.maybe(schema.string()), +}; + /** * Logstash schemas */ @@ -287,12 +303,14 @@ const KafkaUpdateSchema = { export const OutputSchema = schema.oneOf([ schema.object({ ...ElasticSearchSchema }), + schema.object({ ...RemoteElasticSearchSchema }), schema.object({ ...LogstashSchema }), schema.object({ ...KafkaSchema }), ]); export const UpdateOutputSchema = schema.oneOf([ schema.object({ ...ElasticSearchUpdateSchema }), + schema.object({ ...RemoteElasticSearchUpdateSchema }), schema.object({ ...LogstashUpdateSchema }), schema.object({ ...KafkaUpdateSchema }), ]); diff --git a/x-pack/plugins/fleet/server/types/rest_spec/app.ts b/x-pack/plugins/fleet/server/types/rest_spec/app.ts new file mode 100644 index 0000000000000..e79f8dda0d2ee --- /dev/null +++ b/x-pack/plugins/fleet/server/types/rest_spec/app.ts @@ -0,0 +1,14 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { schema } from '@kbn/config-schema'; + +export const GenerateServiceTokenRequestSchema = { + body: schema.object({ + remote: schema.boolean({ defaultValue: false }), + }), +}; diff --git a/x-pack/plugins/fleet/server/types/rest_spec/index.ts b/x-pack/plugins/fleet/server/types/rest_spec/index.ts index 8fdad29dc1d11..ebdaa02902e37 100644 --- a/x-pack/plugins/fleet/server/types/rest_spec/index.ts +++ b/x-pack/plugins/fleet/server/types/rest_spec/index.ts @@ -22,3 +22,4 @@ export * from './download_sources'; export * from './tags'; export * from './health_check'; export * from './message_signing_service'; +export * from './app'; diff --git a/x-pack/plugins/fleet/server/types/so_attributes.ts b/x-pack/plugins/fleet/server/types/so_attributes.ts index 00bd1b3a67d57..66974744d4adb 100644 --- a/x-pack/plugins/fleet/server/types/so_attributes.ts +++ b/x-pack/plugins/fleet/server/types/so_attributes.ts @@ -151,6 +151,12 @@ interface OutputSoElasticsearchAttributes extends OutputSoBaseAttributes { secrets?: {}; } +export interface OutputSoRemoteElasticsearchAttributes extends OutputSoBaseAttributes { + type: OutputType['RemoteElasticsearch']; + service_token?: string; + secrets?: {}; +} + interface OutputSoLogstashAttributes extends OutputSoBaseAttributes { type: OutputType['Logstash']; secrets?: { @@ -209,6 +215,7 @@ export interface OutputSoKafkaAttributes extends OutputSoBaseAttributes { export type OutputSOAttributes = | OutputSoElasticsearchAttributes + | OutputSoRemoteElasticsearchAttributes | OutputSoLogstashAttributes | OutputSoKafkaAttributes; diff --git a/x-pack/plugins/index_lifecycle_management/__jest__/extend_index_management.test.tsx b/x-pack/plugins/index_lifecycle_management/__jest__/extend_index_management.test.tsx index be64e1a4674aa..244536ad4afef 100644 --- a/x-pack/plugins/index_lifecycle_management/__jest__/extend_index_management.test.tsx +++ b/x-pack/plugins/index_lifecycle_management/__jest__/extend_index_management.test.tsx @@ -5,12 +5,12 @@ * 2.0. */ +import React from 'react'; import moment from 'moment-timezone'; import { init } from '../integration_tests/helpers/http_requests'; import { mountWithIntl } from '@kbn/test-jest-helpers'; import { usageCollectionPluginMock } from '@kbn/usage-collection-plugin/public/mocks'; -import { Index } from '../common/types'; import { retryLifecycleActionExtension, removeLifecyclePolicyActionExtension, @@ -20,8 +20,8 @@ import { } from '../public/extend_index_management'; import { init as initHttp } from '../public/application/services/http'; import { init as initUiMetric } from '../public/application/services/ui_metric'; -import { IndexLifecycleSummary } from '../public/extend_index_management/components/index_lifecycle_summary'; -import React from 'react'; +import { indexLifecycleTab } from '../public/extend_index_management/components/index_lifecycle_summary'; +import { Index } from '@kbn/index-management-plugin/common'; const { httpSetup } = init(); @@ -113,6 +113,7 @@ const indexWithLifecycleError: Index = { }, phase_execution: { policy: 'testy', + // @ts-expect-error ILM type is incorrect https://github.com/elastic/elasticsearch-specification/issues/2326 phase_definition: { min_age: '0s', actions: { rollover: { max_size: '1gb' } } }, version: 1, modified_date_in_millis: 1544031699844, @@ -243,29 +244,31 @@ describe('extend index management', () => { }); describe('ilm summary extension', () => { - test('should render null when index has no index lifecycle policy', () => { - const extension = ( - - ); - const rendered = mountWithIntl(extension); - expect(rendered.isEmptyRender()).toBeTruthy(); + const IlmComponent = indexLifecycleTab.renderTabContent; + test('should not render the tab when index has no index lifecycle policy', () => { + const shouldRenderTab = + indexLifecycleTab.shouldRenderTab && + indexLifecycleTab.shouldRenderTab({ + index: indexWithoutLifecyclePolicy, + }); + expect(shouldRenderTab).toBeFalsy(); }); test('should return extension when index has lifecycle policy', () => { - const extension = ( - + const ilmContent = ( + ); - expect(extension).toBeDefined(); - const rendered = mountWithIntl(extension); + expect(ilmContent).toBeDefined(); + const rendered = mountWithIntl(ilmContent); expect(rendered.render()).toMatchSnapshot(); }); test('should return extension when index has lifecycle error', () => { - const extension = ( - + const ilmContent = ( + ); - expect(extension).toBeDefined(); - const rendered = mountWithIntl(extension); + expect(ilmContent).toBeDefined(); + const rendered = mountWithIntl(ilmContent); expect(rendered.render()).toMatchSnapshot(); }); }); diff --git a/x-pack/plugins/index_lifecycle_management/common/types/policies.ts b/x-pack/plugins/index_lifecycle_management/common/types/policies.ts index fcc9e89da4796..c241ce6b5c58d 100644 --- a/x-pack/plugins/index_lifecycle_management/common/types/policies.ts +++ b/x-pack/plugins/index_lifecycle_management/common/types/policies.ts @@ -5,8 +5,6 @@ * 2.0. */ -import { Index as IndexInterface } from '@kbn/index-management-plugin/common/types'; - export type Phase = keyof Phases; export type PhaseWithAllocation = 'warm' | 'cold'; @@ -244,7 +242,3 @@ export interface IndexLifecyclePolicy { }; step_time_millis?: number; } - -export interface Index extends IndexInterface { - ilm: IndexLifecyclePolicy; -} diff --git a/x-pack/plugins/index_lifecycle_management/public/extend_index_management/components/add_lifecycle_confirm_modal.tsx b/x-pack/plugins/index_lifecycle_management/public/extend_index_management/components/add_lifecycle_confirm_modal.tsx index 015c1576de5db..79af627f578b1 100644 --- a/x-pack/plugins/index_lifecycle_management/public/extend_index_management/components/add_lifecycle_confirm_modal.tsx +++ b/x-pack/plugins/index_lifecycle_management/public/extend_index_management/components/add_lifecycle_confirm_modal.tsx @@ -25,10 +25,11 @@ import { EuiModalHeaderTitle, } from '@elastic/eui'; +import { Index } from '@kbn/index-management-plugin/common'; import { loadPolicies, addLifecyclePolicyToIndex } from '../../application/services/api'; import { showApiError } from '../../application/services/api_errors'; import { toasts } from '../../application/services/notification'; -import { Index, PolicyFromES } from '../../../common/types'; +import { PolicyFromES } from '../../../common/types'; interface Props { indexName: string; diff --git a/x-pack/plugins/index_lifecycle_management/public/extend_index_management/components/index_lifecycle_summary.tsx b/x-pack/plugins/index_lifecycle_management/public/extend_index_management/components/index_lifecycle_summary.tsx index f1468117dc53c..162457479788f 100644 --- a/x-pack/plugins/index_lifecycle_management/public/extend_index_management/components/index_lifecycle_summary.tsx +++ b/x-pack/plugins/index_lifecycle_management/public/extend_index_management/components/index_lifecycle_summary.tsx @@ -25,10 +25,12 @@ import { } from '@elastic/eui'; import { ApplicationStart } from '@kbn/core/public'; +import { Index } from '@kbn/index-management-plugin/common'; +import { IndexDetailsTab } from '@kbn/index-management-plugin/common/constants'; +import { IlmExplainLifecycleLifecycleExplainManaged } from '@elastic/elasticsearch/lib/api/types'; import { getPolicyEditPath } from '../../application/services/navigation'; -import { Index, IndexLifecyclePolicy } from '../../../common/types'; -const getHeaders = (): Array<[keyof IndexLifecyclePolicy, string]> => { +const getHeaders = (): Array<[keyof IlmExplainLifecycleLifecycleExplainManaged, string]> => { return [ [ 'policy', @@ -85,7 +87,9 @@ interface Props { export const IndexLifecycleSummary: FunctionComponent = ({ index, getUrlForApp }) => { const [showPhaseExecutionPopover, setShowPhaseExecutionPopover] = useState(false); - const { ilm } = index; + const { ilm: ilmData } = index; + // only ILM managed indices render the ILM tab + const ilm = ilmData as IlmExplainLifecycleLifecycleExplainManaged; const togglePhaseExecutionPopover = () => { setShowPhaseExecutionPopover(!showPhaseExecutionPopover); @@ -144,15 +148,15 @@ export const IndexLifecycleSummary: FunctionComponent = ({ index, getUrlF right: [], }; headers.forEach(([fieldName, label], arrayIndex) => { - const value: any = ilm[fieldName]; + const value = ilm[fieldName]; let content; if (fieldName === 'action_time_millis') { - content = moment(value).format('YYYY-MM-DD HH:mm:ss'); + content = moment(value as string).format('YYYY-MM-DD HH:mm:ss'); } else if (fieldName === 'policy') { content = ( {value} @@ -184,9 +188,6 @@ export const IndexLifecycleSummary: FunctionComponent = ({ index, getUrlF return rows; }; - if (!ilm.managed) { - return null; - } const { left, right } = buildRows(); return ( <> @@ -243,3 +244,18 @@ export const IndexLifecycleSummary: FunctionComponent = ({ index, getUrlF ); }; + +export const indexLifecycleTab: IndexDetailsTab = { + id: 'ilm', + name: ( + + ), + order: 50, + renderTabContent: IndexLifecycleSummary, + shouldRenderTab: ({ index }) => { + return !!index.ilm && index.ilm.managed; + }, +}; diff --git a/x-pack/plugins/index_lifecycle_management/public/extend_index_management/index.tsx b/x-pack/plugins/index_lifecycle_management/public/extend_index_management/index.tsx index 9d3d14f11e685..519a0606c36aa 100644 --- a/x-pack/plugins/index_lifecycle_management/public/extend_index_management/index.tsx +++ b/x-pack/plugins/index_lifecycle_management/public/extend_index_management/index.tsx @@ -11,20 +11,19 @@ import { i18n } from '@kbn/i18n'; import { EuiSearchBar } from '@elastic/eui'; import { ApplicationStart } from '@kbn/core/public'; -import { IndexManagementPluginSetup } from '@kbn/index-management-plugin/public'; +import { Index, IndexManagementPluginSetup } from '@kbn/index-management-plugin/public'; import { retryLifecycleForIndex } from '../application/services/api'; -import { IndexLifecycleSummary } from './components/index_lifecycle_summary'; +import { indexLifecycleTab } from './components/index_lifecycle_summary'; import { AddLifecyclePolicyConfirmModal } from './components/add_lifecycle_confirm_modal'; import { RemoveLifecyclePolicyConfirmModal } from './components/remove_lifecycle_confirm_modal'; -import { Index } from '../../common/types'; const stepPath = 'ilm.step'; export const retryLifecycleActionExtension = ({ indices }: { indices: Index[] }) => { const allHaveErrors = every(indices, (index) => { - return index.ilm && index.ilm.failed_step; + return index.ilm?.managed && index.ilm.failed_step; }); if (!allHaveErrors) { return null; @@ -224,6 +223,7 @@ export const addAllExtensions = ( extensionsService.addAction(addLifecyclePolicyActionExtension); extensionsService.addBanner(ilmBannerExtension); - extensionsService.addSummary(IndexLifecycleSummary); extensionsService.addFilter(ilmFilterExtension); + + extensionsService.addIndexDetailsTab(indexLifecycleTab); }; diff --git a/x-pack/plugins/index_lifecycle_management/server/plugin.ts b/x-pack/plugins/index_lifecycle_management/server/plugin.ts index 011825ed9bf77..6b21a477866bb 100644 --- a/x-pack/plugins/index_lifecycle_management/server/plugin.ts +++ b/x-pack/plugins/index_lifecycle_management/server/plugin.ts @@ -9,9 +9,8 @@ import { i18n } from '@kbn/i18n'; import { CoreSetup, Plugin, Logger, PluginInitializerContext } from '@kbn/core/server'; import { IScopedClusterClient } from '@kbn/core/server'; -import { Index as IndexWithoutIlm } from '@kbn/index-management-plugin/common/types'; +import { Index } from '@kbn/index-management-plugin/common/types'; import { PLUGIN } from '../common/constants'; -import { Index } from '../common/types'; import { Dependencies } from './types'; import { registerApiRoutes } from './routes'; import { License } from './services'; @@ -19,7 +18,7 @@ import { IndexLifecycleManagementConfig } from './config'; import { handleEsError } from './shared_imports'; const indexLifecycleDataEnricher = async ( - indicesList: IndexWithoutIlm[], + indicesList: Index[], client: IScopedClusterClient ): Promise => { if (!indicesList || !indicesList.length) { @@ -29,8 +28,7 @@ const indexLifecycleDataEnricher = async ( const { indices: ilmIndicesData } = await client.asCurrentUser.ilm.explainLifecycle({ index: '*', }); - // @ts-expect-error IndexLifecyclePolicy is not compatible with IlmExplainLifecycleResponse - return indicesList.map((index: IndexWithoutIlm) => { + return indicesList.map((index: Index) => { return { ...index, ilm: { ...(ilmIndicesData[index.name] || {}) }, diff --git a/x-pack/plugins/index_management/README.md b/x-pack/plugins/index_management/README.md index 8ac2837a683b6..8673447fc577c 100644 --- a/x-pack/plugins/index_management/README.md +++ b/x-pack/plugins/index_management/README.md @@ -1,4 +1,47 @@ # Index Management UI +## Extensions service +This service is exposed from the Index Management setup contract and can be used to add content to the indices list and the index details page. +### Extensions to the indices list +- `addBanner(banner: any)`: adds a banner on top of the indices list, for example when some indices run into an ILM issue +- `addFilter(filter: any)`: adds a filter to the indices list, for example to filter indices managed by ILM +- `addToggle(toggle: any)`: adds a toggle to the indices list, for example to display hidden indices + +#### Extensions to the indices list and the index details page +- `addAction(action: any)`: adds an option to the "manage index" menu, for example to add an ILM policy to the index +- `addBadge(badge: any)`: adds a badge to the index name, for example to indicate frozen, rollup or follower indices + +#### Extensions to the index details page +- `addIndexDetailsTab(tab: IndexDetailsTab)`: adds a tab to the index details page. The tab has the following interface: + +```ts +interface IndexDetailsTab { + // a unique key to identify the tab + id: IndexDetailsTabId; + // a text that is displayed on the tab label, usually a Formatted message component + name: ReactNode; + // a function that renders the content of the tab + renderTabContent: (args: { + index: Index; + getUrlForApp: ApplicationStart['getUrlForApp']; + }) => ReturnType; + // a number to specify the order of the tabs + order: number; + // an optional function to return a boolean for when to render the tab + // if omitted, the tab is always rendered + shouldRenderTab?: (args: { index: Index }) => boolean; +} +``` + +An example of adding an ILM tab can be found in [this file](https://github.com/elastic/kibana/blob/main/x-pack/plugins/index_lifecycle_management/public/extend_index_management/components/index_lifecycle_summary.tsx#L250). + +- `setIndexOverviewContent(content: IndexOverviewContent)`: replaces the default content in the overview tab (code block describing adding documents to the index) with the custom content. The custom content has the following interface: +```ts +interface IndexOverviewContent { + renderContent: (args: { + index: Index; + getUrlForApp: ApplicationStart['getUrlForApp']; + }) => ReturnType; +``` ## Indices tab diff --git a/x-pack/plugins/index_management/__jest__/client_integration/home/data_streams_tab.test.ts b/x-pack/plugins/index_management/__jest__/client_integration/home/data_streams_tab.test.ts index e78ad9d167f87..db38796d2ab3b 100644 --- a/x-pack/plugins/index_management/__jest__/client_integration/home/data_streams_tab.test.ts +++ b/x-pack/plugins/index_management/__jest__/client_integration/home/data_streams_tab.test.ts @@ -191,8 +191,8 @@ describe('Data Streams tab', () => { const { tableCellsValues } = table.getMetaData('dataStreamTable'); expect(tableCellsValues).toEqual([ - ['', 'dataStream1', 'green', '1', '7d', 'Delete'], - ['', 'dataStream2', 'green', '1', '7d', 'Delete'], + ['', 'dataStream1', 'green', '1', '7 days', 'Delete'], + ['', 'dataStream2', 'green', '1', '7 days', 'Delete'], ]); }); @@ -230,8 +230,26 @@ describe('Data Streams tab', () => { // The table renders with the stats columns though. const { tableCellsValues } = table.getMetaData('dataStreamTable'); expect(tableCellsValues).toEqual([ - ['', 'dataStream1', 'green', 'December 31st, 1969 7:00:00 PM', '5b', '1', '7d', 'Delete'], - ['', 'dataStream2', 'green', 'December 31st, 1969 7:00:00 PM', '1kb', '1', '7d', 'Delete'], + [ + '', + 'dataStream1', + 'green', + 'December 31st, 1969 7:00:00 PM', + '5b', + '1', + '7 days', + 'Delete', + ], + [ + '', + 'dataStream2', + 'green', + 'December 31st, 1969 7:00:00 PM', + '1kb', + '1', + '7 days', + 'Delete', + ], ]); }); @@ -250,8 +268,26 @@ describe('Data Streams tab', () => { // the human-readable string values. const { tableCellsValues } = table.getMetaData('dataStreamTable'); expect(tableCellsValues).toEqual([ - ['', 'dataStream1', 'green', 'December 31st, 1969 7:00:00 PM', '5b', '1', '7d', 'Delete'], - ['', 'dataStream2', 'green', 'December 31st, 1969 7:00:00 PM', '1kb', '1', '7d', 'Delete'], + [ + '', + 'dataStream1', + 'green', + 'December 31st, 1969 7:00:00 PM', + '5b', + '1', + '7 days', + 'Delete', + ], + [ + '', + 'dataStream2', + 'green', + 'December 31st, 1969 7:00:00 PM', + '1kb', + '1', + '7 days', + 'Delete', + ], ]); }); @@ -279,8 +315,8 @@ describe('Data Streams tab', () => { // The table renders with the stats columns except the Storage size column const { tableCellsValues } = table.getMetaData('dataStreamTable'); expect(tableCellsValues).toEqual([ - ['', 'dataStream1', 'green', 'December 31st, 1969 7:00:00 PM', '1', '7d', 'Delete'], - ['', 'dataStream2', 'green', 'December 31st, 1969 7:00:00 PM', '1', '7d', 'Delete'], + ['', 'dataStream1', 'green', 'December 31st, 1969 7:00:00 PM', '1', '7 days', 'Delete'], + ['', 'dataStream2', 'green', 'December 31st, 1969 7:00:00 PM', '1', '7 days', 'Delete'], ]); }); @@ -618,7 +654,7 @@ describe('Data Streams tab', () => { const { actions, find, exists } = testBed; await actions.clickNameAt(1); - expect(find('dataRetentionDetail').text()).toBe('7d'); + expect(find('dataRetentionDetail').text()).toBe('7 days'); actions.clickEditDataRetentionButton(); @@ -782,8 +818,15 @@ describe('Data Streams tab', () => { const { tableCellsValues } = table.getMetaData('dataStreamTable'); expect(tableCellsValues).toEqual([ - ['', `managed-data-stream${nonBreakingSpace}Fleet-managed`, 'green', '1', '7d', 'Delete'], - ['', 'non-managed-data-stream', 'green', '1', '7d', 'Delete'], + [ + '', + `managed-data-stream${nonBreakingSpace}Fleet-managed`, + 'green', + '1', + '7 days', + 'Delete', + ], + ['', 'non-managed-data-stream', 'green', '1', '7 days', 'Delete'], ]); }); @@ -792,15 +835,22 @@ describe('Data Streams tab', () => { let { tableCellsValues } = table.getMetaData('dataStreamTable'); expect(tableCellsValues).toEqual([ - ['', `managed-data-stream${nonBreakingSpace}Fleet-managed`, 'green', '1', '7d', 'Delete'], - ['', 'non-managed-data-stream', 'green', '1', '7d', 'Delete'], + [ + '', + `managed-data-stream${nonBreakingSpace}Fleet-managed`, + 'green', + '1', + '7 days', + 'Delete', + ], + ['', 'non-managed-data-stream', 'green', '1', '7 days', 'Delete'], ]); actions.toggleViewFilterAt(0); ({ tableCellsValues } = table.getMetaData('dataStreamTable')); expect(tableCellsValues).toEqual([ - ['', 'non-managed-data-stream', 'green', '1', '7d', 'Delete'], + ['', 'non-managed-data-stream', 'green', '1', '7 days', 'Delete'], ]); }); }); @@ -832,7 +882,7 @@ describe('Data Streams tab', () => { const { tableCellsValues } = table.getMetaData('dataStreamTable'); expect(tableCellsValues).toEqual([ - ['', `hidden-data-stream${nonBreakingSpace}Hidden`, 'green', '1', '7d', 'Delete'], + ['', `hidden-data-stream${nonBreakingSpace}Hidden`, 'green', '1', '7 days', 'Delete'], ]); }); }); @@ -879,10 +929,10 @@ describe('Data Streams tab', () => { const { tableCellsValues } = table.getMetaData('dataStreamTable'); expect(tableCellsValues).toEqual([ - ['', 'dataStreamNoDelete', 'green', '1', '7d', ''], - ['', 'dataStreamNoEditRetention', 'green', '1', '7d', 'Delete'], - ['', 'dataStreamNoPermissions', 'green', '1', '7d', ''], - ['', 'dataStreamWithDelete', 'green', '1', '7d', 'Delete'], + ['', 'dataStreamNoDelete', 'green', '1', '7 days', ''], + ['', 'dataStreamNoEditRetention', 'green', '1', '7 days', 'Delete'], + ['', 'dataStreamNoPermissions', 'green', '1', '7 days', ''], + ['', 'dataStreamWithDelete', 'green', '1', '7 days', 'Delete'], ]); }); diff --git a/x-pack/plugins/index_management/__jest__/client_integration/home/home.test.ts b/x-pack/plugins/index_management/__jest__/client_integration/home/home.test.ts index 2085368fc7760..49216eb285498 100644 --- a/x-pack/plugins/index_management/__jest__/client_integration/home/home.test.ts +++ b/x-pack/plugins/index_management/__jest__/client_integration/home/home.test.ts @@ -10,15 +10,6 @@ import { act } from 'react-dom/test-utils'; import { setupEnvironment, nextTick } from '../helpers'; import { HomeTestBed, setup } from './home.helpers'; -/** - * The below import is required to avoid a console error warn from the "brace" package - * console.warn ../node_modules/brace/index.js:3999 - Could not load worker ReferenceError: Worker is not defined - at createWorker (//node_modules/brace/index.js:17992:5) - */ -import { stubWebWorker } from '@kbn/test-jest-helpers'; -stubWebWorker(); - describe('', () => { const { httpSetup, httpRequestsMockHelpers } = setupEnvironment(); let testBed: HomeTestBed; diff --git a/x-pack/plugins/index_management/__jest__/client_integration/home/indices_tab.test.ts b/x-pack/plugins/index_management/__jest__/client_integration/home/indices_tab.test.ts index 1158815a62fcc..f7990a3288f04 100644 --- a/x-pack/plugins/index_management/__jest__/client_integration/home/indices_tab.test.ts +++ b/x-pack/plugins/index_management/__jest__/client_integration/home/indices_tab.test.ts @@ -135,6 +135,10 @@ describe('', () => { it('navigates to the index details page when the index name is clicked', async () => { const indexName = 'testIndex'; httpRequestsMockHelpers.setLoadIndicesResponse([createNonDataStreamIndex(indexName)]); + httpRequestsMockHelpers.setLoadIndexDetailsResponse( + indexName, + createNonDataStreamIndex(indexName) + ); testBed = await setup(httpSetup, { history: createMemoryHistory(), @@ -150,6 +154,10 @@ describe('', () => { it('index page works with % character in index name', async () => { const indexName = 'test%'; httpRequestsMockHelpers.setLoadIndicesResponse([createNonDataStreamIndex(indexName)]); + httpRequestsMockHelpers.setLoadIndexDetailsResponse( + encodeURIComponent(indexName), + createNonDataStreamIndex(indexName) + ); testBed = await setup(httpSetup); const { component, actions } = testBed; diff --git a/x-pack/plugins/index_management/__jest__/client_integration/index_details_page/index_details_page.helpers.ts b/x-pack/plugins/index_management/__jest__/client_integration/index_details_page/index_details_page.helpers.ts index cd0c81715cbe9..732fc8f0456fa 100644 --- a/x-pack/plugins/index_management/__jest__/client_integration/index_details_page/index_details_page.helpers.ts +++ b/x-pack/plugins/index_management/__jest__/client_integration/index_details_page/index_details_page.helpers.ts @@ -14,7 +14,7 @@ import { import { HttpSetup } from '@kbn/core/public'; import { act } from 'react-dom/test-utils'; -import { IndexDetailsTabIds } from '../../../common/constants'; +import { IndexDetailsTabId } from '../../../common/constants'; import { IndexDetailsPage } from '../../../public/application/sections/home/index_list/details_page'; import { WithAppDependencies } from '../helpers'; import { testIndexName } from './mocks'; @@ -35,7 +35,7 @@ export interface IndexDetailsPageTestBed extends TestBed { routerMock: typeof reactRouterMock; actions: { getHeader: () => string; - clickIndexDetailsTab: (tab: IndexDetailsTabIds) => Promise; + clickIndexDetailsTab: (tab: IndexDetailsTabId) => Promise; getIndexDetailsTabs: () => string[]; getActiveTabContent: () => string; mappings: { @@ -88,7 +88,6 @@ export interface IndexDetailsPageTestBed extends TestBed { getDataStreamDetailsContent: () => string; reloadDataStreamDetails: () => Promise; addDocCodeBlockExists: () => boolean; - extensionSummaryExists: (index: number) => boolean; }; }; } @@ -127,7 +126,7 @@ export const setup = async ({ return component.find('[data-test-subj="indexDetailsHeader"] h1').text(); }; - const clickIndexDetailsTab = async (tab: IndexDetailsTabIds) => { + const clickIndexDetailsTab = async (tab: IndexDetailsTabId) => { await act(async () => { find(`indexDetailsTab-${tab}`).simulate('click'); }); @@ -178,9 +177,6 @@ export const setup = async ({ addDocCodeBlockExists: () => { return exists('codeBlockControlsPanel'); }, - extensionSummaryExists: (index: number) => { - return exists(`extensionsSummary-${index}`); - }, }; const mappings = { diff --git a/x-pack/plugins/index_management/__jest__/client_integration/index_details_page/index_details_page.test.tsx b/x-pack/plugins/index_management/__jest__/client_integration/index_details_page/index_details_page.test.tsx index 76247c483b3c4..9f9018edceead 100644 --- a/x-pack/plugins/index_management/__jest__/client_integration/index_details_page/index_details_page.test.tsx +++ b/x-pack/plugins/index_management/__jest__/client_integration/index_details_page/index_details_page.test.tsx @@ -11,11 +11,7 @@ import { act } from 'react-dom/test-utils'; import React from 'react'; -import { - IndexDetailsSection, - IndexDetailsTab, - IndexDetailsTabIds, -} from '../../../common/constants'; +import { IndexDetailsSection, IndexDetailsTab, IndexDetailsTabId } from '../../../common/constants'; import { API_BASE_PATH, Index, INTERNAL_API_BASE_PATH } from '../../../common'; import { @@ -399,57 +395,28 @@ describe('', () => { expect(testBed.actions.overview.addDocCodeBlockExists()).toBe(true); }); - describe('extension service summary', () => { - it('renders all summaries added to the extension service', async () => { + describe('extension service overview content', () => { + it('renders the content instead of the default code block', async () => { + const extensionsServiceOverview = 'Test content via extensions service'; await act(async () => { testBed = await setup({ httpSetup, dependencies: { services: { extensionsService: { - summaries: [() => test, () => test2], + _indexOverviewContent: { + renderContent: () => extensionsServiceOverview, + }, }, }, }, }); }); testBed.component.update(); - expect(testBed.actions.overview.extensionSummaryExists(0)).toBe(true); - expect(testBed.actions.overview.extensionSummaryExists(1)).toBe(true); - }); - it(`doesn't render empty panels if the summary renders null`, async () => { - await act(async () => { - testBed = await setup({ - httpSetup, - dependencies: { - services: { - extensionsService: { - summaries: [() => null], - }, - }, - }, - }); - }); - testBed.component.update(); - expect(testBed.actions.overview.extensionSummaryExists(0)).toBe(false); - }); - - it(`doesn't render anything when no summaries added to the extension service`, async () => { - await act(async () => { - testBed = await setup({ - httpSetup, - dependencies: { - services: { - extensionsService: { - summaries: [], - }, - }, - }, - }); - }); - testBed.component.update(); - expect(testBed.actions.overview.extensionSummaryExists(0)).toBe(false); + expect(testBed.actions.overview.addDocCodeBlockExists()).toBe(false); + const content = testBed.actions.getActiveTabContent(); + expect(content).toContain(extensionsServiceOverview); }); }); }); @@ -851,8 +818,9 @@ describe('', () => { ); }); }); + describe('extension service tabs', () => { - const testTabId = 'testTab' as IndexDetailsTabIds; + const testTabId = 'testTab' as IndexDetailsTabId; const testContent = 'Test content'; const additionalTab: IndexDetailsTab = { id: testTabId, diff --git a/x-pack/plugins/index_management/common/constants/home_sections.ts b/x-pack/plugins/index_management/common/constants/home_sections.ts index c478c9ea0ec67..436a9ae56aa1a 100644 --- a/x-pack/plugins/index_management/common/constants/home_sections.ts +++ b/x-pack/plugins/index_management/common/constants/home_sections.ts @@ -5,7 +5,8 @@ * 2.0. */ -import { ReactNode } from 'react'; +import { FunctionComponent, ReactNode } from 'react'; +import { ApplicationStart } from '@kbn/core-application-browser'; import { Index } from '../types'; export enum Section { @@ -23,15 +24,21 @@ export enum IndexDetailsSection { Stats = 'stats', } -export type IndexDetailsTabIds = IndexDetailsSection | string; +export type IndexDetailsTabId = IndexDetailsSection | string; export interface IndexDetailsTab { // a unique key to identify the tab - id: IndexDetailsTabIds; + id: IndexDetailsTabId; // a text that is displayed on the tab label, usually a Formatted message component name: ReactNode; // a function that renders the content of the tab - renderTabContent: (indexName: string, index: Index) => ReactNode; + renderTabContent: (args: { + index: Index; + getUrlForApp: ApplicationStart['getUrlForApp']; + }) => ReturnType; // a number to specify the order of the tabs order: number; + // an optional function to return a boolean for when to render the tab + // if omitted, the tab is always rendered + shouldRenderTab?: (args: { index: Index }) => boolean; } diff --git a/x-pack/plugins/index_management/common/constants/index.ts b/x-pack/plugins/index_management/common/constants/index.ts index b84442a89d49f..a41f3d71bc6bc 100644 --- a/x-pack/plugins/index_management/common/constants/index.ts +++ b/x-pack/plugins/index_management/common/constants/index.ts @@ -49,4 +49,4 @@ export { export { MAJOR_VERSION } from './plugin'; export { Section, IndexDetailsSection } from './home_sections'; -export type { IndexDetailsTab, IndexDetailsTabIds } from './home_sections'; +export type { IndexDetailsTab, IndexDetailsTabId } from './home_sections'; diff --git a/x-pack/plugins/index_management/common/types/indices.ts b/x-pack/plugins/index_management/common/types/indices.ts index ab6080f30fdb2..b5f70ec5e1463 100644 --- a/x-pack/plugins/index_management/common/types/indices.ts +++ b/x-pack/plugins/index_management/common/types/indices.ts @@ -7,6 +7,7 @@ import { HealthStatus, + IlmExplainLifecycleLifecycleExplain, IndicesStatsIndexMetadataState, Uuid, } from '@elastic/elasticsearch/lib/api/types'; @@ -56,6 +57,7 @@ export interface IndexSettings { analysis?: AnalysisModule; [key: string]: any; } + export interface Index { name: string; primary?: number | string; @@ -67,10 +69,7 @@ export interface Index { // The types below are added by extension services if corresponding plugins are enabled (ILM, Rollup, CCR) isRollupIndex?: boolean; - ilm?: { - index: string; - managed: boolean; - }; + ilm?: IlmExplainLifecycleLifecycleExplain; isFollowerIndex?: boolean; // The types from here below represent information returned from the index stats API; diff --git a/x-pack/plugins/index_management/public/application/constants/time_units.ts b/x-pack/plugins/index_management/public/application/constants/time_units.ts new file mode 100644 index 0000000000000..f3b637877ff11 --- /dev/null +++ b/x-pack/plugins/index_management/public/application/constants/time_units.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 { i18n } from '@kbn/i18n'; + +export const timeUnits = [ + { + value: 'd', + text: i18n.translate('xpack.idxMgmt.dataStream.retention.timeUnits.daysLabel', { + defaultMessage: 'days', + }), + }, + { + value: 'h', + text: i18n.translate('xpack.idxMgmt.dataStream.retention.timeUnits.hoursLabel', { + defaultMessage: 'hours', + }), + }, + { + value: 'm', + text: i18n.translate('xpack.idxMgmt.dataStream.retention.timeUnits.minutesLabel', { + defaultMessage: 'minutes', + }), + }, + { + value: 's', + text: i18n.translate('xpack.idxMgmt.dataStream.retention.timeUnits.secondsLabel', { + defaultMessage: 'seconds', + }), + }, +]; + +// These are the time units that are not supported by the UI, but are supported by the ES API. +export const extraTimeUnits = [ + { + value: 'ms', + text: i18n.translate('xpack.idxMgmt.dataStream.retention.timeUnits.msLabel', { + defaultMessage: 'milliseconds', + }), + }, + { + value: 'micros', + text: i18n.translate('xpack.idxMgmt.dataStream.retention.timeUnits.microsLabel', { + defaultMessage: 'microseconds', + }), + }, + { + value: 'nanos', + text: i18n.translate('xpack.idxMgmt.dataStream.retention.timeUnits.nanosLabel', { + defaultMessage: 'nanoseconds', + }), + }, +]; diff --git a/x-pack/plugins/index_management/public/application/lib/data_streams.test.tsx b/x-pack/plugins/index_management/public/application/lib/data_streams.test.tsx index a15cbaefbd0fa..3c915a05ff4f4 100644 --- a/x-pack/plugins/index_management/public/application/lib/data_streams.test.tsx +++ b/x-pack/plugins/index_management/public/application/lib/data_streams.test.tsx @@ -32,7 +32,7 @@ describe('Data stream helpers', () => { enabled: true, data_retention: '2d', }) - ).toBe('2d'); + ).toBe('2 days'); }); }); }); diff --git a/x-pack/plugins/index_management/public/application/lib/data_streams.tsx b/x-pack/plugins/index_management/public/application/lib/data_streams.tsx index 90b6001d3d949..c16b28f73410a 100644 --- a/x-pack/plugins/index_management/public/application/lib/data_streams.tsx +++ b/x-pack/plugins/index_management/public/application/lib/data_streams.tsx @@ -9,7 +9,8 @@ import React from 'react'; import { i18n } from '@kbn/i18n'; import { EuiIcon, EuiToolTip } from '@elastic/eui'; -import { DataStream } from '../../../common'; +import { splitSizeAndUnits, DataStream } from '../../../common'; +import { timeUnits, extraTimeUnits } from '../constants/time_units'; export const isFleetManaged = (dataStream: DataStream): boolean => { // TODO check if the wording will change to 'fleet' @@ -74,7 +75,12 @@ export const getLifecycleValue = ( return infiniteDataRetention; } - return lifecycle?.data_retention; + // Extract size and unit, in order to correctly map the unit to the correct text + const { size, unit } = splitSizeAndUnits(lifecycle?.data_retention as string); + const availableTimeUnits = [...timeUnits, ...extraTimeUnits]; + const match = availableTimeUnits.find((timeUnit) => timeUnit.value === unit); + + return `${size} ${match?.text ?? unit}`; }; export const isDataStreamFullyManagedByILM = (dataStream?: DataStream | null) => { diff --git a/x-pack/plugins/index_management/public/application/sections/home/data_stream_list/edit_data_retention_modal/edit_data_retention_modal.tsx b/x-pack/plugins/index_management/public/application/sections/home/data_stream_list/edit_data_retention_modal/edit_data_retention_modal.tsx index dfe325ac48d44..a1ac650ba0cb7 100644 --- a/x-pack/plugins/index_management/public/application/sections/home/data_stream_list/edit_data_retention_modal/edit_data_retention_modal.tsx +++ b/x-pack/plugins/index_management/public/application/sections/home/data_stream_list/edit_data_retention_modal/edit_data_retention_modal.tsx @@ -39,6 +39,7 @@ import { reactRouterNavigate } from '../../../../../shared_imports'; import { getIndexListUri } from '../../../../services/routing'; import { documentationService } from '../../../../services/documentation'; import { splitSizeAndUnits, DataStream } from '../../../../../../common'; +import { timeUnits } from '../../../../constants/time_units'; import { isDSLWithILMIndices } from '../../../../lib/data_streams'; import { useAppContext } from '../../../../app_context'; import { UnitField } from './unit_field'; @@ -51,45 +52,6 @@ interface Props { onClose: (data?: { hasUpdatedDataRetention: boolean }) => void; } -export const timeUnits = [ - { - value: 'd', - text: i18n.translate( - 'xpack.idxMgmt.dataStreamsDetailsPanel.editDataRetentionModal.timeUnits.daysLabel', - { - defaultMessage: 'days', - } - ), - }, - { - value: 'h', - text: i18n.translate( - 'xpack.idxMgmt.dataStreamsDetailsPanel.editDataRetentionModal.timeUnits.hoursLabel', - { - defaultMessage: 'hours', - } - ), - }, - { - value: 'm', - text: i18n.translate( - 'xpack.idxMgmt.dataStreamsDetailsPanel.editDataRetentionModal.timeUnits.minutesLabel', - { - defaultMessage: 'minutes', - } - ), - }, - { - value: 's', - text: i18n.translate( - 'xpack.idxMgmt.dataStreamsDetailsPanel.editDataRetentionModal.timeUnits.secondsLabel', - { - defaultMessage: 'seconds', - } - ), - }, -]; - const configurationFormSchema: FormSchema = { dataRetention: { type: FIELD_TYPES.TEXT, diff --git a/x-pack/plugins/index_management/public/application/sections/home/index_list/details_page/details_page.tsx b/x-pack/plugins/index_management/public/application/sections/home/index_list/details_page/details_page.tsx index f3e54ae946a99..f028dee3d8eee 100644 --- a/x-pack/plugins/index_management/public/application/sections/home/index_list/details_page/details_page.tsx +++ b/x-pack/plugins/index_management/public/application/sections/home/index_list/details_page/details_page.tsx @@ -6,142 +6,29 @@ */ import React, { useCallback, useEffect, useMemo, useState, FunctionComponent } from 'react'; -import { css } from '@emotion/react'; import { RouteComponentProps } from 'react-router-dom'; import { FormattedMessage } from '@kbn/i18n-react'; -import { - EuiPageHeader, - EuiSpacer, - EuiPageHeaderProps, - EuiPageSection, - EuiButton, - EuiPageTemplate, - EuiText, - EuiCode, -} from '@elastic/eui'; +import { EuiPageTemplate, EuiText, EuiCode } from '@elastic/eui'; import { SectionLoading } from '@kbn/es-ui-shared-plugin/public'; -import { - Section, - IndexDetailsSection, - IndexDetailsTab, - IndexDetailsTabIds, -} from '../../../../../../common/constants'; -import { getIndexDetailsLink } from '../../../../services/routing'; +import { IndexDetailsSection, IndexDetailsTabId } from '../../../../../../common/constants'; import { Index } from '../../../../../../common'; -import { INDEX_OPEN } from '../../../../../../common/constants'; import { Error } from '../../../../../shared_imports'; import { loadIndex } from '../../../../services'; -import { useAppContext } from '../../../../app_context'; -import { DiscoverLink } from '../../../../lib/discover_link'; import { DetailsPageError } from './details_page_error'; -import { ManageIndexButton } from './manage_index_button'; -import { DetailsPageStats } from './details_page_stats'; -import { DetailsPageMappings } from './details_page_mappings'; -import { DetailsPageOverview } from './details_page_overview'; -import { DetailsPageSettings } from './details_page_settings'; +import { DetailsPageContent } from './details_page_content'; -const defaultTabs: IndexDetailsTab[] = [ - { - id: IndexDetailsSection.Overview, - name: ( - - ), - renderTabContent: (indexName: string, index: Index) => ( - - ), - order: 10, - }, - { - id: IndexDetailsSection.Mappings, - name: ( - - ), - renderTabContent: (indexName: string, index: Index) => ( - - ), - order: 20, - }, - { - id: IndexDetailsSection.Settings, - name: ( - - ), - renderTabContent: (indexName: string, index: Index) => ( - - ), - order: 30, - }, -]; - -const statsTab: IndexDetailsTab = { - id: IndexDetailsSection.Stats, - name: , - renderTabContent: (indexName: string, index: Index) => ( - - ), - order: 40, -}; - -const getSelectedTabContent = ({ - tabs, - indexDetailsSection, - index, - indexName, -}: { - tabs: IndexDetailsTab[]; - indexDetailsSection: IndexDetailsTabIds; - index?: Index | null; - indexName: string; -}) => { - // if there is no index data, the tab content won't be rendered, so it's safe to return null here - if (!index) { - return null; - } - const selectedTab = tabs.find((tab) => tab.id === indexDetailsSection); - return selectedTab ? ( - selectedTab.renderTabContent(indexName, index) - ) : ( - - ); -}; export const DetailsPage: FunctionComponent< RouteComponentProps<{ indexName: string; indexDetailsSection: IndexDetailsSection }> > = ({ location: { search }, history }) => { - const { - config, - services: { extensionsService }, - } = useAppContext(); const queryParams = useMemo(() => new URLSearchParams(search), [search]); const indexName = queryParams.get('indexName') ?? ''; - - const tabs = useMemo(() => { - const sortedTabs = [...defaultTabs]; - if (config.enableIndexStats) { - sortedTabs.push(statsTab); - } - sortedTabs.push(...extensionsService.indexDetailsTabs); - - sortedTabs.sort((tabA, tabB) => { - return tabA.order - tabB.order; - }); - return sortedTabs; - }, [config.enableIndexStats, extensionsService.indexDetailsTabs]); - - const tabQueryParam = queryParams.get('tab') ?? IndexDetailsSection.Overview; - let indexDetailsSection = IndexDetailsSection.Overview; - if (tabs.map((tab) => tab.id).includes(tabQueryParam as IndexDetailsTabIds)) { - indexDetailsSection = tabQueryParam as IndexDetailsSection; - } + const tab: IndexDetailsTabId = queryParams.get('tab') ?? IndexDetailsSection.Overview; const [isLoading, setIsLoading] = useState(false); const [error, setError] = useState(null); const [index, setIndex] = useState(); - const selectedTabContent = useMemo(() => { - return getSelectedTabContent({ tabs, indexDetailsSection, index, indexName }); - }, [index, indexDetailsSection, indexName, tabs]); - const fetchIndexDetails = useCallback(async () => { if (indexName) { setIsLoading(true); @@ -161,27 +48,6 @@ export const DetailsPage: FunctionComponent< fetchIndexDetails(); }, [fetchIndexDetails]); - const onSectionChange = useCallback( - (newSection: IndexDetailsTabIds) => { - return history.push(getIndexDetailsLink(indexName, newSection)); - }, - [history, indexName] - ); - - const navigateToAllIndices = useCallback(() => { - history.push(`/${Section.Indices}`); - }, [history]); - - const headerTabs = useMemo(() => { - return tabs.map((tab) => ({ - onClick: () => onSectionChange(tab.id), - isSelected: tab.id === indexDetailsSection, - key: tab.id, - 'data-test-subj': `indexDetailsTab-${tab.id}`, - label: tab.name, - })); - }, [tabs, indexDetailsSection, onSectionChange]); - if (!indexName) { return ( ; } return ( - <> - - - - - - - - - , - , - ]} - rightSideGroupProps={{ - wrap: false, - }} - responsive="reverse" - tabs={headerTabs} - /> - - - -
- {selectedTabContent} -
- + ); }; diff --git a/x-pack/plugins/index_management/public/application/sections/home/index_list/details_page/details_page_content.tsx b/x-pack/plugins/index_management/public/application/sections/home/index_list/details_page/details_page_content.tsx new file mode 100644 index 0000000000000..1a9d5935cca19 --- /dev/null +++ b/x-pack/plugins/index_management/public/application/sections/home/index_list/details_page/details_page_content.tsx @@ -0,0 +1,176 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { FunctionComponent, useCallback, useMemo } from 'react'; +import { + EuiButton, + EuiPageHeader, + EuiPageHeaderProps, + EuiPageSection, + EuiSpacer, +} from '@elastic/eui'; +import { css } from '@emotion/react'; +import { FormattedMessage } from '@kbn/i18n-react'; +import { RouteComponentProps } from 'react-router-dom'; + +import { Index } from '../../../../../../common'; +import { + INDEX_OPEN, + IndexDetailsSection, + IndexDetailsTab, + IndexDetailsTabId, + Section, +} from '../../../../../../common/constants'; +import { getIndexDetailsLink } from '../../../../services/routing'; +import { useAppContext } from '../../../../app_context'; +import { DiscoverLink } from '../../../../lib/discover_link'; +import { ManageIndexButton } from './manage_index_button'; +import { DetailsPageOverview } from './details_page_overview'; +import { DetailsPageMappings } from './details_page_mappings'; +import { DetailsPageSettings } from './details_page_settings'; +import { DetailsPageStats } from './details_page_stats'; +import { DetailsPageTab } from './details_page_tab'; + +const defaultTabs: IndexDetailsTab[] = [ + { + id: IndexDetailsSection.Overview, + name: ( + + ), + renderTabContent: ({ index }) => , + order: 10, + }, + { + id: IndexDetailsSection.Mappings, + name: ( + + ), + renderTabContent: ({ index }) => , + order: 20, + }, + { + id: IndexDetailsSection.Settings, + name: ( + + ), + renderTabContent: ({ index }) => ( + + ), + order: 30, + }, +]; + +const statsTab: IndexDetailsTab = { + id: IndexDetailsSection.Stats, + name: , + renderTabContent: ({ index }) => ( + + ), + order: 40, +}; + +interface Props { + index: Index; + tab: IndexDetailsTabId; + history: RouteComponentProps['history']; + fetchIndexDetails: () => Promise; +} +export const DetailsPageContent: FunctionComponent = ({ + index, + tab, + history, + fetchIndexDetails, +}) => { + const { + config: { enableIndexStats }, + services: { extensionsService }, + } = useAppContext(); + + const tabs = useMemo(() => { + const sortedTabs = [...defaultTabs]; + if (enableIndexStats) { + sortedTabs.push(statsTab); + } + extensionsService.indexDetailsTabs.forEach((dynamicTab) => { + if (!dynamicTab.shouldRenderTab || dynamicTab.shouldRenderTab({ index })) { + sortedTabs.push(dynamicTab); + } + }); + + sortedTabs.sort((tabA, tabB) => { + return tabA.order - tabB.order; + }); + return sortedTabs; + }, [enableIndexStats, extensionsService.indexDetailsTabs, index]); + + const onSectionChange = useCallback( + (newSection: IndexDetailsTabId) => { + return history.push(getIndexDetailsLink(index.name, newSection)); + }, + [history, index] + ); + + const navigateToAllIndices = useCallback(() => { + history.push(`/${Section.Indices}`); + }, [history]); + + const headerTabs = useMemo(() => { + return tabs.map((tabConfig) => ({ + onClick: () => onSectionChange(tabConfig.id), + isSelected: tabConfig.id === tab, + key: tabConfig.id, + 'data-test-subj': `indexDetailsTab-${tabConfig.id}`, + label: tabConfig.name, + })); + }, [tabs, tab, onSectionChange]); + + return ( + <> + + + + + + + , + , + ]} + rightSideGroupProps={{ + wrap: false, + }} + responsive="reverse" + tabs={headerTabs} + /> + +
+ +
+ + ); +}; diff --git a/x-pack/plugins/index_management/public/application/sections/home/index_list/details_page/details_page_overview/details_page_overview.tsx b/x-pack/plugins/index_management/public/application/sections/home/index_list/details_page/details_page_overview/details_page_overview.tsx index 624a58f6e722a..0a9503c56cb59 100644 --- a/x-pack/plugins/index_management/public/application/sections/home/index_list/details_page/details_page_overview/details_page_overview.tsx +++ b/x-pack/plugins/index_management/public/application/sections/home/index_list/details_page/details_page_overview/details_page_overview.tsx @@ -32,7 +32,6 @@ import { useAppContext } from '../../../../../app_context'; import { documentationService } from '../../../../../services'; import { breadcrumbService, IndexManagementBreadcrumb } from '../../../../../services/breadcrumbs'; import { languageDefinitions, curlDefinition } from './languages'; -import { ExtensionsSummary } from './extensions_summary'; import { DataStreamDetails } from './data_stream_details'; import { StorageDetails } from './storage_details'; import { AliasesDetails } from './aliases_details'; @@ -55,7 +54,11 @@ export const DetailsPageOverview: React.FunctionComponent = ({ indexDetai size, primary_size: primarySize, } = indexDetails; - const { core, plugins } = useAppContext(); + const { + core, + plugins, + services: { extensionsService }, + } = useAppContext(); useEffect(() => { breadcrumbService.setBreadcrumbs(IndexManagementBreadcrumb.indexDetailsOverview); @@ -94,59 +97,64 @@ export const DetailsPageOverview: React.FunctionComponent = ({ indexDetai - - - - - -

- {i18n.translate('xpack.idxMgmt.indexDetails.overviewTab.addMoreDataTitle', { - defaultMessage: 'Add data to this index', - })} -

-
- - - - - -

- - - - ), - }} - /> -

-
-
-
- - - - -
+ {extensionsService.indexOverviewContent ? ( + extensionsService.indexOverviewContent.renderContent({ + index: indexDetails, + getUrlForApp: core.getUrlForApp, + }) + ) : ( + + + +

+ {i18n.translate('xpack.idxMgmt.indexDetails.overviewTab.addMoreDataTitle', { + defaultMessage: 'Add data to this index', + })} +

+
+ + + + + +

+ + + + ), + }} + /> +

+
+
+
+ + + + +
+ )} ); }; diff --git a/x-pack/plugins/index_management/public/application/sections/home/index_list/details_page/details_page_overview/extensions_summary.tsx b/x-pack/plugins/index_management/public/application/sections/home/index_list/details_page/details_page_overview/extensions_summary.tsx deleted file mode 100644 index b119a99cd1a0a..0000000000000 --- a/x-pack/plugins/index_management/public/application/sections/home/index_list/details_page/details_page_overview/extensions_summary.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; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React, { Fragment, FunctionComponent } from 'react'; -import { EuiPanel, EuiSpacer } from '@elastic/eui'; -import { Index } from '../../../../../../../common'; -import { useAppContext } from '../../../../../app_context'; - -export const ExtensionsSummary: FunctionComponent<{ index: Index }> = ({ index }) => { - const { - services: { extensionsService }, - core: { getUrlForApp }, - } = useAppContext(); - const summaries = extensionsService.summaries.map((summaryExtension, i) => { - const summary = summaryExtension({ index, getUrlForApp }); - - if (!summary) { - return null; - } - return ( - - - {summary} - - - - ); - }); - return <>{summaries}; -}; diff --git a/x-pack/plugins/index_management/public/application/sections/home/index_list/details_page/details_page_tab.tsx b/x-pack/plugins/index_management/public/application/sections/home/index_list/details_page/details_page_tab.tsx new file mode 100644 index 0000000000000..9f760aab91324 --- /dev/null +++ b/x-pack/plugins/index_management/public/application/sections/home/index_list/details_page/details_page_tab.tsx @@ -0,0 +1,29 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { FunctionComponent } from 'react'; +import { Index } from '../../../../../../common'; +import { IndexDetailsTab, IndexDetailsTabId } from '../../../../../../common/constants'; +import { useAppContext } from '../../../../app_context'; +import { DetailsPageOverview } from './details_page_overview'; + +interface Props { + tabs: IndexDetailsTab[]; + tab: IndexDetailsTabId; + index: Index; +} +export const DetailsPageTab: FunctionComponent = ({ tabs, tab, index }) => { + const selectedTab = tabs.find((tabConfig) => tabConfig.id === tab); + const { + core: { getUrlForApp }, + } = useAppContext(); + return selectedTab ? ( + selectedTab.renderTabContent({ index, getUrlForApp }) + ) : ( + + ); +}; diff --git a/x-pack/plugins/index_management/public/application/sections/home/index_list/details_page/manage_index_button.tsx b/x-pack/plugins/index_management/public/application/sections/home/index_list/details_page/manage_index_button.tsx index 2d7d7aab0d23f..8bfaffa51273f 100644 --- a/x-pack/plugins/index_management/public/application/sections/home/index_list/details_page/manage_index_button.tsx +++ b/x-pack/plugins/index_management/public/application/sections/home/index_list/details_page/manage_index_button.tsx @@ -41,21 +41,26 @@ const getIndexStatusByName = ( }; interface Props { - indexName: string; - indexDetails: Index; + index: Index; reloadIndexDetails: () => Promise; navigateToAllIndices: () => void; } + +/** + * This component is a wrapper for the underlying "index actions context menu" that is currently used + * in the indices list and works with redux. That is why all request helpers from the services are expecting + * an array of indices, for example "deleteIndices(indexNames)". + * + */ export const ManageIndexButton: FunctionComponent = ({ - indexName, - indexDetails, + index, reloadIndexDetails, navigateToAllIndices, }) => { const [isLoading, setIsLoading] = useState(false); - // the variables are created to write the index actions in a way to later re-use for indices list without redux - const indexNames = useMemo(() => [indexName], [indexName]); + // the "index actions context menu" component is expecting an array of indices, the same as on the indices list + const indexNames = useMemo(() => [index.name], [index]); const reloadIndices = useCallback(async () => { setIsLoading(true); @@ -63,7 +68,8 @@ export const ManageIndexButton: FunctionComponent = ({ setIsLoading(false); }, [reloadIndexDetails]); - const indices = [indexDetails]; + // the "index actions context menu" component is expecting an array of indices, the same as on the indices list + const indices = [index]; const indexStatusByName = getIndexStatusByName(indexNames, indices); const closeIndices = useCallback(async () => { diff --git a/x-pack/plugins/index_management/public/application/services/routing.ts b/x-pack/plugins/index_management/public/application/services/routing.ts index 1d3a41f0d54a3..3ec13eca06516 100644 --- a/x-pack/plugins/index_management/public/application/services/routing.ts +++ b/x-pack/plugins/index_management/public/application/services/routing.ts @@ -6,7 +6,7 @@ */ import { Section } from '../../../common/constants'; -import type { IndexDetailsTabIds } from '../../../common/constants'; +import type { IndexDetailsTabId } from '../../../common/constants'; export const getTemplateListLink = () => `/templates`; @@ -58,7 +58,7 @@ export const getDataStreamDetailsLink = (name: string) => { return encodeURI(`/data_streams/${encodeURIComponent(name)}`); }; -export const getIndexDetailsLink = (indexName: string, tab?: IndexDetailsTabIds) => { +export const getIndexDetailsLink = (indexName: string, tab?: IndexDetailsTabId) => { let link = `/${Section.Indices}/index_details?indexName=${encodeURIComponent(indexName)}`; if (tab) { link = `${link}&tab=${tab}`; diff --git a/x-pack/plugins/index_management/public/services/extensions_service.mock.ts b/x-pack/plugins/index_management/public/services/extensions_service.mock.ts index 6ef42d7944d67..3c0886b0fe4a3 100644 --- a/x-pack/plugins/index_management/public/services/extensions_service.mock.ts +++ b/x-pack/plugins/index_management/public/services/extensions_service.mock.ts @@ -15,9 +15,9 @@ const createServiceMock = (): ExtensionsSetupMock => ({ addBadge: jest.fn(), addBanner: jest.fn(), addFilter: jest.fn(), - addSummary: jest.fn(), addToggle: jest.fn(), addIndexDetailsTab: jest.fn(), + setIndexOverviewContent: jest.fn(), }); const createMock = () => { diff --git a/x-pack/plugins/index_management/public/services/extensions_service.ts b/x-pack/plugins/index_management/public/services/extensions_service.ts index 5c81e825eb1b1..5ffef366a016c 100644 --- a/x-pack/plugins/index_management/public/services/extensions_service.ts +++ b/x-pack/plugins/index_management/public/services/extensions_service.ts @@ -6,21 +6,29 @@ */ import { i18n } from '@kbn/i18n'; +import { FunctionComponent } from 'react'; +import { ApplicationStart } from '@kbn/core-application-browser'; import type { IndexDetailsTab } from '../../common/constants'; +import { Index } from '..'; + +export interface IndexOverviewContent { + renderContent: (args: { + index: Index; + getUrlForApp: ApplicationStart['getUrlForApp']; + }) => ReturnType; +} export interface ExtensionsSetup { - addSummary(summary: any): void; addAction(action: any): void; addBanner(banner: any): void; addFilter(filter: any): void; addBadge(badge: any): void; addToggle(toggle: any): void; addIndexDetailsTab(tab: IndexDetailsTab): void; + setIndexOverviewContent(content: IndexOverviewContent): void; } export class ExtensionsService { - private _indexDetailsTabs: IndexDetailsTab[] = []; - private _summaries: any[] = []; private _actions: any[] = []; private _banners: any[] = []; private _filters: any[] = []; @@ -37,6 +45,8 @@ export class ExtensionsService { }, ]; private _toggles: any[] = []; + private _indexDetailsTabs: IndexDetailsTab[] = []; + private _indexOverviewContent: IndexOverviewContent | null = null; private service?: ExtensionsSetup; public setup(): ExtensionsSetup { @@ -45,18 +55,14 @@ export class ExtensionsService { addBadge: this.addBadge.bind(this), addBanner: this.addBanner.bind(this), addFilter: this.addFilter.bind(this), - addSummary: this.addSummary.bind(this), addToggle: this.addToggle.bind(this), addIndexDetailsTab: this.addIndexDetailsTab.bind(this), + setIndexOverviewContent: this.setIndexOverviewMainContent.bind(this), }; return this.service; } - private addSummary(summary: any) { - this._summaries.push(summary); - } - private addAction(action: any) { this._actions.push(action); } @@ -81,8 +87,12 @@ export class ExtensionsService { this._indexDetailsTabs.push(tab); } - public get summaries() { - return this._summaries; + private setIndexOverviewMainContent(content: IndexOverviewContent) { + if (this._indexOverviewContent) { + throw new Error(`The content for index overview has already been set.`); + } else { + this._indexOverviewContent = content; + } } public get actions() { @@ -108,4 +118,8 @@ export class ExtensionsService { public get indexDetailsTabs() { return this._indexDetailsTabs; } + + public get indexOverviewContent() { + return this._indexOverviewContent; + } } diff --git a/x-pack/plugins/index_management/tsconfig.json b/x-pack/plugins/index_management/tsconfig.json index 7b52920e5e5d4..b1ccc4b12cdd5 100644 --- a/x-pack/plugins/index_management/tsconfig.json +++ b/x-pack/plugins/index_management/tsconfig.json @@ -41,6 +41,7 @@ "@kbn/search-api-panels", "@kbn/cloud-plugin", "@kbn/ui-theme", + "@kbn/core-application-browser", ], "exclude": [ "target/**/*", diff --git a/x-pack/plugins/infra/common/alerting/metrics/types.ts b/x-pack/plugins/infra/common/alerting/metrics/types.ts index 7ca0e9e64ca34..9121ec11adfab 100644 --- a/x-pack/plugins/infra/common/alerting/metrics/types.ts +++ b/x-pack/plugins/infra/common/alerting/metrics/types.ts @@ -7,8 +7,8 @@ import * as rt from 'io-ts'; import { TimeUnitChar } from '@kbn/observability-plugin/common/utils/formatters/duration'; import { ML_ANOMALY_THRESHOLD } from '@kbn/ml-anomaly-utils/anomaly_threshold'; +import { InventoryItemType, SnapshotMetricType } from '@kbn/metrics-data-access-plugin/common'; import { SnapshotCustomMetricInput } from '../../http_api'; -import { InventoryItemType, SnapshotMetricType } from '../../inventory_models/types'; export const METRIC_THRESHOLD_ALERT_TYPE_ID = 'metrics.alert.threshold'; export const METRIC_INVENTORY_THRESHOLD_ALERT_TYPE_ID = 'metrics.alert.inventory.threshold'; diff --git a/x-pack/plugins/infra/common/formatters/index.ts b/x-pack/plugins/infra/common/formatters/index.ts index efa4f2faf769f..4c60a46ffe2af 100644 --- a/x-pack/plugins/infra/common/formatters/index.ts +++ b/x-pack/plugins/infra/common/formatters/index.ts @@ -5,10 +5,10 @@ * 2.0. */ +import { InventoryFormatterType } from '@kbn/metrics-data-access-plugin/common'; import { createBytesFormatter } from './bytes'; import { formatNumber } from './number'; import { formatPercent } from './percent'; -import { InventoryFormatterType } from '../inventory_models/types'; import { formatHighPrecision } from './high_precision'; import { InfraWaffleMapDataFormat } from './types'; diff --git a/x-pack/plugins/infra/common/http_api/inventory_meta_api.ts b/x-pack/plugins/infra/common/http_api/inventory_meta_api.ts index 7221e518cf977..284a67907b73c 100644 --- a/x-pack/plugins/infra/common/http_api/inventory_meta_api.ts +++ b/x-pack/plugins/infra/common/http_api/inventory_meta_api.ts @@ -6,7 +6,7 @@ */ import * as rt from 'io-ts'; -import { ItemTypeRT } from '../inventory_models/types'; +import { ItemTypeRT } from '@kbn/metrics-data-access-plugin/common'; const CloudAccountRT = rt.type({ value: rt.string, diff --git a/x-pack/plugins/infra/common/http_api/metadata_api.ts b/x-pack/plugins/infra/common/http_api/metadata_api.ts index 360923e5307a1..194cce74258f2 100644 --- a/x-pack/plugins/infra/common/http_api/metadata_api.ts +++ b/x-pack/plugins/infra/common/http_api/metadata_api.ts @@ -6,7 +6,7 @@ */ import * as rt from 'io-ts'; -import { ItemTypeRT } from '../inventory_models/types'; +import { ItemTypeRT } from '@kbn/metrics-data-access-plugin/common'; export const InfraMetadataRequestRT = rt.type({ nodeId: rt.string, diff --git a/x-pack/plugins/infra/common/http_api/metrics_api.ts b/x-pack/plugins/infra/common/http_api/metrics_api.ts index d24c6ba2ce58f..c59dd1c64443c 100644 --- a/x-pack/plugins/infra/common/http_api/metrics_api.ts +++ b/x-pack/plugins/infra/common/http_api/metrics_api.ts @@ -7,7 +7,7 @@ import { createLiteralValueFromUndefinedRT } from '@kbn/io-ts-utils'; import * as rt from 'io-ts'; -import { MetricsUIAggregationRT } from '../inventory_models/types'; +import { MetricsUIAggregationRT } from '@kbn/metrics-data-access-plugin/common'; import { afterKeyObjectRT } from './metrics_explorer'; export const MetricsAPITimerangeRT = rt.intersection([ diff --git a/x-pack/plugins/infra/common/http_api/node_details_api.ts b/x-pack/plugins/infra/common/http_api/node_details_api.ts index 648f5fcba5688..e575ed04a5a93 100644 --- a/x-pack/plugins/infra/common/http_api/node_details_api.ts +++ b/x-pack/plugins/infra/common/http_api/node_details_api.ts @@ -6,7 +6,7 @@ */ import * as rt from 'io-ts'; -import { InventoryMetricRT, ItemTypeRT } from '../inventory_models/types'; +import { InventoryMetricRT, ItemTypeRT } from '@kbn/metrics-data-access-plugin/common'; import { InfraTimerangeInputRT } from './snapshot_api'; const NodeDetailsDataPointRT = rt.intersection([ diff --git a/x-pack/plugins/infra/common/http_api/snapshot_api.ts b/x-pack/plugins/infra/common/http_api/snapshot_api.ts index 6b3a683ef7d26..4742b4cbdd6c1 100644 --- a/x-pack/plugins/infra/common/http_api/snapshot_api.ts +++ b/x-pack/plugins/infra/common/http_api/snapshot_api.ts @@ -7,7 +7,7 @@ import { createLiteralValueFromUndefinedRT } from '@kbn/io-ts-utils'; import * as rt from 'io-ts'; -import { SnapshotMetricTypeRT, ItemTypeRT } from '../inventory_models/types'; +import { SnapshotMetricTypeRT, ItemTypeRT } from '@kbn/metrics-data-access-plugin/common'; import { MetricsAPISeriesRT } from './metrics_api'; export const SnapshotNodePathRT = rt.intersection([ diff --git a/x-pack/plugins/infra/common/inventory_models/intl_strings.ts b/x-pack/plugins/infra/common/inventory_models/intl_strings.ts index 8131f8c9a9f67..5a90113c9069e 100644 --- a/x-pack/plugins/infra/common/inventory_models/intl_strings.ts +++ b/x-pack/plugins/infra/common/inventory_models/intl_strings.ts @@ -6,8 +6,8 @@ */ import { i18n } from '@kbn/i18n'; +import { SnapshotMetricType, SnapshotMetricTypeKeys } from '@kbn/metrics-data-access-plugin/common'; import { toMetricOpt } from '../snapshot_metric_i18n'; -import { SnapshotMetricType, SnapshotMetricTypeKeys } from './types'; interface Lookup { [id: string]: string; diff --git a/x-pack/plugins/infra/common/inventory_views/types.ts b/x-pack/plugins/infra/common/inventory_views/types.ts index a493d2332f212..cae233c884f16 100644 --- a/x-pack/plugins/infra/common/inventory_views/types.ts +++ b/x-pack/plugins/infra/common/inventory_views/types.ts @@ -7,12 +7,12 @@ import { isoToEpochRt, nonEmptyStringRt, inRangeRt } from '@kbn/io-ts-utils'; import * as rt from 'io-ts'; +import { ItemTypeRT } from '@kbn/metrics-data-access-plugin/common'; import { SnapshotCustomMetricInputRT, SnapshotGroupByRT, SnapshotMetricInputRT, } from '../http_api/snapshot_api'; -import { ItemTypeRT } from '../inventory_models/types'; export const inventoryColorPaletteRT = rt.keyof({ status: null, diff --git a/x-pack/plugins/infra/common/locators/helpers.ts b/x-pack/plugins/infra/common/locators/helpers.ts index b4258053a0c01..582499407bb40 100644 --- a/x-pack/plugins/infra/common/locators/helpers.ts +++ b/x-pack/plugins/infra/common/locators/helpers.ts @@ -12,19 +12,19 @@ import { LogViewColumnConfiguration, LogViewReference, ResolvedLogView, + LogsLocatorParams, + NodeLogsLocatorParams, } from '@kbn/logs-shared-plugin/common'; import { flowRight } from 'lodash'; +import { findInventoryFields } from '@kbn/metrics-data-access-plugin/common'; import type { InfraClientCoreSetup } from '../../public/types'; import { MESSAGE_FIELD, TIMESTAMP_FIELD } from '../constants'; -import { findInventoryFields } from '../inventory_models'; import type { TimeRange } from '../time'; import { replaceLogFilterInQueryString, replaceLogPositionInQueryString, replaceLogViewInQueryString, } from '../url_state_storage_service'; -import type { LogsLocatorParams } from './logs_locator'; -import type { NodeLogsLocatorParams } from './node_logs_locator'; interface LocationToDiscoverParams { core: InfraClientCoreSetup; diff --git a/x-pack/plugins/infra/common/locators/locators.test.ts b/x-pack/plugins/infra/common/locators/locators.test.ts index c0573d942e757..fb6f8283b63fd 100644 --- a/x-pack/plugins/infra/common/locators/locators.test.ts +++ b/x-pack/plugins/infra/common/locators/locators.test.ts @@ -8,12 +8,15 @@ import { v4 as uuidv4 } from 'uuid'; import { LogsLocatorDefinition, LogsLocatorDependencies } from './logs_locator'; import { NodeLogsLocatorDefinition } from './node_logs_locator'; -import type { LogsLocatorParams } from './logs_locator'; -import type { NodeLogsLocatorParams } from './node_logs_locator'; import { coreMock } from '@kbn/core/public/mocks'; -import { findInventoryFields } from '../inventory_models'; +import { findInventoryFields } from '@kbn/metrics-data-access-plugin/common'; import moment from 'moment'; -import { DEFAULT_LOG_VIEW, LogViewReference } from '@kbn/logs-shared-plugin/common'; +import { + DEFAULT_LOG_VIEW, + LogViewReference, + LogsLocatorParams, + NodeLogsLocatorParams, +} from '@kbn/logs-shared-plugin/common'; const setupLogsLocator = async () => { const deps: LogsLocatorDependencies = { diff --git a/x-pack/plugins/infra/common/locators/logs_locator.ts b/x-pack/plugins/infra/common/locators/logs_locator.ts index ee9006f359e66..e481c0d53d390 100644 --- a/x-pack/plugins/infra/common/locators/logs_locator.ts +++ b/x-pack/plugins/infra/common/locators/logs_locator.ts @@ -6,24 +6,9 @@ */ import type { LocatorDefinition, LocatorPublic } from '@kbn/share-plugin/public'; -import { SerializableRecord } from '@kbn/utility-types'; -import type { LogViewReference } from '@kbn/logs-shared-plugin/common'; -import type { TimeRange } from '../time'; +import { LOGS_LOCATOR_ID, LogsLocatorParams } from '@kbn/logs-shared-plugin/common'; import type { InfraClientCoreSetup } from '../../public/types'; -export const LOGS_LOCATOR_ID = 'LOGS_LOCATOR'; - -export interface LogsLocatorParams extends SerializableRecord { - /** Defines log position */ - time?: number; - /** - * Optionally set the time range in the time picker. - */ - timeRange?: TimeRange; - filter?: string; - logView?: LogViewReference; -} - export type LogsLocator = LocatorPublic; export interface LogsLocatorDependencies { diff --git a/x-pack/plugins/infra/common/locators/node_logs_locator.ts b/x-pack/plugins/infra/common/locators/node_logs_locator.ts index abad1ea82c429..c8c53ec69292e 100644 --- a/x-pack/plugins/infra/common/locators/node_logs_locator.ts +++ b/x-pack/plugins/infra/common/locators/node_logs_locator.ts @@ -6,15 +6,8 @@ */ import type { LocatorDefinition, LocatorPublic } from '@kbn/share-plugin/public'; -import type { InventoryItemType } from '../inventory_models/types'; -import type { LogsLocatorDependencies, LogsLocatorParams } from './logs_locator'; - -export const NODE_LOGS_LOCATOR_ID = 'NODE_LOGS_LOCATOR'; - -export interface NodeLogsLocatorParams extends LogsLocatorParams { - nodeId: string; - nodeType: InventoryItemType; -} +import { NODE_LOGS_LOCATOR_ID, NodeLogsLocatorParams } from '@kbn/logs-shared-plugin/common'; +import type { LogsLocatorDependencies } from './logs_locator'; export type NodeLogsLocator = LocatorPublic; diff --git a/x-pack/plugins/infra/common/snapshot_metric_i18n.ts b/x-pack/plugins/infra/common/snapshot_metric_i18n.ts index 8aa56b236b4a1..3dc948d7bc82d 100644 --- a/x-pack/plugins/infra/common/snapshot_metric_i18n.ts +++ b/x-pack/plugins/infra/common/snapshot_metric_i18n.ts @@ -7,7 +7,7 @@ import { i18n } from '@kbn/i18n'; import { mapValues } from 'lodash'; -import { SnapshotMetricType } from './inventory_models/types'; +import { SnapshotMetricType } from '@kbn/metrics-data-access-plugin/common'; // Lowercase versions of all metrics, for when they need to be used in the middle of a sentence; // these may need to be translated differently depending on language, e.g. still capitalizing "CPU" diff --git a/x-pack/plugins/infra/public/alerting/inventory/components/alert_flyout.tsx b/x-pack/plugins/infra/public/alerting/inventory/components/alert_flyout.tsx index 0c9dfb731df86..41fdc1b6f7d30 100644 --- a/x-pack/plugins/infra/public/alerting/inventory/components/alert_flyout.tsx +++ b/x-pack/plugins/infra/public/alerting/inventory/components/alert_flyout.tsx @@ -7,10 +7,10 @@ import React, { useCallback, useContext, useMemo } from 'react'; +import { InventoryItemType } from '@kbn/metrics-data-access-plugin/common'; import { TriggerActionsContext } from '../../../utils/triggers_actions_context'; import { METRIC_INVENTORY_THRESHOLD_ALERT_TYPE_ID } from '../../../../common/alerting/metrics'; import { InfraWaffleMapOptions } from '../../../lib/lib'; -import { InventoryItemType } from '../../../../common/inventory_models/types'; import { useAlertPrefillContext } from '../../use_alert_prefill'; interface Props { diff --git a/x-pack/plugins/infra/public/alerting/inventory/components/expression.tsx b/x-pack/plugins/infra/public/alerting/inventory/components/expression.tsx index 6375a5032d365..8bfd458f98af2 100644 --- a/x-pack/plugins/infra/public/alerting/inventory/components/expression.tsx +++ b/x-pack/plugins/infra/public/alerting/inventory/components/expression.tsx @@ -31,6 +31,19 @@ import { import { debounce, omit } from 'lodash'; import React, { ChangeEvent, useCallback, useEffect, useMemo, useState } from 'react'; import useToggle from 'react-use/lib/useToggle'; +import { + findInventoryModel, + awsEC2SnapshotMetricTypes, + awsRDSSnapshotMetricTypes, + awsS3SnapshotMetricTypes, + awsSQSSnapshotMetricTypes, + containerSnapshotMetricTypes, + hostSnapshotMetricTypes, + podSnapshotMetricTypes, + InventoryItemType, + SnapshotMetricType, + SnapshotMetricTypeRT, +} from '@kbn/metrics-data-access-plugin/common'; import { Comparator, FilterQuery, @@ -41,19 +54,6 @@ import { SnapshotCustomMetricInput, SnapshotCustomMetricInputRT, } from '../../../../common/http_api/snapshot_api'; -import { findInventoryModel } from '../../../../common/inventory_models'; -import { awsEC2SnapshotMetricTypes } from '../../../../common/inventory_models/aws_ec2'; -import { awsRDSSnapshotMetricTypes } from '../../../../common/inventory_models/aws_rds'; -import { awsS3SnapshotMetricTypes } from '../../../../common/inventory_models/aws_s3'; -import { awsSQSSnapshotMetricTypes } from '../../../../common/inventory_models/aws_sqs'; -import { containerSnapshotMetricTypes } from '../../../../common/inventory_models/container'; -import { hostSnapshotMetricTypes } from '../../../../common/inventory_models/host'; -import { podSnapshotMetricTypes } from '../../../../common/inventory_models/pod'; -import { - InventoryItemType, - SnapshotMetricType, - SnapshotMetricTypeRT, -} from '../../../../common/inventory_models/types'; import { toMetricOpt } from '../../../../common/snapshot_metric_i18n'; import { DerivedIndexPattern, diff --git a/x-pack/plugins/infra/public/alerting/inventory/components/expression_chart.tsx b/x-pack/plugins/infra/public/alerting/inventory/components/expression_chart.tsx index 6f991254df780..5206f04237e6c 100644 --- a/x-pack/plugins/infra/public/alerting/inventory/components/expression_chart.tsx +++ b/x-pack/plugins/infra/public/alerting/inventory/components/expression_chart.tsx @@ -11,11 +11,11 @@ import { first, last } from 'lodash'; import moment from 'moment'; import React, { useCallback, useMemo } from 'react'; import { i18n } from '@kbn/i18n'; +import { InventoryItemType, SnapshotMetricType } from '@kbn/metrics-data-access-plugin/common'; import { useTimelineChartTheme } from '../../../utils/use_timeline_chart_theme'; import { InventoryMetricConditions } from '../../../../common/alerting/metrics'; import { Color } from '../../../../common/color_palette'; import { MetricsExplorerAggregation, MetricsExplorerRow } from '../../../../common/http_api'; -import { InventoryItemType, SnapshotMetricType } from '../../../../common/inventory_models/types'; import { useSnapshot } from '../../../pages/metrics/inventory_view/hooks/use_snaphot'; import { useWaffleOptionsContext } from '../../../pages/metrics/inventory_view/hooks/use_waffle_options'; import { createInventoryMetricFormatter } from '../../../pages/metrics/inventory_view/lib/create_inventory_metric_formatter'; diff --git a/x-pack/plugins/infra/public/alerting/inventory/components/node_type.tsx b/x-pack/plugins/infra/public/alerting/inventory/components/node_type.tsx index 1f07c314b3b2a..31c4ae45c105b 100644 --- a/x-pack/plugins/infra/public/alerting/inventory/components/node_type.tsx +++ b/x-pack/plugins/infra/public/alerting/inventory/components/node_type.tsx @@ -10,7 +10,7 @@ import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; import { EuiExpression, EuiPopover, EuiFlexGroup, EuiFlexItem, EuiSelect } from '@elastic/eui'; import { EuiPopoverTitle, EuiButtonIcon } from '@elastic/eui'; -import { InventoryItemType } from '../../../../common/inventory_models/types'; +import { InventoryItemType } from '@kbn/metrics-data-access-plugin/common'; interface WhenExpressionProps { value: InventoryItemType; diff --git a/x-pack/plugins/infra/public/alerting/inventory/hooks/use_inventory_alert_prefill.ts b/x-pack/plugins/infra/public/alerting/inventory/hooks/use_inventory_alert_prefill.ts index 5b246d95bd757..1fdbed3057aa0 100644 --- a/x-pack/plugins/infra/public/alerting/inventory/hooks/use_inventory_alert_prefill.ts +++ b/x-pack/plugins/infra/public/alerting/inventory/hooks/use_inventory_alert_prefill.ts @@ -6,11 +6,11 @@ */ import { useState } from 'react'; +import { InventoryItemType } from '@kbn/metrics-data-access-plugin/common'; import { SnapshotMetricInput, SnapshotCustomMetricInput, } from '../../../../common/http_api/snapshot_api'; -import { InventoryItemType } from '../../../../common/inventory_models/types'; export const useInventoryAlertPrefill = () => { const [nodeType, setNodeType] = useState('host'); diff --git a/x-pack/plugins/infra/public/alerting/log_threshold/log_threshold_rule_type.tsx b/x-pack/plugins/infra/public/alerting/log_threshold/log_threshold_rule_type.tsx index fe77e937445bf..1f2e8731a85df 100644 --- a/x-pack/plugins/infra/public/alerting/log_threshold/log_threshold_rule_type.tsx +++ b/x-pack/plugins/infra/public/alerting/log_threshold/log_threshold_rule_type.tsx @@ -8,7 +8,7 @@ import { i18n } from '@kbn/i18n'; import { ObservabilityRuleTypeModel } from '@kbn/observability-plugin/public'; import type { LocatorPublic } from '@kbn/share-plugin/public'; -import type { LogsLocatorParams } from '../../../common/locators'; +import type { LogsLocatorParams } from '@kbn/logs-shared-plugin/common'; import { LOG_DOCUMENT_COUNT_RULE_TYPE_ID, PartialRuleParams, diff --git a/x-pack/plugins/infra/public/alerting/log_threshold/rule_data_formatters.ts b/x-pack/plugins/infra/public/alerting/log_threshold/rule_data_formatters.ts index e9389b9e6a759..4d6e4cce322cf 100644 --- a/x-pack/plugins/infra/public/alerting/log_threshold/rule_data_formatters.ts +++ b/x-pack/plugins/infra/public/alerting/log_threshold/rule_data_formatters.ts @@ -8,7 +8,7 @@ import { ALERT_REASON, ALERT_START } from '@kbn/rule-data-utils'; import type { ObservabilityRuleTypeFormatter } from '@kbn/observability-plugin/public'; import type { LocatorPublic } from '@kbn/share-plugin/public'; -import type { LogsLocatorParams } from '../../../common/locators'; +import type { LogsLocatorParams } from '@kbn/logs-shared-plugin/common'; export const createRuleFormatter: ( logsLocator: LocatorPublic diff --git a/x-pack/plugins/infra/public/components/asset_details/hooks/use_metadata.ts b/x-pack/plugins/infra/public/components/asset_details/hooks/use_metadata.ts index 555712f6627ec..0bfb9a0900c42 100644 --- a/x-pack/plugins/infra/public/components/asset_details/hooks/use_metadata.ts +++ b/x-pack/plugins/infra/public/components/asset_details/hooks/use_metadata.ts @@ -9,12 +9,12 @@ import { useEffect } from 'react'; import { fold } from 'fp-ts/lib/Either'; import { identity } from 'fp-ts/lib/function'; import { pipe } from 'fp-ts/lib/pipeable'; +import type { InventoryItemType, InventoryMetric } from '@kbn/metrics-data-access-plugin/common'; import { Subject } from 'rxjs'; import { useHTTPRequest } from '../../../hooks/use_http_request'; import { type InfraMetadata, InfraMetadataRT } from '../../../../common/http_api/metadata_api'; import { throwErrors, createPlainError } from '../../../../common/runtime_types'; import { getFilteredMetrics } from '../../../pages/metrics/metric_detail/lib/get_filtered_metrics'; -import type { InventoryItemType, InventoryMetric } from '../../../../common/inventory_models/types'; interface UseMetadataProps { assetId: string; diff --git a/x-pack/plugins/infra/public/components/asset_details/links/link_to_node_details.tsx b/x-pack/plugins/infra/public/components/asset_details/links/link_to_node_details.tsx index 212b19753f80f..f4b3810479766 100644 --- a/x-pack/plugins/infra/public/components/asset_details/links/link_to_node_details.tsx +++ b/x-pack/plugins/infra/public/components/asset_details/links/link_to_node_details.tsx @@ -9,9 +9,9 @@ import { FormattedMessage } from '@kbn/i18n-react'; import { EuiButtonEmpty } from '@elastic/eui'; import { useLinkProps } from '@kbn/observability-shared-plugin/public'; import { parse } from '@kbn/datemath'; +import type { InventoryItemType } from '@kbn/metrics-data-access-plugin/common'; import { useNodeDetailsRedirect } from '../../../pages/link_to'; -import type { InventoryItemType } from '../../../../common/inventory_models/types'; import { useAssetDetailsUrlState } from '../hooks/use_asset_details_url_state'; export interface LinkToNodeDetailsProps { diff --git a/x-pack/plugins/infra/public/components/asset_details/tabs/logs/logs.tsx b/x-pack/plugins/infra/public/components/asset_details/tabs/logs/logs.tsx index a62a797ecfdef..1999c6604f553 100644 --- a/x-pack/plugins/infra/public/components/asset_details/tabs/logs/logs.tsx +++ b/x-pack/plugins/infra/public/components/asset_details/tabs/logs/logs.tsx @@ -13,8 +13,8 @@ import { EuiFieldSearch, EuiFlexGroup, EuiFlexItem, EuiButtonEmpty } from '@elas import { RedirectAppLinks } from '@kbn/shared-ux-link-redirect-app'; import { LogStream } from '@kbn/logs-shared-plugin/public'; import { DEFAULT_LOG_VIEW, LogViewReference } from '@kbn/logs-shared-plugin/common'; +import { findInventoryFields } from '@kbn/metrics-data-access-plugin/common'; import { useKibanaContextForPlugin } from '../../../../hooks/use_kibana'; -import { findInventoryFields } from '../../../../../common/inventory_models'; import { InfraLoadingPanel } from '../../../loading'; import { useAssetDetailsRenderPropsContext } from '../../hooks/use_asset_details_render_props'; import { useDataViewsProviderContext } from '../../hooks/use_data_views'; diff --git a/x-pack/plugins/infra/public/components/asset_details/tabs/overview/alerts.tsx b/x-pack/plugins/infra/public/components/asset_details/tabs/overview/alerts.tsx index 195ca67196b3c..9b964a0974a23 100644 --- a/x-pack/plugins/infra/public/components/asset_details/tabs/overview/alerts.tsx +++ b/x-pack/plugins/infra/public/components/asset_details/tabs/overview/alerts.tsx @@ -9,10 +9,10 @@ import React, { useMemo } from 'react'; import { EuiFlexGroup, EuiFlexItem, EuiSpacer } from '@elastic/eui'; import { useSummaryTimeRange } from '@kbn/observability-plugin/public'; import type { TimeRange } from '@kbn/es-query'; +import type { InventoryItemType } from '@kbn/metrics-data-access-plugin/common'; +import { findInventoryFields } from '@kbn/metrics-data-access-plugin/common'; import { usePluginConfig } from '../../../../containers/plugin_config_context'; import type { AlertsEsQuery } from '../../../../common/alerts/types'; -import type { InventoryItemType } from '../../../../../common/inventory_models/types'; -import { findInventoryFields } from '../../../../../common/inventory_models'; import { createAlertsEsQuery } from '../../../../common/alerts/create_alerts_es_query'; import { infraAlertFeatureIds } from '../../../../pages/metrics/hosts/components/tabs/config'; import { useKibanaContextForPlugin } from '../../../../hooks/use_kibana'; diff --git a/x-pack/plugins/infra/public/components/asset_details/tabs/processes/processes.tsx b/x-pack/plugins/infra/public/components/asset_details/tabs/processes/processes.tsx index fce43bdc4678f..be3aa0b5d6d0d 100644 --- a/x-pack/plugins/infra/public/components/asset_details/tabs/processes/processes.tsx +++ b/x-pack/plugins/infra/public/components/asset_details/tabs/processes/processes.tsx @@ -19,12 +19,12 @@ import { } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; import { EuiLoadingSpinner } from '@elastic/eui'; +import { getFieldByType } from '@kbn/metrics-data-access-plugin/common'; import { parseSearchString } from './parse_search_string'; import { ProcessesTable } from './processes_table'; import { STATE_NAMES } from './states'; import { SummaryTable } from './summary_table'; import { SortBy, useProcessList, ProcessListContextProvider } from '../../hooks/use_process_list'; -import { getFieldByType } from '../../../../../common/inventory_models'; import { useAssetDetailsRenderPropsContext } from '../../hooks/use_asset_details_render_props'; import { useDatePickerContext } from '../../hooks/use_date_picker'; import { ProcessesExplanationMessage } from '../../components/processes_explanation'; diff --git a/x-pack/plugins/infra/public/components/asset_details/types.ts b/x-pack/plugins/infra/public/components/asset_details/types.ts index 6aa5a021f77c6..56f62a5ebc086 100644 --- a/x-pack/plugins/infra/public/components/asset_details/types.ts +++ b/x-pack/plugins/infra/public/components/asset_details/types.ts @@ -7,7 +7,7 @@ import { TimeRange } from '@kbn/es-query'; import { Search } from 'history'; -import type { InventoryItemType } from '../../../common/inventory_models/types'; +import type { InventoryItemType } from '@kbn/metrics-data-access-plugin/common'; import type { InfraWaffleMapOptions } from '../../lib/lib'; export type { AssetDetailsUrlState } from './hooks/use_asset_details_url_state'; diff --git a/x-pack/plugins/infra/public/index.ts b/x-pack/plugins/infra/public/index.ts index 49a0257a22b38..74b071b6161cd 100644 --- a/x-pack/plugins/infra/public/index.ts +++ b/x-pack/plugins/infra/public/index.ts @@ -26,7 +26,5 @@ export const plugin: PluginInitializer< export { FORMATTERS } from '../common/formatters'; export { InfraFormatterType } from './lib/lib'; -export type InfraAppId = 'logs' | 'metrics'; - // Shared components export type { InfraClientStartExports } from './types'; diff --git a/x-pack/plugins/infra/public/mocks.tsx b/x-pack/plugins/infra/public/mocks.tsx index 9b232c515ce81..cb607111a992b 100644 --- a/x-pack/plugins/infra/public/mocks.tsx +++ b/x-pack/plugins/infra/public/mocks.tsx @@ -5,7 +5,6 @@ * 2.0. */ -import React from 'react'; import { createLocatorMock } from '../common/locators/locators.mock'; import { createInventoryViewsServiceStartMock } from './services/inventory_views/inventory_views_service.mock'; import { createMetricsExplorerViewsServiceStartMock } from './services/metrics_explorer_views/metrics_explorer_views_service.mock'; @@ -17,9 +16,6 @@ export const createInfraPluginStartMock = () => ({ metricsExplorerViews: createMetricsExplorerViewsServiceStartMock(), telemetry: createTelemetryServiceMock(), locators: createLocatorMock(), - ContainerMetricsTable: () =>
, - HostMetricsTable: () =>
, - PodMetricsTable: () =>
, }); export const _ensureTypeCompatibility = (): InfraClientStartExports => createInfraPluginStartMock(); diff --git a/x-pack/plugins/infra/public/pages/link_to/link_to_logs.tsx b/x-pack/plugins/infra/public/pages/link_to/link_to_logs.tsx index 52cdf12fe77b9..0e2e6eea6c49b 100644 --- a/x-pack/plugins/infra/public/pages/link_to/link_to_logs.tsx +++ b/x-pack/plugins/infra/public/pages/link_to/link_to_logs.tsx @@ -9,9 +9,9 @@ import React from 'react'; import { match as RouteMatch, Redirect } from 'react-router-dom'; import { Routes, Route } from '@kbn/shared-ux-router'; +import { inventoryModels } from '@kbn/metrics-data-access-plugin/common'; import { RedirectToLogs } from './redirect_to_logs'; import { RedirectToNodeLogs } from './redirect_to_node_logs'; -import { inventoryModels } from '../../../common/inventory_models'; interface LinkToPageProps { match: RouteMatch<{}>; diff --git a/x-pack/plugins/infra/public/pages/link_to/link_to_metrics.tsx b/x-pack/plugins/infra/public/pages/link_to/link_to_metrics.tsx index 0915d34ed35f3..a1280cb394079 100644 --- a/x-pack/plugins/infra/public/pages/link_to/link_to_metrics.tsx +++ b/x-pack/plugins/infra/public/pages/link_to/link_to_metrics.tsx @@ -9,10 +9,10 @@ import React from 'react'; import { match as RouteMatch, Redirect } from 'react-router-dom'; import { Routes, Route } from '@kbn/shared-ux-router'; +import { inventoryModels } from '@kbn/metrics-data-access-plugin/common'; import { RedirectToNodeDetail } from './redirect_to_node_detail'; import { RedirectToHostDetailViaIP } from './redirect_to_host_detail_via_ip'; import { RedirectToInventory } from './redirect_to_inventory'; -import { inventoryModels } from '../../../common/inventory_models'; interface LinkToPageProps { match: RouteMatch<{}>; diff --git a/x-pack/plugins/infra/public/pages/link_to/redirect_to_node_detail.tsx b/x-pack/plugins/infra/public/pages/link_to/redirect_to_node_detail.tsx index 606ab658bf648..f00691031b80d 100644 --- a/x-pack/plugins/infra/public/pages/link_to/redirect_to_node_detail.tsx +++ b/x-pack/plugins/infra/public/pages/link_to/redirect_to_node_detail.tsx @@ -8,9 +8,9 @@ import React from 'react'; import { Redirect, useLocation, useRouteMatch } from 'react-router-dom'; import rison from '@kbn/rison'; +import { InventoryItemType } from '@kbn/metrics-data-access-plugin/common'; import { replaceStateKeyInQueryString } from '../../../common/url_state_storage_service'; import { replaceMetricTimeInQueryString } from '../metrics/metric_detail/hooks/use_metrics_time'; -import { InventoryItemType } from '../../../common/inventory_models/types'; import { AssetDetailsUrlState } from '../../components/asset_details/types'; import { ASSET_DETAILS_URL_STATE_KEY } from '../../components/asset_details/constants'; diff --git a/x-pack/plugins/infra/public/pages/link_to/redirect_to_node_logs.tsx b/x-pack/plugins/infra/public/pages/link_to/redirect_to_node_logs.tsx index e3382d43c0e15..0eade78931ed0 100644 --- a/x-pack/plugins/infra/public/pages/link_to/redirect_to_node_logs.tsx +++ b/x-pack/plugins/infra/public/pages/link_to/redirect_to_node_logs.tsx @@ -8,7 +8,7 @@ import { useEffect } from 'react'; import { RouteComponentProps } from 'react-router-dom'; import { DEFAULT_LOG_VIEW } from '@kbn/logs-shared-plugin/common'; -import { InventoryItemType } from '../../../common/inventory_models/types'; +import { InventoryItemType } from '@kbn/metrics-data-access-plugin/common'; import { useKibanaContextForPlugin } from '../../hooks/use_kibana'; import { getFilterFromLocation, getTimeFromLocation } from './query_params'; diff --git a/x-pack/plugins/infra/public/pages/link_to/use_node_details_redirect.ts b/x-pack/plugins/infra/public/pages/link_to/use_node_details_redirect.ts index 6b6f2fda8a1f5..adcd5e9f2f2e5 100644 --- a/x-pack/plugins/infra/public/pages/link_to/use_node_details_redirect.ts +++ b/x-pack/plugins/infra/public/pages/link_to/use_node_details_redirect.ts @@ -10,7 +10,7 @@ import { useLocation } from 'react-router-dom'; import type { LinkDescriptor } from '@kbn/observability-shared-plugin/public'; import useObservable from 'react-use/lib/useObservable'; import rison from '@kbn/rison'; -import type { InventoryItemType } from '../../../common/inventory_models/types'; +import type { InventoryItemType } from '@kbn/metrics-data-access-plugin/common'; import type { AssetDetailsUrlState, RouteState } from '../../components/asset_details/types'; import { useKibanaContextForPlugin } from '../../hooks/use_kibana'; import { diff --git a/x-pack/plugins/infra/public/pages/metrics/hosts/components/hosts_table.tsx b/x-pack/plugins/infra/public/pages/metrics/hosts/components/hosts_table.tsx index d75fca31ce4d8..2082689cb6e1a 100644 --- a/x-pack/plugins/infra/public/pages/metrics/hosts/components/hosts_table.tsx +++ b/x-pack/plugins/infra/public/pages/metrics/hosts/components/hosts_table.tsx @@ -8,10 +8,9 @@ import React from 'react'; import { EuiBasicTable } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { NoData } from '../../../../components/empty_states'; +import { EuiEmptyPrompt } from '@elastic/eui'; import { HostNodeRow, useHostsTableContext } from '../hooks/use_hosts_table'; import { useHostsViewContext } from '../hooks/use_hosts_view'; -import { useUnifiedSearchContext } from '../hooks/use_unified_search'; import { FlyoutWrapper } from './host_details_flyout/flyout_wrapper'; import { DEFAULT_PAGE_SIZE } from '../constants'; import { FilterAction } from './table/filter_action'; @@ -20,7 +19,6 @@ const PAGE_SIZE_OPTIONS = [5, 10, 20]; export const HostsTable = () => { const { loading } = useHostsViewContext(); - const { onSubmit } = useUnifiedSearchContext(); const { columns, @@ -75,18 +73,21 @@ export const HostsTable = () => { defaultMessage: 'Loading data', }) ) : ( - onSubmit()} - testString="noMetricsDataPrompt" + data-test-subj="hostsViewTableNoData" + layout="vertical" + title={ +

+ {i18n.translate('xpack.infra.waffle.noDataTitle', { + defaultMessage: 'There is no data to display.', + })} +

+ } + hasBorder={false} + titleSize="m" /> ) } diff --git a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/bottom_drawer.tsx b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/bottom_drawer.tsx index 133fd1d7fbffd..882b5b5d84c42 100644 --- a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/bottom_drawer.tsx +++ b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/bottom_drawer.tsx @@ -11,7 +11,7 @@ import { EuiFlexGroup, EuiFlexItem, EuiButtonEmpty, EuiPanel } from '@elastic/eu import { euiStyled } from '@kbn/kibana-react-plugin/common'; import { useUiTracker } from '@kbn/observability-shared-plugin/public'; import useLocalStorage from 'react-use/lib/useLocalStorage'; -import { InventoryItemType } from '../../../../../common/inventory_models/types'; +import { InventoryItemType } from '@kbn/metrics-data-access-plugin/common'; import { TryItButton } from '../../../../components/try_it_button'; import { useWaffleOptionsContext } from '../hooks/use_waffle_options'; import { InfraFormatter } from '../../../../lib/lib'; diff --git a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/ml/anomaly_detection/anomalies_table/anomalies_table.tsx b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/ml/anomaly_detection/anomalies_table/anomalies_table.tsx index 25258a1aff1a4..5a96642ce22f9 100644 --- a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/ml/anomaly_detection/anomalies_table/anomalies_table.tsx +++ b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/ml/anomaly_detection/anomalies_table/anomalies_table.tsx @@ -29,9 +29,9 @@ import { FormattedMessage, FormattedDate } from '@kbn/i18n-react'; import { useLinkProps, useUiTracker } from '@kbn/observability-shared-plugin/public'; import type { TimeRange } from '@kbn/es-query'; import { css } from '@emotion/react'; +import type { SnapshotMetricType } from '@kbn/metrics-data-access-plugin/common'; import { Subject } from 'rxjs'; import { datemathToEpochMillis } from '../../../../../../../utils/datemath'; -import type { SnapshotMetricType } from '../../../../../../../../common/inventory_models/types'; import { useSorting } from '../../../../../../../hooks/use_sorting'; import { useMetricsK8sAnomaliesResults } from '../../../../hooks/use_metrics_k8s_anomalies'; import { useMetricsHostsAnomaliesResults } from '../../../../hooks/use_metrics_hosts_anomalies'; diff --git a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/nodes_overview.tsx b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/nodes_overview.tsx index fee52b3b4a8a7..878afbbc37576 100644 --- a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/nodes_overview.tsx +++ b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/nodes_overview.tsx @@ -9,7 +9,7 @@ import { i18n } from '@kbn/i18n'; import React, { useCallback } from 'react'; import { useCurrentEuiBreakpoint } from '@elastic/eui'; import { euiStyled } from '@kbn/kibana-react-plugin/common'; -import { InventoryItemType } from '../../../../../common/inventory_models/types'; +import { InventoryItemType } from '@kbn/metrics-data-access-plugin/common'; import { InfraWaffleMapBounds, InfraWaffleMapOptions, InfraFormatter } from '../../../../lib/lib'; import { NoData } from '../../../../components/empty_states'; import { InfraLoadingPanel } from '../../../../components/loading'; diff --git a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/table_view.tsx b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/table_view.tsx index dfede3481dca6..4791875958c67 100644 --- a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/table_view.tsx +++ b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/table_view.tsx @@ -11,11 +11,11 @@ import { i18n } from '@kbn/i18n'; import { last, first } from 'lodash'; import React, { useState, useMemo } from 'react'; import { EuiPopover } from '@elastic/eui'; +import { InventoryItemType } from '@kbn/metrics-data-access-plugin/common'; import { createWaffleMapNode } from '../lib/nodes_to_wafflemap'; import { InfraWaffleMapNode, InfraWaffleMapOptions } from '../../../../lib/lib'; import { fieldToName } from '../lib/field_to_display_name'; import { NodeContextMenu } from './waffle/node_context_menu'; -import { InventoryItemType } from '../../../../../common/inventory_models/types'; import { SnapshotNode, SnapshotNodePath } from '../../../../../common/http_api/snapshot_api'; interface Props { diff --git a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/toolbars/aws_ec2_toolbar_items.tsx b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/toolbars/aws_ec2_toolbar_items.tsx index ec593e4acd4db..3a5697aebcbcf 100644 --- a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/toolbars/aws_ec2_toolbar_items.tsx +++ b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/toolbars/aws_ec2_toolbar_items.tsx @@ -6,7 +6,7 @@ */ import React from 'react'; -import { awsEC2SnapshotMetricTypes } from '../../../../../../common/inventory_models/aws_ec2'; +import { awsEC2SnapshotMetricTypes } from '@kbn/metrics-data-access-plugin/common'; import { MetricsAndGroupByToolbarItems } from './metrics_and_groupby_toolbar_items'; import { CloudToolbarItems } from './cloud_toolbar_items'; import { ToolbarProps } from './types'; diff --git a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/toolbars/aws_rds_toolbar_items.tsx b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/toolbars/aws_rds_toolbar_items.tsx index 8d0661dfbab13..96663879afc88 100644 --- a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/toolbars/aws_rds_toolbar_items.tsx +++ b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/toolbars/aws_rds_toolbar_items.tsx @@ -6,7 +6,7 @@ */ import React from 'react'; -import { awsRDSSnapshotMetricTypes } from '../../../../../../common/inventory_models/aws_rds'; +import { awsRDSSnapshotMetricTypes } from '@kbn/metrics-data-access-plugin/common'; import { CloudToolbarItems } from './cloud_toolbar_items'; import { MetricsAndGroupByToolbarItems } from './metrics_and_groupby_toolbar_items'; import type { ToolbarProps } from './types'; diff --git a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/toolbars/aws_s3_toolbar_items.tsx b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/toolbars/aws_s3_toolbar_items.tsx index b60f99fed7c46..dc9e17bed1ae9 100644 --- a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/toolbars/aws_s3_toolbar_items.tsx +++ b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/toolbars/aws_s3_toolbar_items.tsx @@ -6,7 +6,7 @@ */ import React from 'react'; -import { awsS3SnapshotMetricTypes } from '../../../../../../common/inventory_models/aws_s3'; +import { awsS3SnapshotMetricTypes } from '@kbn/metrics-data-access-plugin/common'; import { CloudToolbarItems } from './cloud_toolbar_items'; import { MetricsAndGroupByToolbarItems } from './metrics_and_groupby_toolbar_items'; import type { ToolbarProps } from './types'; diff --git a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/toolbars/aws_sqs_toolbar_items.tsx b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/toolbars/aws_sqs_toolbar_items.tsx index 246a22e8a398a..a0a8e31db5cff 100644 --- a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/toolbars/aws_sqs_toolbar_items.tsx +++ b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/toolbars/aws_sqs_toolbar_items.tsx @@ -6,7 +6,7 @@ */ import React from 'react'; -import { awsSQSSnapshotMetricTypes } from '../../../../../../common/inventory_models/aws_sqs'; +import { awsSQSSnapshotMetricTypes } from '@kbn/metrics-data-access-plugin/common'; import { CloudToolbarItems } from './cloud_toolbar_items'; import { MetricsAndGroupByToolbarItems } from './metrics_and_groupby_toolbar_items'; import type { ToolbarProps } from './types'; diff --git a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/toolbars/container_toolbar_items.tsx b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/toolbars/container_toolbar_items.tsx index ac6f0d0f50dd1..2df067e8bbb0e 100644 --- a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/toolbars/container_toolbar_items.tsx +++ b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/toolbars/container_toolbar_items.tsx @@ -6,7 +6,7 @@ */ import React from 'react'; -import { containerSnapshotMetricTypes } from '../../../../../../common/inventory_models/container'; +import { containerSnapshotMetricTypes } from '@kbn/metrics-data-access-plugin/common'; import { MetricsAndGroupByToolbarItems } from './metrics_and_groupby_toolbar_items'; import type { ToolbarProps } from './types'; diff --git a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/toolbars/host_toolbar_items.tsx b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/toolbars/host_toolbar_items.tsx index 7a26829ec7d32..c6e3dfa83ac3c 100644 --- a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/toolbars/host_toolbar_items.tsx +++ b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/toolbars/host_toolbar_items.tsx @@ -5,7 +5,7 @@ * 2.0. */ import React from 'react'; -import { hostSnapshotMetricTypes } from '../../../../../../common/inventory_models/host'; +import { hostSnapshotMetricTypes } from '@kbn/metrics-data-access-plugin/common'; import { MetricsAndGroupByToolbarItems } from './metrics_and_groupby_toolbar_items'; import type { ToolbarProps } from './types'; diff --git a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/toolbars/metrics_and_groupby_toolbar_items.tsx b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/toolbars/metrics_and_groupby_toolbar_items.tsx index 6cc669e73e954..edf124978c093 100644 --- a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/toolbars/metrics_and_groupby_toolbar_items.tsx +++ b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/toolbars/metrics_and_groupby_toolbar_items.tsx @@ -7,7 +7,7 @@ import { EuiFlexItem } from '@elastic/eui'; import React, { useMemo } from 'react'; -import { SnapshotMetricType } from '../../../../../../common/inventory_models/types'; +import { SnapshotMetricType } from '@kbn/metrics-data-access-plugin/common'; import { toMetricOpt } from '../../../../../../common/snapshot_metric_i18n'; import { WaffleMetricControls } from '../waffle/metric_control'; import { WaffleGroupByControls } from '../waffle/waffle_group_by_controls'; diff --git a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/toolbars/pod_toolbar_items.tsx b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/toolbars/pod_toolbar_items.tsx index 0e12fbd5cc6d2..8eddd41c9e8be 100644 --- a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/toolbars/pod_toolbar_items.tsx +++ b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/toolbars/pod_toolbar_items.tsx @@ -6,7 +6,7 @@ */ import React from 'react'; -import { podSnapshotMetricTypes } from '../../../../../../common/inventory_models/pod'; +import { podSnapshotMetricTypes } from '@kbn/metrics-data-access-plugin/common'; import { MetricsAndGroupByToolbarItems } from './metrics_and_groupby_toolbar_items'; import type { ToolbarProps } from './types'; diff --git a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/toolbars/toolbar.tsx b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/toolbars/toolbar.tsx index 5711fad511d8e..12ca6a084c7d0 100644 --- a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/toolbars/toolbar.tsx +++ b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/toolbars/toolbar.tsx @@ -7,7 +7,7 @@ import { EuiFlexItem } from '@elastic/eui'; import React from 'react'; -import { InventoryItemType } from '../../../../../../common/inventory_models/types'; +import { InventoryItemType } from '@kbn/metrics-data-access-plugin/common'; import { useSourceContext } from '../../../../../containers/metrics_source'; import { useInventoryMeta } from '../../hooks/use_inventory_meta'; import { AwsEC2ToolbarItems } from './aws_ec2_toolbar_items'; diff --git a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/asset_details_flyout.tsx b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/asset_details_flyout.tsx index 63adcbb147b91..1a900fb3e55b7 100644 --- a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/asset_details_flyout.tsx +++ b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/asset_details_flyout.tsx @@ -7,9 +7,9 @@ import { i18n } from '@kbn/i18n'; import React, { useMemo } from 'react'; +import { InventoryItemType } from '@kbn/metrics-data-access-plugin/common'; import type { InfraWaffleMapOptions } from '../../../../../lib/lib'; import { ContentTabIds } from '../../../../../components/asset_details/types'; -import { InventoryItemType } from '../../../../../../common/inventory_models/types'; import AssetDetails from '../../../../../components/asset_details/asset_details'; import { useSourceContext } from '../../../../../containers/metrics_source'; import { commonFlyoutTabs } from '../../../../../common/asset_details_config/asset_details_tabs'; diff --git a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/conditional_tooltip.tsx b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/conditional_tooltip.tsx index 5ef86a7fd695b..4d82f7b7a39c8 100644 --- a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/conditional_tooltip.tsx +++ b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/conditional_tooltip.tsx @@ -9,15 +9,15 @@ import React from 'react'; import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import { first } from 'lodash'; import { withTheme, EuiTheme } from '@kbn/kibana-react-plugin/common'; -import { getCustomMetricLabel } from '../../../../../../common/formatters/get_custom_metric_label'; -import { SnapshotCustomMetricInput } from '../../../../../../common/http_api'; -import { useSourceContext } from '../../../../../containers/metrics_source'; -import { findInventoryModel } from '../../../../../../common/inventory_models'; +import { findInventoryModel } from '@kbn/metrics-data-access-plugin/common'; import { InventoryItemType, SnapshotMetricType, SnapshotMetricTypeRT, -} from '../../../../../../common/inventory_models/types'; +} from '@kbn/metrics-data-access-plugin/common'; +import { getCustomMetricLabel } from '../../../../../../common/formatters/get_custom_metric_label'; +import { SnapshotCustomMetricInput } from '../../../../../../common/http_api'; +import { useSourceContext } from '../../../../../containers/metrics_source'; import { InfraWaffleMapNode } from '../../../../../lib/lib'; import { useSnapshot } from '../../hooks/use_snaphot'; import { createInventoryMetricFormatter } from '../../lib/create_inventory_metric_formatter'; diff --git a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/group_of_groups.tsx b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/group_of_groups.tsx index 76dd103a25d1a..6ae50b1d356c3 100644 --- a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/group_of_groups.tsx +++ b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/group_of_groups.tsx @@ -8,6 +8,7 @@ import React from 'react'; import { euiStyled } from '@kbn/kibana-react-plugin/common'; +import { InventoryItemType } from '@kbn/metrics-data-access-plugin/common'; import { InfraWaffleMapBounds, InfraWaffleMapGroupOfGroups, @@ -15,7 +16,6 @@ import { } from '../../../../../lib/lib'; import { GroupName } from './group_name'; import { GroupOfNodes } from './group_of_nodes'; -import { InventoryItemType } from '../../../../../../common/inventory_models/types'; interface Props { onDrilldown: (filter: string) => void; diff --git a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/group_of_nodes.tsx b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/group_of_nodes.tsx index 1fe78bfdc142d..736a05c26908d 100644 --- a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/group_of_nodes.tsx +++ b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/group_of_nodes.tsx @@ -9,6 +9,7 @@ import React from 'react'; import { EuiLoadingSpinner } from '@elastic/eui'; import { isEqual } from 'lodash'; import { euiStyled } from '@kbn/kibana-react-plugin/common'; +import { InventoryItemType } from '@kbn/metrics-data-access-plugin/common'; import { InfraWaffleMapBounds, InfraWaffleMapGroupOfNodes, @@ -16,7 +17,6 @@ import { } from '../../../../../lib/lib'; import { GroupName } from './group_name'; import { Node } from './node'; -import { InventoryItemType } from '../../../../../../common/inventory_models/types'; import { useAssetDetailsFlyoutState } from '../../hooks/use_asset_details_flyout_url_state'; interface Props { diff --git a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/map.tsx b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/map.tsx index 920e893f5a4f7..dcbda63921b74 100644 --- a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/map.tsx +++ b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/map.tsx @@ -8,6 +8,7 @@ import React from 'react'; import { euiStyled } from '@kbn/kibana-react-plugin/common'; +import { InventoryItemType } from '@kbn/metrics-data-access-plugin/common'; import { nodesToWaffleMap } from '../../lib/nodes_to_wafflemap'; import { isWaffleMapGroupWithGroups, isWaffleMapGroupWithNodes } from '../../lib/type_guards'; import { InfraWaffleMapBounds, InfraWaffleMapOptions } from '../../../../../lib/lib'; @@ -16,7 +17,6 @@ import { GroupOfGroups } from './group_of_groups'; import { GroupOfNodes } from './group_of_nodes'; import { applyWaffleMapLayout } from '../../lib/apply_wafflemap_layout'; import { SnapshotNode } from '../../../../../../common/http_api/snapshot_api'; -import { InventoryItemType } from '../../../../../../common/inventory_models/types'; import { sortNodes } from '../../lib/sort_nodes'; interface Props { diff --git a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/metric_control/custom_metric_form.tsx b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/metric_control/custom_metric_form.tsx index 1767aa3476e44..c3cd96ca5ad43 100644 --- a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/metric_control/custom_metric_form.tsx +++ b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/metric_control/custom_metric_form.tsx @@ -6,7 +6,7 @@ */ import React, { useState, useCallback } from 'react'; -import { v1 as uuidv1 } from 'uuid'; +import { v4 as uuidv4 } from 'uuid'; import { EuiForm, EuiButton, @@ -78,7 +78,7 @@ export const CustomMetricForm = withTheme( } else if (aggregation && field) { const newMetric: SnapshotCustomMetricInput = { type: 'custom', - id: uuidv1(), + id: uuidv4(), label, aggregation, field, diff --git a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/metric_control/index.tsx b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/metric_control/index.tsx index 76432a27a3cdf..cab778feda4df 100644 --- a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/metric_control/index.tsx +++ b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/metric_control/index.tsx @@ -8,6 +8,7 @@ import { EuiPopover } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import React, { useState, useCallback } from 'react'; +import { SnapshotMetricType } from '@kbn/metrics-data-access-plugin/common'; import { getCustomMetricLabel } from '../../../../../../../common/formatters/get_custom_metric_label'; import { SnapshotMetricInput, @@ -19,7 +20,6 @@ import { MetricsContextMenu } from './metrics_context_menu'; import { ModeSwitcher } from './mode_switcher'; import { MetricsEditMode } from './metrics_edit_mode'; import { CustomMetricMode } from './types'; -import { SnapshotMetricType } from '../../../../../../../common/inventory_models/types'; import { DropdownButton } from '../../dropdown_button'; import { DerivedIndexPattern } from '../../../../../../containers/metrics_source'; diff --git a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/metric_control/metrics_context_menu.tsx b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/metric_control/metrics_context_menu.tsx index fa3d35ef1f97c..4085b9c5b051b 100644 --- a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/metric_control/metrics_context_menu.tsx +++ b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/metric_control/metrics_context_menu.tsx @@ -7,16 +7,13 @@ import React, { useCallback } from 'react'; import { EuiContextMenuPanelDescriptor, EuiContextMenu } from '@elastic/eui'; +import { SnapshotMetricTypeRT, SnapshotMetricType } from '@kbn/metrics-data-access-plugin/common'; import { getCustomMetricLabel } from '../../../../../../../common/formatters/get_custom_metric_label'; import { SnapshotMetricInput, SnapshotCustomMetricInput, SnapshotCustomMetricInputRT, } from '../../../../../../../common/http_api/snapshot_api'; -import { - SnapshotMetricTypeRT, - SnapshotMetricType, -} from '../../../../../../../common/inventory_models/types'; interface Props { options: Array<{ text: string; value: string }>; diff --git a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/node.tsx b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/node.tsx index c539d8faaf3e2..ea0627a0685c3 100644 --- a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/node.tsx +++ b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/node.tsx @@ -9,6 +9,7 @@ import React from 'react'; import { first } from 'lodash'; import { EuiPopover, EuiToolTip } from '@elastic/eui'; +import { InventoryItemType } from '@kbn/metrics-data-access-plugin/common'; import { useBoolean } from '../../../../../hooks/use_boolean'; import { InfraWaffleMapBounds, @@ -17,7 +18,6 @@ import { } from '../../../../../lib/lib'; import { ConditionalToolTip } from './conditional_tooltip'; import { colorFromValue } from '../../lib/color_from_value'; -import { InventoryItemType } from '../../../../../../common/inventory_models/types'; import { NodeContextMenu } from './node_context_menu'; import { NodeSquare } from './node_square'; diff --git a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/node_context_menu.tsx b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/node_context_menu.tsx index f27c4e8f2aba4..c989f3727f825 100644 --- a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/node_context_menu.tsx +++ b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/node_context_menu.tsx @@ -21,12 +21,12 @@ import { ActionMenuDivider, useLinkProps, } from '@kbn/observability-shared-plugin/public'; +import { findInventoryModel, findInventoryFields } from '@kbn/metrics-data-access-plugin/common'; +import { InventoryItemType } from '@kbn/metrics-data-access-plugin/common'; import { useKibanaContextForPlugin } from '../../../../../hooks/use_kibana'; import { AlertFlyout } from '../../../../../alerting/inventory/components/alert_flyout'; import { InfraWaffleMapNode, InfraWaffleMapOptions } from '../../../../../lib/lib'; import { useNodeDetailsRedirect } from '../../../../link_to'; -import { findInventoryModel, findInventoryFields } from '../../../../../../common/inventory_models'; -import { InventoryItemType } from '../../../../../../common/inventory_models/types'; import { navigateToUptime } from '../../lib/navigate_to_uptime'; interface Props { @@ -64,7 +64,16 @@ export const NodeContextMenu: React.FC = withTheme const inventoryId = useMemo(() => { if (nodeType === 'host') { if (node.ip) { - return { label: host.ip, value: node.ip }; + return { + label: ( + + {i18n.translate('xpack.infra.inventoryId.host.ipCodeLabel', { + defaultMessage: 'host.ip', + })} + + ), + value: node.ip, + }; } } else { const { id } = findInventoryFields(nodeType); diff --git a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/waffle_group_by_controls.tsx b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/waffle_group_by_controls.tsx index 419e41ae04557..48c0e60262236 100644 --- a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/waffle_group_by_controls.tsx +++ b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/waffle_group_by_controls.tsx @@ -16,9 +16,9 @@ import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; import React from 'react'; import { euiStyled } from '@kbn/kibana-react-plugin/common'; +import { InventoryItemType } from '@kbn/metrics-data-access-plugin/common'; import { InfraGroupByOptions } from '../../../../../lib/lib'; import { CustomFieldPanel } from './custom_field_panel'; -import { InventoryItemType } from '../../../../../../common/inventory_models/types'; import { SnapshotGroupBy } from '../../../../../../common/http_api/snapshot_api'; import { DropdownButton } from '../dropdown_button'; import { DerivedIndexPattern } from '../../../../../containers/metrics_source'; diff --git a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/waffle_inventory_switcher.tsx b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/waffle_inventory_switcher.tsx index 4dea25bd6cf70..29b3978573377 100644 --- a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/waffle_inventory_switcher.tsx +++ b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/waffle/waffle_inventory_switcher.tsx @@ -9,8 +9,8 @@ import { EuiPopover, EuiContextMenu, EuiContextMenuPanelDescriptor } from '@elas import React, { useCallback, useState, useMemo } from 'react'; import { i18n } from '@kbn/i18n'; -import { findInventoryModel } from '../../../../../../common/inventory_models'; -import { InventoryItemType } from '../../../../../../common/inventory_models/types'; +import { findInventoryModel } from '@kbn/metrics-data-access-plugin/common'; +import { InventoryItemType } from '@kbn/metrics-data-access-plugin/common'; import { useWaffleOptionsContext } from '../../hooks/use_waffle_options'; import { DropdownButton } from '../dropdown_button'; diff --git a/x-pack/plugins/infra/public/pages/metrics/inventory_view/hooks/use_inventory_meta.ts b/x-pack/plugins/infra/public/pages/metrics/inventory_view/hooks/use_inventory_meta.ts index b08e7f253e656..94a0ce54d301d 100644 --- a/x-pack/plugins/infra/public/pages/metrics/inventory_view/hooks/use_inventory_meta.ts +++ b/x-pack/plugins/infra/public/pages/metrics/inventory_view/hooks/use_inventory_meta.ts @@ -9,13 +9,13 @@ import { fold } from 'fp-ts/lib/Either'; import { identity } from 'fp-ts/lib/function'; import { pipe } from 'fp-ts/lib/pipeable'; import { useEffect } from 'react'; +import { InventoryItemType } from '@kbn/metrics-data-access-plugin/common'; import { throwErrors, createPlainError } from '../../../../../common/runtime_types'; import { useHTTPRequest } from '../../../../hooks/use_http_request'; import { InventoryMetaResponseRT, InventoryMetaResponse, } from '../../../../../common/http_api/inventory_meta_api'; -import { InventoryItemType } from '../../../../../common/inventory_models/types'; export function useInventoryMeta( sourceId: string, diff --git a/x-pack/plugins/infra/public/pages/metrics/inventory_view/hooks/use_timeline.ts b/x-pack/plugins/infra/public/pages/metrics/inventory_view/hooks/use_timeline.ts index 31c2ce9e186ef..d603972743e0a 100644 --- a/x-pack/plugins/infra/public/pages/metrics/inventory_view/hooks/use_timeline.ts +++ b/x-pack/plugins/infra/public/pages/metrics/inventory_view/hooks/use_timeline.ts @@ -10,6 +10,7 @@ import { identity } from 'fp-ts/lib/function'; import { pipe } from 'fp-ts/lib/pipeable'; import { first } from 'lodash'; import { useEffect, useMemo, useCallback } from 'react'; +import type { InventoryItemType, SnapshotMetricType } from '@kbn/metrics-data-access-plugin/common'; import { getIntervalInSeconds } from '../../../../../common/utils/get_interval_in_seconds'; import { throwErrors, createPlainError } from '../../../../../common/runtime_types'; import { useHTTPRequest } from '../../../../hooks/use_http_request'; @@ -19,10 +20,6 @@ import { SnapshotRequest, InfraTimerangeInput, } from '../../../../../common/http_api/snapshot_api'; -import type { - InventoryItemType, - SnapshotMetricType, -} from '../../../../../common/inventory_models/types'; const ONE_MINUTE = 60; const ONE_HOUR = ONE_MINUTE * 60; diff --git a/x-pack/plugins/infra/public/pages/metrics/inventory_view/hooks/use_waffle_options.ts b/x-pack/plugins/infra/public/pages/metrics/inventory_view/hooks/use_waffle_options.ts index 9151e591a09f1..2303602ec5cda 100644 --- a/x-pack/plugins/infra/public/pages/metrics/inventory_view/hooks/use_waffle_options.ts +++ b/x-pack/plugins/infra/public/pages/metrics/inventory_view/hooks/use_waffle_options.ts @@ -10,6 +10,7 @@ import { pipe } from 'fp-ts/lib/pipeable'; import { fold } from 'fp-ts/lib/Either'; import { constant, identity } from 'fp-ts/lib/function'; import createContainer from 'constate'; +import type { InventoryItemType } from '@kbn/metrics-data-access-plugin/common'; import { InventoryViewOptions } from '../../../../../common/inventory_views/types'; import { type InventoryLegendOptions, @@ -24,7 +25,6 @@ import type { SnapshotCustomMetricInput, } from '../../../../../common/http_api/snapshot_api'; import { useUrlState } from '../../../../utils/use_url_state'; -import type { InventoryItemType } from '../../../../../common/inventory_models/types'; export const DEFAULT_LEGEND: WaffleLegendOptions = { palette: 'cool', diff --git a/x-pack/plugins/infra/public/pages/metrics/inventory_view/lib/create_inventory_metric_formatter.ts b/x-pack/plugins/infra/public/pages/metrics/inventory_view/lib/create_inventory_metric_formatter.ts index a43589759ee6e..f056337265ece 100644 --- a/x-pack/plugins/infra/public/pages/metrics/inventory_view/lib/create_inventory_metric_formatter.ts +++ b/x-pack/plugins/infra/public/pages/metrics/inventory_view/lib/create_inventory_metric_formatter.ts @@ -6,7 +6,7 @@ */ import { get, isNumber } from 'lodash'; -import { SnapshotMetricType } from '../../../../../common/inventory_models/types'; +import { SnapshotMetricType } from '@kbn/metrics-data-access-plugin/common'; import { InfraFormatterType } from '../../../../lib/lib'; import { SnapshotMetricInput, diff --git a/x-pack/plugins/infra/public/pages/metrics/inventory_view/lib/navigate_to_uptime.ts b/x-pack/plugins/infra/public/pages/metrics/inventory_view/lib/navigate_to_uptime.ts index 74ce3dc55e999..6996bbd50fe32 100644 --- a/x-pack/plugins/infra/public/pages/metrics/inventory_view/lib/navigate_to_uptime.ts +++ b/x-pack/plugins/infra/public/pages/metrics/inventory_view/lib/navigate_to_uptime.ts @@ -7,8 +7,8 @@ import { uptimeOverviewLocatorID } from '@kbn/observability-plugin/public'; import { LocatorClient } from '@kbn/share-plugin/common/url_service/locators'; +import { InventoryItemType } from '@kbn/metrics-data-access-plugin/common'; import { InfraWaffleMapNode } from '../../../../lib/lib'; -import { InventoryItemType } from '../../../../../common/inventory_models/types'; export const navigateToUptime = ( locators: LocatorClient, diff --git a/x-pack/plugins/infra/public/pages/metrics/metric_detail/asset_detail_page.tsx b/x-pack/plugins/infra/public/pages/metrics/metric_detail/asset_detail_page.tsx index 216c32abaa0b1..e52008e2a90ab 100644 --- a/x-pack/plugins/infra/public/pages/metrics/metric_detail/asset_detail_page.tsx +++ b/x-pack/plugins/infra/public/pages/metrics/metric_detail/asset_detail_page.tsx @@ -7,11 +7,11 @@ import React from 'react'; import { useRouteMatch } from 'react-router-dom'; +import type { InventoryItemType } from '@kbn/metrics-data-access-plugin/common'; import { NoRemoteCluster } from '../../../components/empty_states'; import { SourceErrorPage } from '../../../components/source_error_page'; import { SourceLoadingPage } from '../../../components/source_loading_page'; import { useSourceContext } from '../../../containers/metrics_source'; -import type { InventoryItemType } from '../../../../common/inventory_models/types'; import { AssetDetails } from '../../../components/asset_details/asset_details'; import { MetricsPageTemplate } from '../page_template'; import { commonFlyoutTabs } from '../../../common/asset_details_config/asset_details_tabs'; diff --git a/x-pack/plugins/infra/public/pages/metrics/metric_detail/components/gauges_section_vis.tsx b/x-pack/plugins/infra/public/pages/metrics/metric_detail/components/gauges_section_vis.tsx index 6faa13f31fc80..5106aecfc29f2 100644 --- a/x-pack/plugins/infra/public/pages/metrics/metric_detail/components/gauges_section_vis.tsx +++ b/x-pack/plugins/infra/public/pages/metrics/metric_detail/components/gauges_section_vis.tsx @@ -18,8 +18,8 @@ import { get, last, max } from 'lodash'; import React, { ReactText } from 'react'; import { euiStyled } from '@kbn/kibana-react-plugin/common'; +import { InventoryFormatterType } from '@kbn/metrics-data-access-plugin/common'; import { createFormatter } from '../../../../../common/formatters'; -import { InventoryFormatterType } from '../../../../../common/inventory_models/types'; import { SeriesOverrides, VisSectionProps } from '../types'; import { getChartName } from './helpers'; diff --git a/x-pack/plugins/infra/public/pages/metrics/metric_detail/components/helpers.ts b/x-pack/plugins/infra/public/pages/metrics/metric_detail/components/helpers.ts index 0602e8a39b03b..ff3147def0d77 100644 --- a/x-pack/plugins/infra/public/pages/metrics/metric_detail/components/helpers.ts +++ b/x-pack/plugins/infra/public/pages/metrics/metric_detail/components/helpers.ts @@ -8,12 +8,12 @@ import { ReactText } from 'react'; import Color from 'color'; import { get, first, last, min, max } from 'lodash'; -import { createFormatter } from '../../../../../common/formatters'; import { InventoryVisTypeRT, InventoryFormatterType, InventoryVisType, -} from '../../../../../common/inventory_models/types'; +} from '@kbn/metrics-data-access-plugin/common'; +import { createFormatter } from '../../../../../common/formatters'; import { SeriesOverrides } from '../types'; import { NodeDetailsDataSeries, diff --git a/x-pack/plugins/infra/public/pages/metrics/metric_detail/components/layout.tsx b/x-pack/plugins/infra/public/pages/metrics/metric_detail/components/layout.tsx index c89fa6f7fe601..041d8b81da756 100644 --- a/x-pack/plugins/infra/public/pages/metrics/metric_detail/components/layout.tsx +++ b/x-pack/plugins/infra/public/pages/metrics/metric_detail/components/layout.tsx @@ -6,7 +6,7 @@ */ import React from 'react'; -import { InventoryItemType } from '../../../../../common/inventory_models/types'; +import { InventoryItemType } from '@kbn/metrics-data-access-plugin/common'; import { LayoutProps } from '../types'; import { AwsEC2Layout } from './layouts/aws_ec2_layout'; import { AwsRDSLayout } from './layouts/aws_rds_layout'; diff --git a/x-pack/plugins/infra/public/pages/metrics/metric_detail/components/node_details_page.tsx b/x-pack/plugins/infra/public/pages/metrics/metric_detail/components/node_details_page.tsx index 0ef201b612f2f..fdc274a6d06f7 100644 --- a/x-pack/plugins/infra/public/pages/metrics/metric_detail/components/node_details_page.tsx +++ b/x-pack/plugins/infra/public/pages/metrics/metric_detail/components/node_details_page.tsx @@ -9,9 +9,9 @@ import React, { useCallback, useEffect, useState } from 'react'; import dateMath from '@kbn/datemath'; import moment from 'moment'; import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; +import { InventoryMetric, InventoryItemType } from '@kbn/metrics-data-access-plugin/common'; import { useTemplateHeaderBreadcrumbs } from '../../../../components/asset_details/hooks/use_page_header'; import { useSourceContext } from '../../../../containers/metrics_source'; -import { InventoryMetric, InventoryItemType } from '../../../../../common/inventory_models/types'; import { useNodeDetails } from '../hooks/use_node_details'; import { MetricsSideNav } from './side_nav'; import { MetricsTimeControls } from './time_controls'; diff --git a/x-pack/plugins/infra/public/pages/metrics/metric_detail/components/page_body.tsx b/x-pack/plugins/infra/public/pages/metrics/metric_detail/components/page_body.tsx index 247f68a057d80..51933e753bd68 100644 --- a/x-pack/plugins/infra/public/pages/metrics/metric_detail/components/page_body.tsx +++ b/x-pack/plugins/infra/public/pages/metrics/metric_detail/components/page_body.tsx @@ -7,8 +7,8 @@ import { i18n } from '@kbn/i18n'; import React from 'react'; +import { InventoryItemType } from '@kbn/metrics-data-access-plugin/common'; import { NodeDetailsMetricData } from '../../../../../common/http_api/node_details_api'; -import { InventoryItemType } from '../../../../../common/inventory_models/types'; import { NoData } from '../../../../components/empty_states'; import { InfraLoadingPanel } from '../../../../components/loading'; import { MetricsTimeInput } from '../hooks/use_metrics_time'; diff --git a/x-pack/plugins/infra/public/pages/metrics/metric_detail/components/series_chart.tsx b/x-pack/plugins/infra/public/pages/metrics/metric_detail/components/series_chart.tsx index 22079943efb54..8d8d28e3abd52 100644 --- a/x-pack/plugins/infra/public/pages/metrics/metric_detail/components/series_chart.tsx +++ b/x-pack/plugins/infra/public/pages/metrics/metric_detail/components/series_chart.tsx @@ -14,8 +14,8 @@ import { BarSeriesStyle, AreaSeriesStyle, } from '@elastic/charts'; +import { InventoryVisType } from '@kbn/metrics-data-access-plugin/common'; import { NodeDetailsDataSeries } from '../../../../../common/http_api/node_details_api'; -import { InventoryVisType } from '../../../../../common/inventory_models/types'; import { useKibanaTimeZoneSetting } from '../../../../hooks/use_kibana_time_zone_setting'; interface Props { diff --git a/x-pack/plugins/infra/public/pages/metrics/metric_detail/components/sub_section.tsx b/x-pack/plugins/infra/public/pages/metrics/metric_detail/components/sub_section.tsx index 6dd52bd183dc7..10d8908c79374 100644 --- a/x-pack/plugins/infra/public/pages/metrics/metric_detail/components/sub_section.tsx +++ b/x-pack/plugins/infra/public/pages/metrics/metric_detail/components/sub_section.tsx @@ -7,7 +7,7 @@ import React, { isValidElement, cloneElement, FunctionComponent, Children, useMemo } from 'react'; import { EuiTitle } from '@elastic/eui'; -import { InventoryMetric } from '../../../../../common/inventory_models/types'; +import { InventoryMetric } from '@kbn/metrics-data-access-plugin/common'; import { LayoutProps } from '../types'; type SubSectionProps = LayoutProps & { diff --git a/x-pack/plugins/infra/public/pages/metrics/metric_detail/hooks/use_node_details.ts b/x-pack/plugins/infra/public/pages/metrics/metric_detail/hooks/use_node_details.ts index c75af97a12ce3..b5e8cc5367c1f 100644 --- a/x-pack/plugins/infra/public/pages/metrics/metric_detail/hooks/use_node_details.ts +++ b/x-pack/plugins/infra/public/pages/metrics/metric_detail/hooks/use_node_details.ts @@ -8,13 +8,13 @@ import { fold } from 'fp-ts/lib/Either'; import { identity } from 'fp-ts/lib/function'; import { pipe } from 'fp-ts/lib/pipeable'; +import { InventoryMetric, InventoryItemType } from '@kbn/metrics-data-access-plugin/common'; import { throwErrors, createPlainError } from '../../../../../common/runtime_types'; import { useHTTPRequest } from '../../../../hooks/use_http_request'; import { NodeDetailsMetricDataResponseRT, NodeDetailsMetricDataResponse, } from '../../../../../common/http_api/node_details_api'; -import { InventoryMetric, InventoryItemType } from '../../../../../common/inventory_models/types'; import { InfraTimerangeInput } from '../../../../../common/http_api/snapshot_api'; export function useNodeDetails( diff --git a/x-pack/plugins/infra/public/pages/metrics/metric_detail/index.tsx b/x-pack/plugins/infra/public/pages/metrics/metric_detail/index.tsx index dbccacb36adba..f05a5d3d2dc2e 100644 --- a/x-pack/plugins/infra/public/pages/metrics/metric_detail/index.tsx +++ b/x-pack/plugins/infra/public/pages/metrics/metric_detail/index.tsx @@ -8,8 +8,8 @@ import { EuiErrorBoundary } from '@elastic/eui'; import React from 'react'; import { useRouteMatch } from 'react-router-dom'; +import type { InventoryItemType } from '@kbn/metrics-data-access-plugin/common'; import { useMetricsBreadcrumbs } from '../../../hooks/use_metrics_breadcrumbs'; -import type { InventoryItemType } from '../../../../common/inventory_models/types'; import { AssetDetailPage } from './asset_detail_page'; import { MetricDetailPage } from './metric_detail_page'; import { MetricsTimeProvider } from './hooks/use_metrics_time'; diff --git a/x-pack/plugins/infra/public/pages/metrics/metric_detail/lib/get_filtered_metrics.ts b/x-pack/plugins/infra/public/pages/metrics/metric_detail/lib/get_filtered_metrics.ts index d1ba4502f37c3..7f10c7aa4aa7d 100644 --- a/x-pack/plugins/infra/public/pages/metrics/metric_detail/lib/get_filtered_metrics.ts +++ b/x-pack/plugins/infra/public/pages/metrics/metric_detail/lib/get_filtered_metrics.ts @@ -5,9 +5,9 @@ * 2.0. */ +import { InventoryMetric } from '@kbn/metrics-data-access-plugin/common'; +import { metrics } from '@kbn/metrics-data-access-plugin/common'; import { InfraMetadataFeature } from '../../../../../common/http_api/metadata_api'; -import { InventoryMetric } from '../../../../../common/inventory_models/types'; -import { metrics } from '../../../../../common/inventory_models/metrics'; import { TIMESTAMP_FIELD } from '../../../../../common/constants'; export const getFilteredMetrics = ( diff --git a/x-pack/plugins/infra/public/pages/metrics/metric_detail/metric_detail_page.tsx b/x-pack/plugins/infra/public/pages/metrics/metric_detail/metric_detail_page.tsx index 15425ef618049..4dd0da57536e2 100644 --- a/x-pack/plugins/infra/public/pages/metrics/metric_detail/metric_detail_page.tsx +++ b/x-pack/plugins/infra/public/pages/metrics/metric_detail/metric_detail_page.tsx @@ -8,14 +8,14 @@ import { i18n } from '@kbn/i18n'; import React, { useState } from 'react'; import { useRouteMatch } from 'react-router-dom'; +import { findInventoryModel } from '@kbn/metrics-data-access-plugin/common'; +import type { InventoryItemType } from '@kbn/metrics-data-access-plugin/common'; import { useMetricsBreadcrumbs } from '../../../hooks/use_metrics_breadcrumbs'; import { useMetadata } from '../../../components/asset_details/hooks/use_metadata'; import { useSourceContext } from '../../../containers/metrics_source'; import { InfraLoadingPanel } from '../../../components/loading'; -import { findInventoryModel } from '../../../../common/inventory_models'; import type { NavItem } from './lib/side_nav_context'; import { NodeDetailsPage } from './components/node_details_page'; -import type { InventoryItemType } from '../../../../common/inventory_models/types'; import { useMetricsTimeContext } from './hooks/use_metrics_time'; import { MetricsPageTemplate } from '../page_template'; diff --git a/x-pack/plugins/infra/public/pages/metrics/metric_detail/types.ts b/x-pack/plugins/infra/public/pages/metrics/metric_detail/types.ts index 31399b5f8696c..2cf5c8844d726 100644 --- a/x-pack/plugins/infra/public/pages/metrics/metric_detail/types.ts +++ b/x-pack/plugins/infra/public/pages/metrics/metric_detail/types.ts @@ -7,7 +7,7 @@ import rt from 'io-ts'; import { EuiTheme } from '@kbn/kibana-react-plugin/common'; -import { InventoryFormatterTypeRT } from '../../../../common/inventory_models/types'; +import { InventoryFormatterTypeRT } from '@kbn/metrics-data-access-plugin/common'; import { MetricsTimeInput } from './hooks/use_metrics_time'; import { NodeDetailsMetricData } from '../../../../common/http_api/node_details_api'; diff --git a/x-pack/plugins/infra/public/pages/metrics/metrics_explorer/components/chart_context_menu.tsx b/x-pack/plugins/infra/public/pages/metrics/metrics_explorer/components/chart_context_menu.tsx index f52a137b8792c..a793d69ea2d27 100644 --- a/x-pack/plugins/infra/public/pages/metrics/metrics_explorer/components/chart_context_menu.tsx +++ b/x-pack/plugins/infra/public/pages/metrics/metrics_explorer/components/chart_context_menu.tsx @@ -17,6 +17,7 @@ import { import DateMath from '@kbn/datemath'; import { Capabilities } from '@kbn/core/public'; import { useLinkProps } from '@kbn/observability-shared-plugin/public'; +import { InventoryItemType } from '@kbn/metrics-data-access-plugin/common'; import { MetricsSourceConfigurationProperties } from '../../../../../common/metrics_sources'; import { AlertFlyout } from '../../../../alerting/metric_threshold/components/alert_flyout'; import { MetricsExplorerSeries } from '../../../../../common/http_api/metrics_explorer'; @@ -27,7 +28,6 @@ import { } from '../hooks/use_metrics_explorer_options'; import { createTSVBLink } from './helpers/create_tsvb_link'; import { useNodeDetailsRedirect } from '../../../link_to'; -import { InventoryItemType } from '../../../../../common/inventory_models/types'; import { HOST_FIELD, POD_FIELD, CONTAINER_FIELD } from '../../../../../common/constants'; export interface Props { diff --git a/x-pack/plugins/infra/public/pages/metrics/metrics_explorer/components/helpers/create_tsvb_link.test.ts b/x-pack/plugins/infra/public/pages/metrics/metrics_explorer/components/helpers/create_tsvb_link.test.ts index 10aeeadb74060..ec41d0ff770d1 100644 --- a/x-pack/plugins/infra/public/pages/metrics/metrics_explorer/components/helpers/create_tsvb_link.test.ts +++ b/x-pack/plugins/infra/public/pages/metrics/metrics_explorer/components/helpers/create_tsvb_link.test.ts @@ -18,7 +18,7 @@ import { } from '../../hooks/use_metrics_explorer_options'; import { MetricsExplorerOptions } from '../../hooks/use_metrics_explorer_options'; jest.mock('uuid', () => ({ - v1: jest.fn().mockReturnValue('test-id'), + v4: jest.fn().mockReturnValue('test-id'), })); const series = { id: 'example-01', rows: [], columns: [] }; diff --git a/x-pack/plugins/infra/public/pages/metrics/metrics_explorer/components/helpers/create_tsvb_link.ts b/x-pack/plugins/infra/public/pages/metrics/metrics_explorer/components/helpers/create_tsvb_link.ts index a97f8bc862d3c..2725dc46d5cea 100644 --- a/x-pack/plugins/infra/public/pages/metrics/metrics_explorer/components/helpers/create_tsvb_link.ts +++ b/x-pack/plugins/infra/public/pages/metrics/metrics_explorer/components/helpers/create_tsvb_link.ts @@ -6,7 +6,7 @@ */ import { encode } from '@kbn/rison'; -import { v1 as uuidv1 } from 'uuid'; +import { v4 as uuidv4 } from 'uuid'; import { set } from '@kbn/safer-lodash-set'; import { LinkDescriptor } from '@kbn/observability-shared-plugin/public'; import { TIMESTAMP_FIELD } from '../../../../../../common/constants'; @@ -35,9 +35,9 @@ const TSVB_WORKAROUND_INDEX_PATTERN = 'metric*'; export const metricsExplorerMetricToTSVBMetric = (metric: MetricsExplorerOptionsMetric) => { if (metric.aggregation === 'rate') { - const metricId = uuidv1(); - const positiveOnlyId = uuidv1(); - const derivativeId = uuidv1(); + const metricId = uuidv4(); + const positiveOnlyId = uuidv4(); + const derivativeId = uuidv4(); return [ { id: metricId, @@ -60,12 +60,12 @@ export const metricsExplorerMetricToTSVBMetric = (metric: MetricsExplorerOptions const percentileValue = metric.aggregation === 'p95' ? '95' : '99'; return [ { - id: uuidv1(), + id: uuidv4(), type: 'percentile', field: metric.field, percentiles: [ { - id: uuidv1(), + id: uuidv4(), value: percentileValue, mode: 'line', percentile: '', @@ -77,7 +77,7 @@ export const metricsExplorerMetricToTSVBMetric = (metric: MetricsExplorerOptions } else { return [ { - id: uuidv1(), + id: uuidv4(), type: metric.aggregation, field: metric.field || void 0, }, @@ -96,7 +96,7 @@ const mapMetricToSeries = fill: chartOptions.type === MetricsExplorerChartType.area ? 0.5 : 0, formatter: format === InfraFormatterType.bits ? InfraFormatterType.bytes : format, value_template: 'rate' === metric.aggregation ? '{{value}}/s' : '{{value}}', - id: uuidv1(), + id: uuidv4(), line_width: 2, metrics: metricsExplorerMetricToTSVBMetric(metric), point_size: 0, @@ -163,7 +163,7 @@ export const createTSVBLink = ( axis_formatter: 'number', axis_position: 'left', axis_scale: 'normal', - id: uuidv1(), + id: uuidv4(), default_index_pattern: tsvbIndexPattern, index_pattern: tsvbIndexPattern, interval: 'auto', diff --git a/x-pack/plugins/infra/public/plugin.ts b/x-pack/plugins/infra/public/plugin.ts index 4066aaff37ffd..a25e553faa2cf 100644 --- a/x-pack/plugins/infra/public/plugin.ts +++ b/x-pack/plugins/infra/public/plugin.ts @@ -23,9 +23,6 @@ import type { InfraPublicConfig } from '../common/plugin_config_types'; import { createInventoryMetricRuleType } from './alerting/inventory'; import { createLogThresholdRuleType } from './alerting/log_threshold'; import { createMetricThresholdRuleType } from './alerting/metric_threshold'; -import { createLazyContainerMetricsTable } from './components/infrastructure_node_metrics_tables/container/create_lazy_container_metrics_table'; -import { createLazyHostMetricsTable } from './components/infrastructure_node_metrics_tables/host/create_lazy_host_metrics_table'; -import { createLazyPodMetricsTable } from './components/infrastructure_node_metrics_tables/pod/create_lazy_pod_metrics_table'; import { LOG_STREAM_EMBEDDABLE } from './components/log_stream/log_stream_embeddable'; import { LogStreamEmbeddableFactoryDefinition } from './components/log_stream/log_stream_embeddable_factory'; import { @@ -45,7 +42,6 @@ import type { InfraClientSetupDeps, InfraClientStartDeps, InfraClientStartExports, - InfraClientStartServices, } from './types'; import { getLogsHasDataFetcher, getLogsOverviewDataFetcher } from './utils/logs_overview_fetchers'; @@ -250,46 +246,52 @@ export class Plugin implements InfraClientPluginClass { }: { hostsEnabled: boolean; metricsExplorerEnabled: boolean; - }): AppDeepLink[] => [ - { - id: 'inventory', - title: i18n.translate('xpack.infra.homePage.inventoryTabTitle', { - defaultMessage: 'Inventory', - }), - path: '/inventory', - navLinkStatus: AppNavLinkStatus.visible, - }, - ...(hostsEnabled - ? [ - { - id: 'hosts', - title: i18n.translate('xpack.infra.homePage.metricsHostsTabTitle', { - defaultMessage: 'Hosts', - }), - path: '/hosts', - navLinkStatus: AppNavLinkStatus.visible, - }, - ] - : []), - ...(metricsExplorerEnabled - ? [ - { - id: 'metrics-explorer', - title: i18n.translate('xpack.infra.homePage.metricsExplorerTabTitle', { - defaultMessage: 'Metrics Explorer', - }), - path: '/explorer', - }, - ] - : []), - { - id: 'settings', - title: i18n.translate('xpack.infra.homePage.settingsTabTitle', { - defaultMessage: 'Settings', - }), - path: '/settings', - }, - ]; + }): AppDeepLink[] => { + const serverlessNavLinkStatus = this.isServerlessEnv + ? AppNavLinkStatus.visible + : AppNavLinkStatus.hidden; + + return [ + { + id: 'inventory', + title: i18n.translate('xpack.infra.homePage.inventoryTabTitle', { + defaultMessage: 'Inventory', + }), + path: '/inventory', + navLinkStatus: serverlessNavLinkStatus, + }, + ...(hostsEnabled + ? [ + { + id: 'hosts', + title: i18n.translate('xpack.infra.homePage.metricsHostsTabTitle', { + defaultMessage: 'Hosts', + }), + path: '/hosts', + navLinkStatus: serverlessNavLinkStatus, + }, + ] + : []), + ...(metricsExplorerEnabled + ? [ + { + id: 'metrics-explorer', + title: i18n.translate('xpack.infra.homePage.metricsExplorerTabTitle', { + defaultMessage: 'Metrics Explorer', + }), + path: '/explorer', + }, + ] + : []), + { + id: 'settings', + title: i18n.translate('xpack.infra.homePage.settingsTabTitle', { + defaultMessage: 'Settings', + }), + path: '/settings', + }, + ]; + }; core.application.register({ id: 'metrics', @@ -364,8 +366,6 @@ export class Plugin implements InfraClientPluginClass { } start(core: InfraClientCoreStart, plugins: InfraClientStartDeps) { - const getStartServices = (): InfraClientStartServices => [core, plugins, startContract]; - const inventoryViews = this.inventoryViews.start({ http: core.http, }); @@ -381,9 +381,6 @@ export class Plugin implements InfraClientPluginClass { metricsExplorerViews, telemetry, locators: this.locators!, - ContainerMetricsTable: createLazyContainerMetricsTable(getStartServices), - HostMetricsTable: createLazyHostMetricsTable(getStartServices), - PodMetricsTable: createLazyPodMetricsTable(getStartServices), }; return startContract; diff --git a/x-pack/plugins/infra/public/types.ts b/x-pack/plugins/infra/public/types.ts index a003208233910..946ee4a7b1943 100644 --- a/x-pack/plugins/infra/public/types.ts +++ b/x-pack/plugins/infra/public/types.ts @@ -47,10 +47,6 @@ import { LicensingPluginSetup, LicensingPluginStart } from '@kbn/licensing-plugi import { ObservabilityAIAssistantPluginStart } from '@kbn/observability-ai-assistant-plugin/public'; import type { CloudSetup } from '@kbn/cloud-plugin/public'; import type { UnwrapPromise } from '../common/utility_types'; -import type { - SourceProviderProps, - UseNodeMetricsTableOptions, -} from './components/infrastructure_node_metrics_tables/shared'; import { InventoryViewsServiceStart } from './services/inventory_views'; import { MetricsExplorerViewsServiceStart } from './services/metrics_explorer_views'; import { ITelemetryClient } from './services/telemetry'; @@ -66,15 +62,6 @@ export interface InfraClientStartExports { metricsExplorerViews?: MetricsExplorerViewsServiceStart; telemetry: ITelemetryClient; locators: InfraLocators; - ContainerMetricsTable: ( - props: UseNodeMetricsTableOptions & Partial - ) => JSX.Element; - HostMetricsTable: ( - props: UseNodeMetricsTableOptions & Partial - ) => JSX.Element; - PodMetricsTable: ( - props: UseNodeMetricsTableOptions & Partial - ) => JSX.Element; } export interface InfraClientSetupDeps { diff --git a/x-pack/plugins/infra/server/infra_server.ts b/x-pack/plugins/infra/server/infra_server.ts index e54713faba76a..6ab8781bdfc4e 100644 --- a/x-pack/plugins/infra/server/infra_server.ts +++ b/x-pack/plugins/infra/server/infra_server.ts @@ -24,7 +24,6 @@ import { } from './routes/log_analysis'; import { initMetadataRoute } from './routes/metadata'; import { initMetricsAPIRoute } from './routes/metrics_api'; -import { initMetricExplorerRoute } from './routes/metrics_explorer'; import { initMetricsSourceConfigurationRoutes } from './routes/metrics_sources'; import { initNodeDetailsRoute } from './routes/node_details'; import { initOverviewRoute } from './routes/overview'; @@ -49,7 +48,6 @@ export const initInfraServer = (libs: InfraBackendLibs) => { initValidateLogAnalysisDatasetsRoute(libs); initValidateLogAnalysisIndicesRoute(libs); initGetLogEntryExamplesRoute(libs); - initMetricExplorerRoute(libs); initMetricsExplorerViewRoutes(libs); initMetricsAPIRoute(libs); initMetadataRoute(libs); diff --git a/x-pack/plugins/infra/server/lib/adapters/framework/kibana_framework_adapter.ts b/x-pack/plugins/infra/server/lib/adapters/framework/kibana_framework_adapter.ts index 3b8b6ada30232..9780a7811b824 100644 --- a/x-pack/plugins/infra/server/lib/adapters/framework/kibana_framework_adapter.ts +++ b/x-pack/plugins/infra/server/lib/adapters/framework/kibana_framework_adapter.ts @@ -12,7 +12,7 @@ import { CoreSetup, IRouter, KibanaRequest, RequestHandler, RouteMethod } from ' import { UI_SETTINGS } from '@kbn/data-plugin/server'; import { TimeseriesVisData } from '@kbn/vis-type-timeseries-plugin/server'; import { DEFAULT_SPACE_ID } from '@kbn/spaces-plugin/common'; -import { TSVBMetricModel } from '../../../../common/inventory_models/types'; +import { TSVBMetricModel } from '@kbn/metrics-data-access-plugin/common'; import { InfraConfig } from '../../../plugin'; import type { InfraPluginRequestHandlerContext } from '../../../types'; import { diff --git a/x-pack/plugins/infra/server/lib/adapters/metrics/adapter_types.ts b/x-pack/plugins/infra/server/lib/adapters/metrics/adapter_types.ts index 9e8b243433f66..28d24bd40153d 100644 --- a/x-pack/plugins/infra/server/lib/adapters/metrics/adapter_types.ts +++ b/x-pack/plugins/infra/server/lib/adapters/metrics/adapter_types.ts @@ -6,12 +6,12 @@ */ import { KibanaRequest } from '@kbn/core/server'; +import { InventoryMetric } from '@kbn/metrics-data-access-plugin/common'; import type { InfraPluginRequestHandlerContext } from '../../../types'; import { NodeDetailsRequest, NodeDetailsMetricData, } from '../../../../common/http_api/node_details_api'; -import { InventoryMetric } from '../../../../common/inventory_models/types'; import { InfraSourceConfiguration } from '../../sources'; export interface InfraMetricsRequestOptions diff --git a/x-pack/plugins/infra/server/lib/adapters/metrics/kibana_metrics_adapter.ts b/x-pack/plugins/infra/server/lib/adapters/metrics/kibana_metrics_adapter.ts index 9708761daad61..e0f542b63e918 100644 --- a/x-pack/plugins/infra/server/lib/adapters/metrics/kibana_metrics_adapter.ts +++ b/x-pack/plugins/infra/server/lib/adapters/metrics/kibana_metrics_adapter.ts @@ -9,17 +9,17 @@ import { i18n } from '@kbn/i18n'; import { KibanaRequest } from '@kbn/core/server'; import { flatten, get } from 'lodash'; import { isVisSeriesData } from '@kbn/vis-type-timeseries-plugin/server'; +import { metrics, findInventoryFields } from '@kbn/metrics-data-access-plugin/common'; +import { + TSVBMetricModelCreator, + InventoryMetric, + InventoryMetricRT, +} from '@kbn/metrics-data-access-plugin/common'; import { TIMESTAMP_FIELD } from '../../../../common/constants'; import { NodeDetailsMetricData } from '../../../../common/http_api/node_details_api'; import { KibanaFramework } from '../framework/kibana_framework_adapter'; import { InfraMetricsAdapter, InfraMetricsRequestOptions } from './adapter_types'; import { checkValidNode } from './lib/check_valid_node'; -import { metrics, findInventoryFields } from '../../../../common/inventory_models'; -import { - TSVBMetricModelCreator, - InventoryMetric, - InventoryMetricRT, -} from '../../../../common/inventory_models/types'; import { calculateMetricInterval } from '../../../utils/calculate_metric_interval'; import { CallWithRequestParams, InfraDatabaseSearchResponse } from '../framework'; import type { InfraPluginRequestHandlerContext } from '../../../types'; diff --git a/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/evaluate_condition.ts b/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/evaluate_condition.ts index fb19bbcef9c57..2568c8828dec9 100644 --- a/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/evaluate_condition.ts +++ b/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/evaluate_condition.ts @@ -8,9 +8,9 @@ import { ElasticsearchClient } from '@kbn/core/server'; import { mapValues } from 'lodash'; import type { Logger } from '@kbn/logging'; +import { InventoryItemType } from '@kbn/metrics-data-access-plugin/common'; import { InventoryMetricConditions } from '../../../../common/alerting/metrics'; import { InfraTimerangeInput } from '../../../../common/http_api'; -import { InventoryItemType } from '../../../../common/inventory_models/types'; import { LogQueryFields } from '../../metrics/types'; import { InfraSource } from '../../sources'; import { calculateFromBasedOnMetric } from './lib/calculate_from_based_on_metric'; diff --git a/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/inventory_metric_threshold_executor.ts b/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/inventory_metric_threshold_executor.ts index 0754c79a99688..7e3315510feec 100644 --- a/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/inventory_metric_threshold_executor.ts +++ b/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/inventory_metric_threshold_executor.ts @@ -16,12 +16,12 @@ import { } from '@kbn/alerting-plugin/common'; import { Alert, RuleTypeState } from '@kbn/alerting-plugin/server'; import { getAlertUrl } from '@kbn/observability-plugin/common'; +import { SnapshotMetricType } from '@kbn/metrics-data-access-plugin/common'; import { getOriginalActionGroup } from '../../../utils/get_original_action_group'; import { AlertStates, InventoryMetricThresholdParams } from '../../../../common/alerting/metrics'; import { createFormatter } from '../../../../common/formatters'; import { getCustomMetricLabel } from '../../../../common/formatters/get_custom_metric_label'; import { METRIC_FORMATTERS } from '../../../../common/formatters/snapshot_metric_formats'; -import { SnapshotMetricType } from '../../../../common/inventory_models/types'; import { toMetricOpt } from '../../../../common/snapshot_metric_i18n'; import { InfraBackendLibs } from '../../infra_types'; import { LogQueryFields } from '../../metrics/types'; diff --git a/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/lib/calculate_from_based_on_metric.ts b/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/lib/calculate_from_based_on_metric.ts index 9b1399fccf705..0053be15ea7eb 100644 --- a/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/lib/calculate_from_based_on_metric.ts +++ b/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/lib/calculate_from_based_on_metric.ts @@ -6,13 +6,10 @@ */ import moment from 'moment'; +import { findInventoryModel } from '@kbn/metrics-data-access-plugin/common'; +import { InventoryItemType, SnapshotMetricType } from '@kbn/metrics-data-access-plugin/common'; import { InventoryMetricConditions } from '../../../../../common/alerting/metrics'; import { SnapshotCustomMetricInput } from '../../../../../common/http_api'; -import { findInventoryModel } from '../../../../../common/inventory_models'; -import { - InventoryItemType, - SnapshotMetricType, -} from '../../../../../common/inventory_models/types'; import { isRate } from './is_rate'; export const calculateFromBasedOnMetric = ( diff --git a/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/lib/convert_metric_value.ts b/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/lib/convert_metric_value.ts index c502d9ca7d7b2..01377ce2c5335 100644 --- a/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/lib/convert_metric_value.ts +++ b/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/lib/convert_metric_value.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { SnapshotMetricType } from '../../../../../common/inventory_models/types'; +import { SnapshotMetricType } from '@kbn/metrics-data-access-plugin/common'; // Some metrics in the UI are in a different unit that what we store in ES. export const convertMetricValue = (metric: SnapshotMetricType, value: number) => { diff --git a/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/lib/create_bucket_selector.ts b/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/lib/create_bucket_selector.ts index 1538b89f5e205..7392446000db6 100644 --- a/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/lib/create_bucket_selector.ts +++ b/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/lib/create_bucket_selector.ts @@ -5,9 +5,9 @@ * 2.0. */ +import { SnapshotMetricType } from '@kbn/metrics-data-access-plugin/common'; import { Comparator, InventoryMetricConditions } from '../../../../../common/alerting/metrics'; import { SnapshotCustomMetricInput } from '../../../../../common/http_api'; -import { SnapshotMetricType } from '../../../../../common/inventory_models/types'; import { createConditionScript } from './create_condition_script'; const EMPTY_SHOULD_WARN = { diff --git a/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/lib/create_condition_script.ts b/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/lib/create_condition_script.ts index 82c4afb49ed3e..37a39d215eddd 100644 --- a/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/lib/create_condition_script.ts +++ b/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/lib/create_condition_script.ts @@ -4,8 +4,8 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ +import { SnapshotMetricType } from '@kbn/metrics-data-access-plugin/common'; import { Comparator } from '../../../../../common/alerting/metrics'; -import { SnapshotMetricType } from '../../../../../common/inventory_models/types'; import { convertMetricValue } from './convert_metric_value'; export const createConditionScript = ( diff --git a/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/lib/create_metric_aggregations.ts b/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/lib/create_metric_aggregations.ts index 6d516fa54b5f1..1b619b63c0e6a 100644 --- a/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/lib/create_metric_aggregations.ts +++ b/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/lib/create_metric_aggregations.ts @@ -6,11 +6,8 @@ */ import { get } from 'lodash'; -import { - InventoryItemType, - SnapshotMetricType, -} from '../../../../../common/inventory_models/types'; -import { findInventoryModel } from '../../../../../common/inventory_models'; +import { InventoryItemType, SnapshotMetricType } from '@kbn/metrics-data-access-plugin/common'; +import { findInventoryModel } from '@kbn/metrics-data-access-plugin/common'; import { InfraTimerangeInput, SnapshotCustomMetricInput } from '../../../../../common/http_api'; import { isMetricRate, isCustomMetricRate, isInterfaceRateAgg } from './is_rate'; import { createRateAggs } from './create_rate_aggs'; diff --git a/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/lib/create_request.ts b/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/lib/create_request.ts index 47736ca1b1a28..54cb8a1cb785d 100644 --- a/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/lib/create_request.ts +++ b/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/lib/create_request.ts @@ -5,12 +5,9 @@ * 2.0. */ import type { ESSearchRequest } from '@kbn/es-types'; -import { findInventoryFields } from '../../../../../common/inventory_models'; +import { findInventoryFields } from '@kbn/metrics-data-access-plugin/common'; +import { InventoryItemType, SnapshotMetricType } from '@kbn/metrics-data-access-plugin/common'; import { InfraTimerangeInput, SnapshotCustomMetricInput } from '../../../../../common/http_api'; -import { - InventoryItemType, - SnapshotMetricType, -} from '../../../../../common/inventory_models/types'; import { parseFilterQuery } from '../../../../utils/serialized_query'; import { createMetricAggregations } from './create_metric_aggregations'; import { InventoryMetricConditions } from '../../../../../common/alerting/metrics'; diff --git a/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/lib/get_data.ts b/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/lib/get_data.ts index 555ea6375eed3..8bcdd53e3bb5a 100644 --- a/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/lib/get_data.ts +++ b/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/lib/get_data.ts @@ -9,12 +9,9 @@ import { AggregationsAggregate, SearchResponse } from '@elastic/elasticsearch/li import { ElasticsearchClient } from '@kbn/core/server'; import type { Logger } from '@kbn/logging'; import { EcsFieldsResponse } from '@kbn/rule-registry-plugin/common/search_strategy'; +import { InventoryItemType, SnapshotMetricType } from '@kbn/metrics-data-access-plugin/common'; import { InventoryMetricConditions } from '../../../../../common/alerting/metrics'; import { InfraTimerangeInput, SnapshotCustomMetricInput } from '../../../../../common/http_api'; -import { - InventoryItemType, - SnapshotMetricType, -} from '../../../../../common/inventory_models/types'; import { LogQueryFields } from '../../../metrics/types'; import { InfraSource } from '../../../sources'; import { createRequest } from './create_request'; diff --git a/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/lib/is_rate.ts b/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/lib/is_rate.ts index 113715336e9dc..476f7d5e9ff49 100644 --- a/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/lib/is_rate.ts +++ b/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/lib/is_rate.ts @@ -13,7 +13,7 @@ import { ESTermsWithAggregationRT, ESDerivativeAggRT, ESBasicMetricAggRT, -} from '../../../../../common/inventory_models/types'; +} from '@kbn/metrics-data-access-plugin/common'; import { SnapshotCustomMetricInput } from '../../../../../common/http_api'; export const isMetricRate = (metric: MetricsUIAggregation | undefined): boolean => { diff --git a/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/register_inventory_metric_threshold_rule_type.ts b/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/register_inventory_metric_threshold_rule_type.ts index a1381f9679d9b..8ea6baff28240 100644 --- a/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/register_inventory_metric_threshold_rule_type.ts +++ b/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/register_inventory_metric_threshold_rule_type.ts @@ -11,6 +11,11 @@ import { DEFAULT_APP_CATEGORIES } from '@kbn/core/server'; import { GetViewInAppRelativeUrlFnOpts, PluginSetupContract } from '@kbn/alerting-plugin/server'; import { observabilityPaths } from '@kbn/observability-plugin/common'; import { TimeUnitChar } from '@kbn/observability-plugin/common/utils/formatters/duration'; +import { + InventoryItemType, + SnapshotMetricType, + SnapshotMetricTypeKeys, +} from '@kbn/metrics-data-access-plugin/common'; import type { InfraConfig } from '../../../../common/plugin_config_types'; import { Comparator, @@ -20,11 +25,6 @@ import { SnapshotCustomAggregation, SNAPSHOT_CUSTOM_AGGREGATIONS, } from '../../../../common/http_api/snapshot_api'; -import { - InventoryItemType, - SnapshotMetricType, - SnapshotMetricTypeKeys, -} from '../../../../common/inventory_models/types'; import { InfraBackendLibs } from '../../infra_types'; import { alertDetailUrlActionVariableDescription, diff --git a/x-pack/plugins/infra/server/lib/metrics/lib/create_metrics_aggregations.ts b/x-pack/plugins/infra/server/lib/metrics/lib/create_metrics_aggregations.ts index 7ab96a870cd1e..7acc262e934dd 100644 --- a/x-pack/plugins/infra/server/lib/metrics/lib/create_metrics_aggregations.ts +++ b/x-pack/plugins/infra/server/lib/metrics/lib/create_metrics_aggregations.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { MetricsUIAggregation } from '../../../../common/inventory_models/types'; +import { MetricsUIAggregation } from '@kbn/metrics-data-access-plugin/common'; import { MetricsAPIRequest } from '../../../../common/http_api/metrics_api'; export const createMetricsAggregations = (options: MetricsAPIRequest): MetricsUIAggregation => { diff --git a/x-pack/plugins/infra/server/routes/infra/lib/helpers/query.ts b/x-pack/plugins/infra/server/routes/infra/lib/helpers/query.ts index 85f75faa4d2e3..5366c2cd8cf97 100644 --- a/x-pack/plugins/infra/server/routes/infra/lib/helpers/query.ts +++ b/x-pack/plugins/infra/server/routes/infra/lib/helpers/query.ts @@ -9,7 +9,7 @@ import { estypes } from '@elastic/elasticsearch'; import { ISearchClient } from '@kbn/data-plugin/common'; import { ESSearchRequest } from '@kbn/es-types'; import { catchError, map, Observable } from 'rxjs'; -import { findInventoryModel } from '../../../../../common/inventory_models'; +import { findInventoryModel } from '@kbn/metrics-data-access-plugin/common'; import { GetInfraMetricsRequestBodyPayload, InfraAssetMetricType, diff --git a/x-pack/plugins/infra/server/routes/inventory_metadata/lib/get_cloud_metadata.ts b/x-pack/plugins/infra/server/routes/inventory_metadata/lib/get_cloud_metadata.ts index 5c4ae1981c5cd..c820aa21a6009 100644 --- a/x-pack/plugins/infra/server/routes/inventory_metadata/lib/get_cloud_metadata.ts +++ b/x-pack/plugins/infra/server/routes/inventory_metadata/lib/get_cloud_metadata.ts @@ -5,6 +5,8 @@ * 2.0. */ +import { InventoryItemType } from '@kbn/metrics-data-access-plugin/common'; +import { findInventoryModel } from '@kbn/metrics-data-access-plugin/common'; import { TIMESTAMP_FIELD } from '../../../../common/constants'; import { InventoryCloudAccount } from '../../../../common/http_api/inventory_meta_api'; import { @@ -13,8 +15,6 @@ import { } from '../../../lib/adapters/framework'; import { InfraSourceConfiguration } from '../../../lib/sources'; import { KibanaFramework } from '../../../lib/adapters/framework/kibana_framework_adapter'; -import { InventoryItemType } from '../../../../common/inventory_models/types'; -import { findInventoryModel } from '../../../../common/inventory_models'; import type { InfraPluginRequestHandlerContext } from '../../../types'; export interface CloudMetaData { diff --git a/x-pack/plugins/infra/server/routes/metadata/lib/get_metric_metadata.ts b/x-pack/plugins/infra/server/routes/metadata/lib/get_metric_metadata.ts index 1962a24f7d4db..f12cce92e60b5 100644 --- a/x-pack/plugins/infra/server/routes/metadata/lib/get_metric_metadata.ts +++ b/x-pack/plugins/infra/server/routes/metadata/lib/get_metric_metadata.ts @@ -6,6 +6,8 @@ */ import { get } from 'lodash'; +import { findInventoryFields } from '@kbn/metrics-data-access-plugin/common'; +import { InventoryItemType } from '@kbn/metrics-data-access-plugin/common'; import type { InfraPluginRequestHandlerContext } from '../../../types'; import { InfraMetadataAggregationBucket, @@ -13,8 +15,6 @@ import { } from '../../../lib/adapters/framework'; import { KibanaFramework } from '../../../lib/adapters/framework/kibana_framework_adapter'; import { InfraSourceConfiguration } from '../../../lib/sources'; -import { findInventoryFields } from '../../../../common/inventory_models'; -import { InventoryItemType } from '../../../../common/inventory_models/types'; import { TIMESTAMP_FIELD } from '../../../../common/constants'; export interface InfraMetricsAdapterResponse { diff --git a/x-pack/plugins/infra/server/routes/metadata/lib/get_node_info.ts b/x-pack/plugins/infra/server/routes/metadata/lib/get_node_info.ts index 5470efcb1fb47..cc03c6e50e2af 100644 --- a/x-pack/plugins/infra/server/routes/metadata/lib/get_node_info.ts +++ b/x-pack/plugins/infra/server/routes/metadata/lib/get_node_info.ts @@ -7,14 +7,14 @@ import { set } from '@kbn/safer-lodash-set'; import { first, startsWith } from 'lodash'; +import { findInventoryFields } from '@kbn/metrics-data-access-plugin/common'; +import { InventoryItemType } from '@kbn/metrics-data-access-plugin/common'; import type { InfraPluginRequestHandlerContext } from '../../../types'; import { KibanaFramework } from '../../../lib/adapters/framework/kibana_framework_adapter'; import { InfraSourceConfiguration } from '../../../lib/sources'; import { InfraMetadataInfo } from '../../../../common/http_api/metadata_api'; import { getPodNodeName } from './get_pod_node_name'; import { CLOUD_METRICS_MODULES } from '../../../lib/constants'; -import { findInventoryFields } from '../../../../common/inventory_models'; -import { InventoryItemType } from '../../../../common/inventory_models/types'; import { TIMESTAMP_FIELD } from '../../../../common/constants'; export const getNodeInfo = async ( diff --git a/x-pack/plugins/infra/server/routes/metadata/lib/get_pod_node_name.ts b/x-pack/plugins/infra/server/routes/metadata/lib/get_pod_node_name.ts index 3afb6a8abcb58..32b5bf3d3ac07 100644 --- a/x-pack/plugins/infra/server/routes/metadata/lib/get_pod_node_name.ts +++ b/x-pack/plugins/infra/server/routes/metadata/lib/get_pod_node_name.ts @@ -6,9 +6,9 @@ */ import { first, get } from 'lodash'; +import { findInventoryFields } from '@kbn/metrics-data-access-plugin/common'; import { KibanaFramework } from '../../../lib/adapters/framework/kibana_framework_adapter'; import { InfraSourceConfiguration } from '../../../lib/sources'; -import { findInventoryFields } from '../../../../common/inventory_models'; import type { InfraPluginRequestHandlerContext } from '../../../types'; import { TIMESTAMP_FIELD } from '../../../../common/constants'; diff --git a/x-pack/plugins/infra/server/routes/metrics_explorer/lib/convert_metric_to_metrics_api_metric.ts b/x-pack/plugins/infra/server/routes/metrics_explorer/lib/convert_metric_to_metrics_api_metric.ts index 299bc75f03114..12ecca8d45ee8 100644 --- a/x-pack/plugins/infra/server/routes/metrics_explorer/lib/convert_metric_to_metrics_api_metric.ts +++ b/x-pack/plugins/infra/server/routes/metrics_explorer/lib/convert_metric_to_metrics_api_metric.ts @@ -6,7 +6,7 @@ */ import { isEmpty } from 'lodash'; -import { networkTraffic } from '../../../../common/inventory_models/shared/metrics/snapshot/network_traffic'; +import { networkTraffic } from '@kbn/metrics-data-access-plugin/common'; import { MetricsAPIMetric, MetricsExplorerMetric } from '../../../../common/http_api'; import { createCustomMetricsAggregations } from '../../../lib/create_custom_metrics_aggregations'; diff --git a/x-pack/plugins/infra/server/routes/snapshot/lib/apply_metadata_to_last_path.ts b/x-pack/plugins/infra/server/routes/snapshot/lib/apply_metadata_to_last_path.ts index 246b63a8d1d69..0a211694003d4 100644 --- a/x-pack/plugins/infra/server/routes/snapshot/lib/apply_metadata_to_last_path.ts +++ b/x-pack/plugins/infra/server/routes/snapshot/lib/apply_metadata_to_last_path.ts @@ -6,7 +6,7 @@ */ import { get, last, first, isArray } from 'lodash'; -import { findInventoryFields } from '../../../../common/inventory_models'; +import { findInventoryFields } from '@kbn/metrics-data-access-plugin/common'; import { SnapshotRequest, SnapshotNodePath, diff --git a/x-pack/plugins/infra/server/routes/snapshot/lib/create_timerange_with_interval.ts b/x-pack/plugins/infra/server/routes/snapshot/lib/create_timerange_with_interval.ts index d992bc3dec96b..4d3a45890bedf 100644 --- a/x-pack/plugins/infra/server/routes/snapshot/lib/create_timerange_with_interval.ts +++ b/x-pack/plugins/infra/server/routes/snapshot/lib/create_timerange_with_interval.ts @@ -6,14 +6,11 @@ */ import { uniq } from 'lodash'; +import { MetricsUIAggregation, ESBasicMetricAggRT } from '@kbn/metrics-data-access-plugin/common'; import { MetricsAPITimerange } from '../../../../common/http_api'; import { ESSearchClient } from '../../../lib/metrics/types'; import { calculateMetricInterval } from '../../../utils/calculate_metric_interval'; import { getMetricsAggregations, InfraSnapshotRequestOptions } from './get_metrics_aggregations'; -import { - MetricsUIAggregation, - ESBasicMetricAggRT, -} from '../../../../common/inventory_models/types'; import { getDatasetForField } from '../../metrics_explorer/lib/get_dataset_for_field'; const DEFAULT_LOOKBACK_SIZE = 5; diff --git a/x-pack/plugins/infra/server/routes/snapshot/lib/get_metrics_aggregations.ts b/x-pack/plugins/infra/server/routes/snapshot/lib/get_metrics_aggregations.ts index aa5141dc509bc..ee1d3717d4f69 100644 --- a/x-pack/plugins/infra/server/routes/snapshot/lib/get_metrics_aggregations.ts +++ b/x-pack/plugins/infra/server/routes/snapshot/lib/get_metrics_aggregations.ts @@ -11,14 +11,14 @@ import { InventoryItemType, MetricsUIAggregation, MetricsUIAggregationRT, -} from '../../../../common/inventory_models/types'; +} from '@kbn/metrics-data-access-plugin/common'; +import { findInventoryModel } from '@kbn/metrics-data-access-plugin/common'; +import { networkTraffic } from '@kbn/metrics-data-access-plugin/common'; import { SnapshotMetricInput, SnapshotCustomMetricInputRT, SnapshotRequest, } from '../../../../common/http_api'; -import { findInventoryModel } from '../../../../common/inventory_models'; -import { networkTraffic } from '../../../../common/inventory_models/shared/metrics/snapshot/network_traffic'; import { InfraSourceConfiguration } from '../../../lib/sources'; export interface InfraSnapshotRequestOptions diff --git a/x-pack/plugins/infra/server/routes/snapshot/lib/transform_metrics_ui_response.ts b/x-pack/plugins/infra/server/routes/snapshot/lib/transform_metrics_ui_response.ts index f11a67ecb4a0c..8c04e6fdfe833 100644 --- a/x-pack/plugins/infra/server/routes/snapshot/lib/transform_metrics_ui_response.ts +++ b/x-pack/plugins/infra/server/routes/snapshot/lib/transform_metrics_ui_response.ts @@ -6,7 +6,7 @@ */ import { get, max, sum, last, isNumber } from 'lodash'; -import { SnapshotMetricType } from '../../../../common/inventory_models/types'; +import { SnapshotMetricType } from '@kbn/metrics-data-access-plugin/common'; import { MetricsAPIResponse, SnapshotNodeResponse, diff --git a/x-pack/plugins/infra/server/routes/snapshot/lib/transform_request_to_metrics_api_request.ts b/x-pack/plugins/infra/server/routes/snapshot/lib/transform_request_to_metrics_api_request.ts index 890295561e3a7..1dd1827110af6 100644 --- a/x-pack/plugins/infra/server/routes/snapshot/lib/transform_request_to_metrics_api_request.ts +++ b/x-pack/plugins/infra/server/routes/snapshot/lib/transform_request_to_metrics_api_request.ts @@ -5,8 +5,8 @@ * 2.0. */ +import { findInventoryFields, findInventoryModel } from '@kbn/metrics-data-access-plugin/common'; import { TIMESTAMP_FIELD } from '../../../../common/constants'; -import { findInventoryFields, findInventoryModel } from '../../../../common/inventory_models'; import { MetricsAPIMetric, MetricsAPIRequest, SnapshotRequest } from '../../../../common/http_api'; import { ESSearchClient } from '../../../lib/metrics/types'; import { InfraSource } from '../../../lib/sources'; diff --git a/x-pack/plugins/infra/server/routes/snapshot/lib/transform_snapshot_metrics_to_metrics_api_metrics.ts b/x-pack/plugins/infra/server/routes/snapshot/lib/transform_snapshot_metrics_to_metrics_api_metrics.ts index e6de664d34b8e..69c0f72762aea 100644 --- a/x-pack/plugins/infra/server/routes/snapshot/lib/transform_snapshot_metrics_to_metrics_api_metrics.ts +++ b/x-pack/plugins/infra/server/routes/snapshot/lib/transform_snapshot_metrics_to_metrics_api_metrics.ts @@ -6,9 +6,11 @@ */ import { identity } from 'lodash'; -import { MetricsUIAggregationRT } from '../../../../common/inventory_models/types'; -import { networkTraffic } from '../../../../common/inventory_models/shared/metrics/snapshot/network_traffic'; -import { findInventoryModel } from '../../../../common/inventory_models'; +import { + MetricsUIAggregationRT, + networkTraffic, + findInventoryModel, +} from '@kbn/metrics-data-access-plugin/common'; import { MetricsAPIMetric, SnapshotRequest, diff --git a/x-pack/plugins/infra/server/saved_objects/inventory_view/types.ts b/x-pack/plugins/infra/server/saved_objects/inventory_view/types.ts index 30ab7068b7f40..a1131a574b7ec 100644 --- a/x-pack/plugins/infra/server/saved_objects/inventory_view/types.ts +++ b/x-pack/plugins/infra/server/saved_objects/inventory_view/types.ts @@ -7,7 +7,7 @@ import { inRangeRt, isoToEpochRt, nonEmptyStringRt } from '@kbn/io-ts-utils'; import * as rt from 'io-ts'; -import { ItemTypeRT } from '../../../common/inventory_models/types'; +import { ItemTypeRT } from '@kbn/metrics-data-access-plugin/common'; export const inventorySavedObjectColorPaletteRT = rt.keyof({ status: null, diff --git a/x-pack/plugins/infra/server/usage/usage_collector.ts b/x-pack/plugins/infra/server/usage/usage_collector.ts index 6e181c09512a8..aada031576717 100644 --- a/x-pack/plugins/infra/server/usage/usage_collector.ts +++ b/x-pack/plugins/infra/server/usage/usage_collector.ts @@ -6,7 +6,7 @@ */ import { UsageCollectionSetup } from '@kbn/usage-collection-plugin/server'; -import { InventoryItemType } from '../../common/inventory_models/types'; +import { InventoryItemType } from '@kbn/metrics-data-access-plugin/common'; interface InfraopsSum { infraopsHosts: number; diff --git a/x-pack/plugins/infra/server/utils/calculate_metric_interval.ts b/x-pack/plugins/infra/server/utils/calculate_metric_interval.ts index cb754153c6615..24819b859f959 100644 --- a/x-pack/plugins/infra/server/utils/calculate_metric_interval.ts +++ b/x-pack/plugins/infra/server/utils/calculate_metric_interval.ts @@ -5,10 +5,10 @@ * 2.0. */ -import { TIMESTAMP_FIELD } from '../../common/constants'; -import { findInventoryModel } from '../../common/inventory_models'; +import { findInventoryModel } from '@kbn/metrics-data-access-plugin/common'; // import { KibanaFramework } from '../lib/adapters/framework/kibana_framework_adapter'; -import { InventoryItemType } from '../../common/inventory_models/types'; +import { InventoryItemType } from '@kbn/metrics-data-access-plugin/common'; +import { TIMESTAMP_FIELD } from '../../common/constants'; import { ESSearchClient } from '../lib/metrics/types'; interface Options { diff --git a/x-pack/plugins/log_explorer/kibana.jsonc b/x-pack/plugins/log_explorer/kibana.jsonc index 969fa50c87a8c..76eb47e4a5915 100644 --- a/x-pack/plugins/log_explorer/kibana.jsonc +++ b/x-pack/plugins/log_explorer/kibana.jsonc @@ -15,6 +15,7 @@ "data", "dataViews", "discover", + "fieldFormats", "fleet", "kibanaReact", "kibanaUtils", diff --git a/x-pack/plugins/log_explorer/public/components/flyout_detail/flyout_detail.tsx b/x-pack/plugins/log_explorer/public/components/flyout_detail/flyout_detail.tsx new file mode 100644 index 0000000000000..012e5c914ed61 --- /dev/null +++ b/x-pack/plugins/log_explorer/public/components/flyout_detail/flyout_detail.tsx @@ -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 React from 'react'; +import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; +import { LogLevel } from './sub_components/log_level'; +import { Timestamp } from './sub_components/timestamp'; +import { FlyoutProps, LogDocument } from './types'; +import { getDocDetailRenderFlags, useDocDetail } from './use_doc_detail'; +import { Message } from './sub_components/message'; + +export function FlyoutDetail({ dataView, doc }: Pick) { + const parsedDoc = useDocDetail(doc as LogDocument, { dataView }); + + const { hasTimestamp, hasLogLevel, hasMessage, hasBadges, hasFlyoutHeader } = + getDocDetailRenderFlags(parsedDoc); + + return hasFlyoutHeader ? ( + + + {hasBadges && ( + + {hasLogLevel && ( + + + + )} + {hasTimestamp && ( + + + + )} + + )} + + {hasMessage && ( + + + + )} + + ) : null; +} diff --git a/x-pack/plugins/log_explorer/public/components/flyout_detail/index.ts b/x-pack/plugins/log_explorer/public/components/flyout_detail/index.ts new file mode 100644 index 0000000000000..4b00c914df228 --- /dev/null +++ b/x-pack/plugins/log_explorer/public/components/flyout_detail/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 './flyout_detail'; +export * from './types'; diff --git a/x-pack/plugins/log_explorer/public/components/flyout_detail/sub_components/log_level.tsx b/x-pack/plugins/log_explorer/public/components/flyout_detail/sub_components/log_level.tsx new file mode 100644 index 0000000000000..57858bb8c0819 --- /dev/null +++ b/x-pack/plugins/log_explorer/public/components/flyout_detail/sub_components/log_level.tsx @@ -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 React from 'react'; +import { EuiBadge, type EuiBadgeProps } from '@elastic/eui'; +import { FlyoutDoc } from '../types'; + +const LEVEL_DICT: Record = { + error: 'danger', + warn: 'warning', + info: 'primary', + default: 'default', +}; + +interface LogLevelProps { + level: FlyoutDoc['log.level']; +} + +export function LogLevel({ level }: LogLevelProps) { + if (!level) return null; + + const levelColor = LEVEL_DICT[level] ?? LEVEL_DICT.default; + + return ( + + {level} + + ); +} diff --git a/x-pack/plugins/log_explorer/public/components/flyout_detail/sub_components/message.tsx b/x-pack/plugins/log_explorer/public/components/flyout_detail/sub_components/message.tsx new file mode 100644 index 0000000000000..584f2eeff5a50 --- /dev/null +++ b/x-pack/plugins/log_explorer/public/components/flyout_detail/sub_components/message.tsx @@ -0,0 +1,34 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { EuiCodeBlock, EuiFlexGroup, EuiFlexItem, EuiText } from '@elastic/eui'; +import { FlyoutDoc } from '../types'; +import { flyoutMessageLabel } from '../translations'; + +interface MessageProps { + message: FlyoutDoc['message']; +} + +export function Message({ message }: MessageProps) { + if (!message) return null; + + return ( + + + + {flyoutMessageLabel} + + + + + {message} + + + + ); +} diff --git a/x-pack/plugins/log_explorer/public/components/flyout_detail/sub_components/timestamp.tsx b/x-pack/plugins/log_explorer/public/components/flyout_detail/sub_components/timestamp.tsx new file mode 100644 index 0000000000000..95df948c80560 --- /dev/null +++ b/x-pack/plugins/log_explorer/public/components/flyout_detail/sub_components/timestamp.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 { EuiBadge } from '@elastic/eui'; +import { FlyoutDoc } from '../types'; + +interface TimestampProps { + timestamp: FlyoutDoc['@timestamp']; +} + +export function Timestamp({ timestamp }: TimestampProps) { + if (!timestamp) return null; + + return ( + + {timestamp} + + ); +} diff --git a/x-pack/plugins/log_explorer/public/components/flyout_detail/translations.ts b/x-pack/plugins/log_explorer/public/components/flyout_detail/translations.ts new file mode 100644 index 0000000000000..fcb42cf79a5dd --- /dev/null +++ b/x-pack/plugins/log_explorer/public/components/flyout_detail/translations.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 { i18n } from '@kbn/i18n'; + +export const flyoutMessageLabel = i18n.translate('xpack.logExplorer.flyoutDetail.label.message', { + defaultMessage: 'Message', +}); diff --git a/x-pack/plugins/log_explorer/public/components/flyout_detail/types.ts b/x-pack/plugins/log_explorer/public/components/flyout_detail/types.ts new file mode 100644 index 0000000000000..cf8cfb8170e21 --- /dev/null +++ b/x-pack/plugins/log_explorer/public/components/flyout_detail/types.ts @@ -0,0 +1,35 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { EuiIconType } from '@elastic/eui/src/components/icon/icon'; +import type { DataView } from '@kbn/data-views-plugin/common'; +import type { FlyoutContentProps } from '@kbn/discover-plugin/public'; +import type { DataTableRecord } from '@kbn/discover-utils/types'; + +export interface FlyoutProps extends FlyoutContentProps { + dataView: DataView; +} + +export interface LogDocument extends DataTableRecord { + flattened: { + '@timestamp': string; + 'log.level'?: string; + message?: string; + }; +} + +export interface FlyoutDoc { + '@timestamp': string; + 'log.level'?: string; + message?: string; +} + +export interface FlyoutHighlightField { + label: string; + value: string; + iconType?: EuiIconType; +} diff --git a/x-pack/plugins/log_explorer/public/components/flyout_detail/use_doc_detail.ts b/x-pack/plugins/log_explorer/public/components/flyout_detail/use_doc_detail.ts new file mode 100644 index 0000000000000..32e4bcd966745 --- /dev/null +++ b/x-pack/plugins/log_explorer/public/components/flyout_detail/use_doc_detail.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 { formatFieldValue } from '@kbn/discover-utils'; +import { LOG_LEVEL_FIELD, MESSAGE_FIELD, TIMESTAMP_FIELD } from '../../../common/constants'; +import { useKibanaContextForPlugin } from '../../utils/use_kibana'; +import { FlyoutDoc, FlyoutProps, LogDocument } from './types'; + +export function useDocDetail( + doc: LogDocument, + { dataView }: Pick +): FlyoutDoc { + const { services } = useKibanaContextForPlugin(); + + const formatField = ( + field: F + ): LogDocument['flattened'][F] => { + return ( + doc.flattened[field] && + formatFieldValue( + doc.flattened[field], + doc.raw, + services.fieldFormats, + dataView, + dataView.fields.getByName(field) + ) + ); + }; + + const level = formatField(LOG_LEVEL_FIELD)?.toLowerCase(); + const timestamp = formatField(TIMESTAMP_FIELD); + const message = formatField(MESSAGE_FIELD); + + return { + [LOG_LEVEL_FIELD]: level, + [TIMESTAMP_FIELD]: timestamp, + [MESSAGE_FIELD]: message, + }; +} + +export const getDocDetailRenderFlags = (doc: FlyoutDoc) => { + const hasTimestamp = Boolean(doc['@timestamp']); + const hasLogLevel = Boolean(doc['log.level']); + const hasMessage = Boolean(doc.message); + + const hasBadges = hasTimestamp || hasLogLevel; + + const hasFlyoutHeader = hasBadges || hasMessage; + + return { + hasTimestamp, + hasLogLevel, + hasMessage, + hasBadges, + hasFlyoutHeader, + }; +}; diff --git a/x-pack/plugins/log_explorer/public/customizations/custom_flyout_content.tsx b/x-pack/plugins/log_explorer/public/customizations/custom_flyout_content.tsx new file mode 100644 index 0000000000000..a4b473119744a --- /dev/null +++ b/x-pack/plugins/log_explorer/public/customizations/custom_flyout_content.tsx @@ -0,0 +1,32 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; +import { FlyoutDetail } from '../components/flyout_detail/flyout_detail'; +import { FlyoutProps } from '../components/flyout_detail'; + +export const CustomFlyoutContent = ({ + actions, + dataView, + doc, + renderDefaultContent, +}: FlyoutProps) => { + return ( + + {/* Apply custom Log Explorer detail */} + + + + {/* Restore default content */} + {renderDefaultContent()} + + ); +}; + +// eslint-disable-next-line import/no-default-export +export default CustomFlyoutContent; diff --git a/x-pack/plugins/log_explorer/public/customizations/log_explorer_profile.tsx b/x-pack/plugins/log_explorer/public/customizations/log_explorer_profile.tsx index 29a3744a9484f..85d1284752977 100644 --- a/x-pack/plugins/log_explorer/public/customizations/log_explorer_profile.tsx +++ b/x-pack/plugins/log_explorer/public/customizations/log_explorer_profile.tsx @@ -8,14 +8,16 @@ import type { CoreStart } from '@kbn/core/public'; import { CustomizationCallback, DiscoverStateContainer } from '@kbn/discover-plugin/public'; import React from 'react'; import { type BehaviorSubject, combineLatest, from, map, Subscription } from 'rxjs'; +import useObservable from 'react-use/lib/useObservable'; import { dynamic } from '../utils/dynamic'; import { LogExplorerProfileStateService } from '../state_machines/log_explorer_profile'; import { LogExplorerStateContainer } from '../components/log_explorer'; import { LogExplorerStartDeps } from '../types'; import { useKibanaContextForPluginProvider } from '../utils/use_kibana'; -const LazyCustomDatasetSelector = dynamic(() => import('./custom_dataset_selector')); const LazyCustomDatasetFilters = dynamic(() => import('./custom_dataset_filters')); +const LazyCustomDatasetSelector = dynamic(() => import('./custom_dataset_selector')); +const LazyCustomFlyoutContent = dynamic(() => import('./custom_flyout_content')); export interface CreateLogExplorerProfileCustomizationsDeps { core: CoreStart; @@ -115,6 +117,20 @@ export const createLogExplorerProfileCustomizations = viewSurroundingDocument: { disabled: true }, }, }, + Content: (props) => { + const KibanaContextProviderForPlugin = useKibanaContextForPluginProvider(core, plugins); + + const internalState = useObservable( + stateContainer.internalState.state$, + stateContainer.internalState.get() + ); + + return ( + + + + ); + }, }); return () => { diff --git a/x-pack/plugins/log_explorer/public/types.ts b/x-pack/plugins/log_explorer/public/types.ts index b260f6ba68ad7..e07b8fdb14b3f 100644 --- a/x-pack/plugins/log_explorer/public/types.ts +++ b/x-pack/plugins/log_explorer/public/types.ts @@ -9,6 +9,7 @@ import type { DataPublicPluginStart } from '@kbn/data-plugin/public'; import { DataViewsPublicPluginStart } from '@kbn/data-views-plugin/public'; import type { DiscoverSetup, DiscoverStart } from '@kbn/discover-plugin/public'; import { SharePluginSetup } from '@kbn/share-plugin/public'; +import { FieldFormatsStart } from '@kbn/field-formats-plugin/public'; import { LogExplorerLocators } from '../common/locators'; import type { LogExplorerProps } from './components/log_explorer'; @@ -28,4 +29,5 @@ export interface LogExplorerStartDeps { data: DataPublicPluginStart; dataViews: DataViewsPublicPluginStart; discover: DiscoverStart; + fieldFormats: FieldFormatsStart; } diff --git a/x-pack/plugins/log_explorer/tsconfig.json b/x-pack/plugins/log_explorer/tsconfig.json index 13a82d1da9f4c..d80736004536f 100644 --- a/x-pack/plugins/log_explorer/tsconfig.json +++ b/x-pack/plugins/log_explorer/tsconfig.json @@ -24,7 +24,8 @@ "@kbn/unified-data-table", "@kbn/core-ui-settings-browser", "@kbn/discover-utils", - "@kbn/deeplinks-observability" + "@kbn/deeplinks-observability", + "@kbn/field-formats-plugin" ], "exclude": ["target/**/*"] } diff --git a/x-pack/plugins/logs_shared/common/index.ts b/x-pack/plugins/logs_shared/common/index.ts index 07f029868b22a..654e8e2e13335 100644 --- a/x-pack/plugins/logs_shared/common/index.ts +++ b/x-pack/plugins/logs_shared/common/index.ts @@ -56,3 +56,7 @@ export { logEntriesSummaryRequestRT, logEntriesSummaryResponseRT, } from './http_api'; + +// Locators +export { LOGS_LOCATOR_ID, NODE_LOGS_LOCATOR_ID } from './locators'; +export type { LogsLocatorParams, NodeLogsLocatorParams } from './locators'; diff --git a/x-pack/plugins/logs_shared/common/locators/index.ts b/x-pack/plugins/logs_shared/common/locators/index.ts new file mode 100644 index 0000000000000..d680977f29f89 --- /dev/null +++ b/x-pack/plugins/logs_shared/common/locators/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 './logs_locator'; +export * from './node_logs_locator'; diff --git a/x-pack/plugins/logs_shared/common/locators/logs_locator.ts b/x-pack/plugins/logs_shared/common/locators/logs_locator.ts new file mode 100644 index 0000000000000..bfd53276ab3e9 --- /dev/null +++ b/x-pack/plugins/logs_shared/common/locators/logs_locator.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 { SerializableRecord } from '@kbn/utility-types'; +import type { TimeRange } from './time_range'; +import type { LogViewReference } from '../log_views/types'; + +export const LOGS_LOCATOR_ID = 'LOGS_LOCATOR'; + +export interface LogsLocatorParams extends SerializableRecord { + /** Defines log position */ + time?: number; + /** + * Optionally set the time range in the time picker. + */ + timeRange?: TimeRange; + filter?: string; + logView?: LogViewReference; +} diff --git a/x-pack/plugins/logs_shared/common/locators/node_logs_locator.ts b/x-pack/plugins/logs_shared/common/locators/node_logs_locator.ts new file mode 100644 index 0000000000000..188c4d1e5a966 --- /dev/null +++ b/x-pack/plugins/logs_shared/common/locators/node_logs_locator.ts @@ -0,0 +1,16 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { InventoryItemType } from './types'; +import type { LogsLocatorParams } from './logs_locator'; + +export const NODE_LOGS_LOCATOR_ID = 'NODE_LOGS_LOCATOR'; + +export interface NodeLogsLocatorParams extends LogsLocatorParams { + nodeId: string; + nodeType: InventoryItemType; +} diff --git a/x-pack/plugins/logs_shared/common/locators/time_range.ts b/x-pack/plugins/logs_shared/common/locators/time_range.ts new file mode 100644 index 0000000000000..ac59e223b383a --- /dev/null +++ b/x-pack/plugins/logs_shared/common/locators/time_range.ts @@ -0,0 +1,15 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import * as rt from 'io-ts'; + +export const timeRangeRT = rt.type({ + startTime: rt.number, + endTime: rt.number, +}); + +export type TimeRange = rt.TypeOf; diff --git a/x-pack/plugins/logs_shared/common/locators/types.ts b/x-pack/plugins/logs_shared/common/locators/types.ts new file mode 100644 index 0000000000000..af6ec963098a0 --- /dev/null +++ b/x-pack/plugins/logs_shared/common/locators/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 * as rt from 'io-ts'; + +export const ItemTypeRT = rt.keyof({ + host: null, + pod: null, + container: null, + awsEC2: null, + awsS3: null, + awsSQS: null, + awsRDS: null, +}); + +export type InventoryItemType = rt.TypeOf; diff --git a/x-pack/plugins/logs_shared/kibana.jsonc b/x-pack/plugins/logs_shared/kibana.jsonc index 406b399d6ed17..051d1a452740e 100644 --- a/x-pack/plugins/logs_shared/kibana.jsonc +++ b/x-pack/plugins/logs_shared/kibana.jsonc @@ -8,13 +8,14 @@ "server": true, "browser": true, "configPath": ["xpack", "logs_shared"], - "requiredPlugins": ["data", "dataViews", "usageCollection", "observabilityShared", "observabilityAIAssistant"], - "requiredBundles": [ - "kibanaUtils", - "kibanaReact", + "requiredPlugins": [ + "data", + "dataViews", + "usageCollection", + "observabilityShared", + "observabilityAIAssistant" ], - "extraPublicDirs": [ - "common", - ] + "requiredBundles": ["kibanaUtils", "kibanaReact"], + "extraPublicDirs": ["common"] } } diff --git a/x-pack/plugins/logs_shared/tsconfig.json b/x-pack/plugins/logs_shared/tsconfig.json index 642b0426dc96b..b7c17b46c9a62 100644 --- a/x-pack/plugins/logs_shared/tsconfig.json +++ b/x-pack/plugins/logs_shared/tsconfig.json @@ -26,6 +26,6 @@ "@kbn/datemath", "@kbn/core-http-browser", "@kbn/ui-actions-plugin", - "@kbn/observability-ai-assistant-plugin", + "@kbn/observability-ai-assistant-plugin" ] } diff --git a/x-pack/plugins/metrics_data_access/common/alerting/metrics/index.ts b/x-pack/plugins/metrics_data_access/common/alerting/metrics/index.ts new file mode 100644 index 0000000000000..6cc0ccaa93a6d --- /dev/null +++ b/x-pack/plugins/metrics_data_access/common/alerting/metrics/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 './types'; diff --git a/x-pack/plugins/metrics_data_access/common/alerting/metrics/types.ts b/x-pack/plugins/metrics_data_access/common/alerting/metrics/types.ts new file mode 100644 index 0000000000000..861cecbfbfb03 --- /dev/null +++ b/x-pack/plugins/metrics_data_access/common/alerting/metrics/types.ts @@ -0,0 +1,31 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export enum Aggregators { + COUNT = 'count', + AVERAGE = 'avg', + SUM = 'sum', + MIN = 'min', + MAX = 'max', + RATE = 'rate', + CARDINALITY = 'cardinality', + P95 = 'p95', + P99 = 'p99', + CUSTOM = 'custom', +} + +export type CustomMetricAggTypes = Exclude< + Aggregators, + Aggregators.CUSTOM | Aggregators.RATE | Aggregators.P95 | Aggregators.P99 +>; + +export interface MetricExpressionCustomMetric { + name: string; + aggType: CustomMetricAggTypes; + field?: string; + filter?: string; +} diff --git a/x-pack/plugins/metrics_data_access/common/color_palette.ts b/x-pack/plugins/metrics_data_access/common/color_palette.ts new file mode 100644 index 0000000000000..d0b340765a788 --- /dev/null +++ b/x-pack/plugins/metrics_data_access/common/color_palette.ts @@ -0,0 +1,50 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { difference, first, values } from 'lodash'; +import { euiPaletteColorBlind } from '@elastic/eui'; + +export enum Color { + color0 = 'color0', + color1 = 'color1', + color2 = 'color2', + color3 = 'color3', + color4 = 'color4', + color5 = 'color5', + color6 = 'color6', + color7 = 'color7', + color8 = 'color8', + color9 = 'color9', +} + +export type Palette = { + [K in keyof typeof Color]: string; +}; + +const euiPalette = euiPaletteColorBlind(); + +export const defaultPalette: Palette = { + [Color.color0]: euiPalette[1], // (blue) + [Color.color1]: euiPalette[2], // (pink) + [Color.color2]: euiPalette[0], // (green-ish) + [Color.color3]: euiPalette[3], // (purple) + [Color.color4]: euiPalette[4], // (light pink) + [Color.color5]: euiPalette[5], // (yellow) + [Color.color6]: euiPalette[6], // (tan) + [Color.color7]: euiPalette[7], // (orange) + [Color.color8]: euiPalette[8], // (brown) + [Color.color9]: euiPalette[9], // (red) +}; + +export const createPaletteTransformer = (palette: Palette) => (color: Color) => palette[color]; + +export const colorTransformer = createPaletteTransformer(defaultPalette); + +export const sampleColor = (usedColors: Color[] = []): Color => { + const available = difference(values(Color) as Color[], usedColors); + return first(available) || Color.color0; +}; diff --git a/x-pack/plugins/metrics_data_access/common/constants.ts b/x-pack/plugins/metrics_data_access/common/constants.ts new file mode 100644 index 0000000000000..9dd43c6e72c99 --- /dev/null +++ b/x-pack/plugins/metrics_data_access/common/constants.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. + */ + +export const METRICS_INDEX_PATTERN = 'metrics-*,metricbeat-*'; +export const LOGS_INDEX_PATTERN = 'logs-*,filebeat-*,kibana_sample_data_logs*'; +export const METRICS_APP = 'metrics'; +export const LOGS_APP = 'logs'; + +export const METRICS_FEATURE_ID = 'infrastructure'; +export const LOGS_FEATURE_ID = 'logs'; + +export type InfraFeatureId = typeof METRICS_FEATURE_ID | typeof LOGS_FEATURE_ID; + +export const TIMESTAMP_FIELD = '@timestamp'; +export const MESSAGE_FIELD = 'message'; +export const TIEBREAKER_FIELD = '_doc'; +export const HOST_FIELD = 'host.name'; +export const CONTAINER_FIELD = 'container.id'; +export const POD_FIELD = 'kubernetes.pod.uid'; + +export const DISCOVER_APP_TARGET = 'discover'; +export const LOGS_APP_TARGET = 'logs-ui'; + +export const O11Y_AAD_FIELDS = [ + 'cloud.*', + 'host.*', + 'orchestrator.*', + 'container.*', + 'labels.*', + 'tags', +]; diff --git a/x-pack/plugins/metrics_data_access/common/http_api/index.ts b/x-pack/plugins/metrics_data_access/common/http_api/index.ts new file mode 100644 index 0000000000000..93e4514383f99 --- /dev/null +++ b/x-pack/plugins/metrics_data_access/common/http_api/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 './metrics_explorer'; +export * from './metrics_api'; diff --git a/x-pack/plugins/metrics_data_access/common/http_api/metric_indices.ts b/x-pack/plugins/metrics_data_access/common/http_api/metric_indices.ts new file mode 100644 index 0000000000000..b18f2487e4a96 --- /dev/null +++ b/x-pack/plugins/metrics_data_access/common/http_api/metric_indices.ts @@ -0,0 +1,15 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import * as rt from 'io-ts'; + +export const MetricIndicesAPIResponseRT = rt.type({ + metricIndices: rt.string, + metricIndicesExist: rt.boolean, +}); + +export type MetricIndicesAPIResponse = rt.TypeOf; diff --git a/x-pack/plugins/metrics_data_access/common/http_api/metrics_api.ts b/x-pack/plugins/metrics_data_access/common/http_api/metrics_api.ts new file mode 100644 index 0000000000000..d24c6ba2ce58f --- /dev/null +++ b/x-pack/plugins/metrics_data_access/common/http_api/metrics_api.ts @@ -0,0 +1,114 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { createLiteralValueFromUndefinedRT } from '@kbn/io-ts-utils'; +import * as rt from 'io-ts'; +import { MetricsUIAggregationRT } from '../inventory_models/types'; +import { afterKeyObjectRT } from './metrics_explorer'; + +export const MetricsAPITimerangeRT = rt.intersection([ + rt.type({ + from: rt.number, + to: rt.number, + interval: rt.string, + }), + rt.partial({ + timeFieldName: rt.string, + }), +]); + +const groupByRT = rt.union([rt.string, rt.null, rt.undefined]); + +export const MetricsAPIMetricRT = rt.type({ + id: rt.string, + aggregations: MetricsUIAggregationRT, +}); + +export const MetricsAPIRequestRT = rt.intersection([ + rt.type({ + timerange: MetricsAPITimerangeRT, + indexPattern: rt.string, + metrics: rt.array(MetricsAPIMetricRT), + includeTimeseries: rt.union([rt.boolean, createLiteralValueFromUndefinedRT(true)]), + }), + rt.partial({ + groupBy: rt.array(groupByRT), + modules: rt.array(rt.string), + afterKey: rt.union([rt.null, afterKeyObjectRT]), + limit: rt.union([rt.number, rt.null]), + filters: rt.array(rt.UnknownRecord), + dropPartialBuckets: rt.boolean, + alignDataToEnd: rt.boolean, + }), +]); + +export const MetricsAPIPageInfoRT = rt.intersection([ + rt.type({ + afterKey: rt.union([rt.null, afterKeyObjectRT, rt.undefined]), + }), + rt.partial({ interval: rt.number }), +]); + +export const MetricsAPIColumnTypeRT = rt.keyof({ + date: null, + number: null, + string: null, +}); + +export const MetricsAPIColumnRT = rt.type({ + name: rt.string, + type: MetricsAPIColumnTypeRT, +}); + +export const MetricsAPIRowRT = rt.intersection([ + rt.type({ + timestamp: rt.number, + }), + rt.record( + rt.string, + rt.union([rt.string, rt.number, rt.null, rt.undefined, rt.array(rt.object)]) + ), +]); + +export const MetricsAPISeriesRT = rt.intersection([ + rt.type({ + id: rt.string, + columns: rt.array(MetricsAPIColumnRT), + rows: rt.array(MetricsAPIRowRT), + }), + rt.partial({ + keys: rt.array(rt.string), + }), +]); + +export const MetricsAPIResponseSeriesRT = rt.intersection([ + MetricsAPISeriesRT, + rt.partial({ metricsets: rt.array(rt.string) }), +]); + +export const MetricsAPIResponseRT = rt.type({ + series: rt.array(MetricsAPIResponseSeriesRT), + info: MetricsAPIPageInfoRT, +}); + +export type MetricsAPITimerange = rt.TypeOf; + +export type MetricsAPIColumnType = rt.TypeOf; + +export type MetricsAPIMetric = rt.TypeOf; + +export type MetricsAPIPageInfo = rt.TypeOf; + +export type MetricsAPIColumn = rt.TypeOf; + +export type MetricsAPIRow = rt.TypeOf; + +export type MetricsAPISeries = rt.TypeOf; + +export type MetricsAPIRequest = rt.TypeOf; + +export type MetricsAPIResponse = rt.TypeOf; diff --git a/x-pack/plugins/metrics_data_access/common/http_api/metrics_explorer.ts b/x-pack/plugins/metrics_data_access/common/http_api/metrics_explorer.ts new file mode 100644 index 0000000000000..2e42dfd046a10 --- /dev/null +++ b/x-pack/plugins/metrics_data_access/common/http_api/metrics_explorer.ts @@ -0,0 +1,171 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license 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 rt from 'io-ts'; +import { xor } from 'lodash'; + +export const METRIC_EXPLORER_AGGREGATIONS = [ + 'avg', + 'max', + 'min', + 'cardinality', + 'rate', + 'count', + 'sum', + 'p95', + 'p99', + 'custom', +] as const; + +export const OMITTED_AGGREGATIONS_FOR_CUSTOM_METRICS = ['custom', 'rate', 'p95', 'p99']; + +type MetricExplorerAggregations = typeof METRIC_EXPLORER_AGGREGATIONS[number]; + +const metricsExplorerAggregationKeys = METRIC_EXPLORER_AGGREGATIONS.reduce< + Record +>((acc, agg) => ({ ...acc, [agg]: null }), {} as Record); + +export const metricsExplorerAggregationRT = rt.keyof(metricsExplorerAggregationKeys); + +export type MetricExplorerCustomMetricAggregations = Exclude< + MetricsExplorerAggregation, + 'custom' | 'rate' | 'p95' | 'p99' +>; +const metricsExplorerCustomMetricAggregationKeys = xor( + METRIC_EXPLORER_AGGREGATIONS, + OMITTED_AGGREGATIONS_FOR_CUSTOM_METRICS +).reduce>( + (acc, agg) => ({ ...acc, [agg]: null }), + {} as Record +); +export const metricsExplorerCustomMetricAggregationRT = rt.keyof( + metricsExplorerCustomMetricAggregationKeys +); + +export const metricsExplorerMetricRequiredFieldsRT = rt.type({ + aggregation: metricsExplorerAggregationRT, +}); + +export const metricsExplorerCustomMetricRT = rt.intersection([ + rt.type({ + name: rt.string, + aggregation: metricsExplorerCustomMetricAggregationRT, + }), + rt.partial({ + field: rt.string, + filter: rt.string, + }), +]); + +export type MetricsExplorerCustomMetric = rt.TypeOf; + +export const metricsExplorerMetricOptionalFieldsRT = rt.partial({ + field: rt.union([rt.string, rt.undefined]), + custom_metrics: rt.array(metricsExplorerCustomMetricRT), + equation: rt.string, +}); + +export const metricsExplorerMetricRT = rt.intersection([ + metricsExplorerMetricRequiredFieldsRT, + metricsExplorerMetricOptionalFieldsRT, +]); + +export const timeRangeRT = rt.intersection([ + rt.type({ + from: rt.number, + to: rt.number, + interval: rt.string, + }), + rt.partial({ + timeFieldName: rt.string, + }), +]); + +export const metricsExplorerRequestBodyRequiredFieldsRT = rt.type({ + timerange: timeRangeRT, + indexPattern: rt.string, + metrics: rt.array(metricsExplorerMetricRT), +}); + +const groupByRT = rt.union([rt.string, rt.null, rt.undefined]); +export const afterKeyObjectRT = rt.record(rt.string, rt.union([rt.string, rt.null])); + +export const metricsExplorerRequestBodyOptionalFieldsRT = rt.partial({ + groupBy: rt.union([groupByRT, rt.array(groupByRT)]), + afterKey: rt.union([rt.string, rt.null, rt.undefined, afterKeyObjectRT]), + limit: rt.union([rt.number, rt.null, rt.undefined]), + filterQuery: rt.union([rt.string, rt.null, rt.undefined]), + forceInterval: rt.boolean, + dropLastBucket: rt.boolean, +}); + +export const metricsExplorerRequestBodyRT = rt.intersection([ + metricsExplorerRequestBodyRequiredFieldsRT, + metricsExplorerRequestBodyOptionalFieldsRT, +]); + +export const metricsExplorerPageInfoRT = rt.type({ + total: rt.number, + afterKey: rt.union([rt.string, rt.null, afterKeyObjectRT]), +}); + +export const metricsExplorerColumnTypeRT = rt.keyof({ + date: null, + number: null, + string: null, +}); + +export const metricsExplorerColumnRT = rt.type({ + name: rt.string, + type: metricsExplorerColumnTypeRT, +}); + +export const metricsExplorerRowRT = rt.intersection([ + rt.type({ + timestamp: rt.number, + }), + rt.record( + rt.string, + rt.union([rt.string, rt.number, rt.null, rt.undefined, rt.array(rt.object)]) + ), +]); + +export const metricsExplorerSeriesRT = rt.intersection([ + rt.type({ + id: rt.string, + columns: rt.array(metricsExplorerColumnRT), + rows: rt.array(metricsExplorerRowRT), + }), + rt.partial({ + keys: rt.array(rt.string), + }), +]); + +export const metricsExplorerResponseRT = rt.type({ + series: rt.array(metricsExplorerSeriesRT), + pageInfo: metricsExplorerPageInfoRT, +}); + +export type AfterKey = rt.TypeOf; + +export type MetricsExplorerAggregation = rt.TypeOf; + +export type MetricsExplorerColumnType = rt.TypeOf; + +export type MetricsExplorerMetric = rt.TypeOf; + +export type MetricsExplorerPageInfo = rt.TypeOf; + +export type MetricsExplorerColumn = rt.TypeOf; + +export type MetricsExplorerRow = rt.TypeOf; + +export type MetricsExplorerSeries = rt.TypeOf; + +export type MetricsExplorerRequestBody = rt.TypeOf; + +export type MetricsExplorerResponse = rt.TypeOf; diff --git a/x-pack/plugins/metrics_data_access/common/index.ts b/x-pack/plugins/metrics_data_access/common/index.ts new file mode 100644 index 0000000000000..38970225a8644 --- /dev/null +++ b/x-pack/plugins/metrics_data_access/common/index.ts @@ -0,0 +1,49 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export { + inventoryModels, + findInventoryModel, + getFieldByType, + findInventoryFields, + metrics, +} from './inventory_models'; + +export { podSnapshotMetricTypes } from './inventory_models/pod'; +export { containerSnapshotMetricTypes } from './inventory_models/container'; +export { awsS3SnapshotMetricTypes } from './inventory_models/aws_s3'; +export { hostSnapshotMetricTypes } from './inventory_models/host'; +export { awsEC2SnapshotMetricTypes } from './inventory_models/aws_ec2'; +export { awsRDSSnapshotMetricTypes } from './inventory_models/aws_rds'; +export { awsSQSSnapshotMetricTypes } from './inventory_models/aws_sqs'; + +export { + InventoryMetricRT, + InventoryFormatterTypeRT, + InventoryVisTypeRT, + ItemTypeRT, + SnapshotMetricTypeRT, + ESSumBucketAggRT, + ESTermsWithAggregationRT, + ESDerivativeAggRT, + MetricsUIAggregationRT, + ESBasicMetricAggRT, + SnapshotMetricTypeKeys, +} from './inventory_models/types'; + +export type { + InventoryItemType, + InventoryMetric, + InventoryFormatterType, + InventoryVisType, + MetricsUIAggregation, + SnapshotMetricType, + TSVBMetricModelCreator, + TSVBMetricModel, +} from './inventory_models/types'; + +export { networkTraffic } from './inventory_models/shared/metrics/snapshot/network_traffic'; diff --git a/x-pack/plugins/infra/common/inventory_models/aws_ec2/index.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/aws_ec2/index.ts similarity index 79% rename from x-pack/plugins/infra/common/inventory_models/aws_ec2/index.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/aws_ec2/index.ts index c15f1366d5273..251d14132bdf7 100644 --- a/x-pack/plugins/infra/common/inventory_models/aws_ec2/index.ts +++ b/x-pack/plugins/metrics_data_access/common/inventory_models/aws_ec2/index.ts @@ -13,12 +13,15 @@ export { awsEC2SnapshotMetricTypes } from './metrics'; export const awsEC2: InventoryModel = { id: 'awsEC2', - displayName: i18n.translate('xpack.infra.inventoryModels.awsEC2.displayName', { + displayName: i18n.translate('xpack.metricsData.inventoryModels.awsEC2.displayName', { defaultMessage: 'EC2 Instances', }), - singularDisplayName: i18n.translate('xpack.infra.inventoryModels.awsEC2.singularDisplayName', { - defaultMessage: 'EC2 Instance', - }), + singularDisplayName: i18n.translate( + 'xpack.metricsData.inventoryModels.awsEC2.singularDisplayName', + { + defaultMessage: 'EC2 Instance', + } + ), requiredModule: 'aws', crosslinkSupport: { details: true, diff --git a/x-pack/plugins/infra/common/inventory_models/aws_ec2/metrics/index.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/aws_ec2/metrics/index.ts similarity index 100% rename from x-pack/plugins/infra/common/inventory_models/aws_ec2/metrics/index.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/aws_ec2/metrics/index.ts diff --git a/x-pack/plugins/infra/common/inventory_models/aws_ec2/metrics/snapshot/cpu.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/aws_ec2/metrics/snapshot/cpu.ts similarity index 100% rename from x-pack/plugins/infra/common/inventory_models/aws_ec2/metrics/snapshot/cpu.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/aws_ec2/metrics/snapshot/cpu.ts diff --git a/x-pack/plugins/infra/common/inventory_models/aws_ec2/metrics/snapshot/disk_io_read_bytes.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/aws_ec2/metrics/snapshot/disk_io_read_bytes.ts similarity index 100% rename from x-pack/plugins/infra/common/inventory_models/aws_ec2/metrics/snapshot/disk_io_read_bytes.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/aws_ec2/metrics/snapshot/disk_io_read_bytes.ts diff --git a/x-pack/plugins/infra/common/inventory_models/aws_ec2/metrics/snapshot/disk_io_write_bytes.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/aws_ec2/metrics/snapshot/disk_io_write_bytes.ts similarity index 100% rename from x-pack/plugins/infra/common/inventory_models/aws_ec2/metrics/snapshot/disk_io_write_bytes.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/aws_ec2/metrics/snapshot/disk_io_write_bytes.ts diff --git a/x-pack/plugins/infra/common/inventory_models/aws_ec2/metrics/snapshot/rx.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/aws_ec2/metrics/snapshot/rx.ts similarity index 100% rename from x-pack/plugins/infra/common/inventory_models/aws_ec2/metrics/snapshot/rx.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/aws_ec2/metrics/snapshot/rx.ts diff --git a/x-pack/plugins/infra/common/inventory_models/aws_ec2/metrics/snapshot/tx.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/aws_ec2/metrics/snapshot/tx.ts similarity index 100% rename from x-pack/plugins/infra/common/inventory_models/aws_ec2/metrics/snapshot/tx.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/aws_ec2/metrics/snapshot/tx.ts diff --git a/x-pack/plugins/infra/common/inventory_models/aws_ec2/metrics/tsvb/aws_ec2_cpu_utilization.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/aws_ec2/metrics/tsvb/aws_ec2_cpu_utilization.ts similarity index 100% rename from x-pack/plugins/infra/common/inventory_models/aws_ec2/metrics/tsvb/aws_ec2_cpu_utilization.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/aws_ec2/metrics/tsvb/aws_ec2_cpu_utilization.ts diff --git a/x-pack/plugins/infra/common/inventory_models/aws_ec2/metrics/tsvb/aws_ec2_diskio_bytes.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/aws_ec2/metrics/tsvb/aws_ec2_diskio_bytes.ts similarity index 100% rename from x-pack/plugins/infra/common/inventory_models/aws_ec2/metrics/tsvb/aws_ec2_diskio_bytes.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/aws_ec2/metrics/tsvb/aws_ec2_diskio_bytes.ts diff --git a/x-pack/plugins/infra/common/inventory_models/aws_ec2/metrics/tsvb/aws_ec2_network_traffic.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/aws_ec2/metrics/tsvb/aws_ec2_network_traffic.ts similarity index 100% rename from x-pack/plugins/infra/common/inventory_models/aws_ec2/metrics/tsvb/aws_ec2_network_traffic.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/aws_ec2/metrics/tsvb/aws_ec2_network_traffic.ts diff --git a/x-pack/plugins/infra/common/inventory_models/aws_rds/index.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/aws_rds/index.ts similarity index 80% rename from x-pack/plugins/infra/common/inventory_models/aws_rds/index.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/aws_rds/index.ts index d1af6e0506142..28c5099ca3bdc 100644 --- a/x-pack/plugins/infra/common/inventory_models/aws_rds/index.ts +++ b/x-pack/plugins/metrics_data_access/common/inventory_models/aws_rds/index.ts @@ -13,12 +13,15 @@ export { awsRDSSnapshotMetricTypes } from './metrics'; export const awsRDS: InventoryModel = { id: 'awsRDS', - displayName: i18n.translate('xpack.infra.inventoryModels.awsRDS.displayName', { + displayName: i18n.translate('xpack.metricsData.inventoryModels.awsRDS.displayName', { defaultMessage: 'RDS Databases', }), - singularDisplayName: i18n.translate('xpack.infra.inventoryModels.awsRDS.singularDisplayName', { - defaultMessage: 'RDS Database', - }), + singularDisplayName: i18n.translate( + 'xpack.metricsData.inventoryModels.awsRDS.singularDisplayName', + { + defaultMessage: 'RDS Database', + } + ), requiredModule: 'aws', crosslinkSupport: { details: true, diff --git a/x-pack/plugins/infra/common/inventory_models/aws_rds/metrics/index.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/aws_rds/metrics/index.ts similarity index 100% rename from x-pack/plugins/infra/common/inventory_models/aws_rds/metrics/index.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/aws_rds/metrics/index.ts diff --git a/x-pack/plugins/infra/common/inventory_models/aws_rds/metrics/snapshot/cpu.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/aws_rds/metrics/snapshot/cpu.ts similarity index 100% rename from x-pack/plugins/infra/common/inventory_models/aws_rds/metrics/snapshot/cpu.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/aws_rds/metrics/snapshot/cpu.ts diff --git a/x-pack/plugins/infra/common/inventory_models/aws_rds/metrics/snapshot/rds_active_transactions.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/aws_rds/metrics/snapshot/rds_active_transactions.ts similarity index 100% rename from x-pack/plugins/infra/common/inventory_models/aws_rds/metrics/snapshot/rds_active_transactions.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/aws_rds/metrics/snapshot/rds_active_transactions.ts diff --git a/x-pack/plugins/infra/common/inventory_models/aws_rds/metrics/snapshot/rds_connections.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/aws_rds/metrics/snapshot/rds_connections.ts similarity index 100% rename from x-pack/plugins/infra/common/inventory_models/aws_rds/metrics/snapshot/rds_connections.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/aws_rds/metrics/snapshot/rds_connections.ts diff --git a/x-pack/plugins/infra/common/inventory_models/aws_rds/metrics/snapshot/rds_latency.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/aws_rds/metrics/snapshot/rds_latency.ts similarity index 100% rename from x-pack/plugins/infra/common/inventory_models/aws_rds/metrics/snapshot/rds_latency.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/aws_rds/metrics/snapshot/rds_latency.ts diff --git a/x-pack/plugins/infra/common/inventory_models/aws_rds/metrics/snapshot/rds_queries_executed.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/aws_rds/metrics/snapshot/rds_queries_executed.ts similarity index 100% rename from x-pack/plugins/infra/common/inventory_models/aws_rds/metrics/snapshot/rds_queries_executed.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/aws_rds/metrics/snapshot/rds_queries_executed.ts diff --git a/x-pack/plugins/infra/common/inventory_models/aws_rds/metrics/tsvb/aws_rds_active_transactions.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/aws_rds/metrics/tsvb/aws_rds_active_transactions.ts similarity index 100% rename from x-pack/plugins/infra/common/inventory_models/aws_rds/metrics/tsvb/aws_rds_active_transactions.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/aws_rds/metrics/tsvb/aws_rds_active_transactions.ts diff --git a/x-pack/plugins/infra/common/inventory_models/aws_rds/metrics/tsvb/aws_rds_connections.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/aws_rds/metrics/tsvb/aws_rds_connections.ts similarity index 100% rename from x-pack/plugins/infra/common/inventory_models/aws_rds/metrics/tsvb/aws_rds_connections.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/aws_rds/metrics/tsvb/aws_rds_connections.ts diff --git a/x-pack/plugins/infra/common/inventory_models/aws_rds/metrics/tsvb/aws_rds_cpu_total.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/aws_rds/metrics/tsvb/aws_rds_cpu_total.ts similarity index 100% rename from x-pack/plugins/infra/common/inventory_models/aws_rds/metrics/tsvb/aws_rds_cpu_total.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/aws_rds/metrics/tsvb/aws_rds_cpu_total.ts diff --git a/x-pack/plugins/infra/common/inventory_models/aws_rds/metrics/tsvb/aws_rds_latency.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/aws_rds/metrics/tsvb/aws_rds_latency.ts similarity index 100% rename from x-pack/plugins/infra/common/inventory_models/aws_rds/metrics/tsvb/aws_rds_latency.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/aws_rds/metrics/tsvb/aws_rds_latency.ts diff --git a/x-pack/plugins/infra/common/inventory_models/aws_rds/metrics/tsvb/aws_rds_queries_executed.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/aws_rds/metrics/tsvb/aws_rds_queries_executed.ts similarity index 100% rename from x-pack/plugins/infra/common/inventory_models/aws_rds/metrics/tsvb/aws_rds_queries_executed.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/aws_rds/metrics/tsvb/aws_rds_queries_executed.ts diff --git a/x-pack/plugins/infra/common/inventory_models/aws_s3/index.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/aws_s3/index.ts similarity index 80% rename from x-pack/plugins/infra/common/inventory_models/aws_s3/index.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/aws_s3/index.ts index 7196fe72465c7..d24aa4b59d1eb 100644 --- a/x-pack/plugins/infra/common/inventory_models/aws_s3/index.ts +++ b/x-pack/plugins/metrics_data_access/common/inventory_models/aws_s3/index.ts @@ -13,12 +13,15 @@ export { awsS3SnapshotMetricTypes } from './metrics'; export const awsS3: InventoryModel = { id: 'awsS3', - displayName: i18n.translate('xpack.infra.inventoryModels.awsS3.displayName', { + displayName: i18n.translate('xpack.metricsData.inventoryModels.awsS3.displayName', { defaultMessage: 'S3 Buckets', }), - singularDisplayName: i18n.translate('xpack.infra.inventoryModels.awsS3.singularDisplayName', { - defaultMessage: 'S3 Bucket', - }), + singularDisplayName: i18n.translate( + 'xpack.metricsData.inventoryModels.awsS3.singularDisplayName', + { + defaultMessage: 'S3 Bucket', + } + ), requiredModule: 'aws', crosslinkSupport: { details: true, diff --git a/x-pack/plugins/infra/common/inventory_models/aws_s3/metrics/index.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/aws_s3/metrics/index.ts similarity index 100% rename from x-pack/plugins/infra/common/inventory_models/aws_s3/metrics/index.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/aws_s3/metrics/index.ts diff --git a/x-pack/plugins/infra/common/inventory_models/aws_s3/metrics/snapshot/s3_bucket_size.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/aws_s3/metrics/snapshot/s3_bucket_size.ts similarity index 100% rename from x-pack/plugins/infra/common/inventory_models/aws_s3/metrics/snapshot/s3_bucket_size.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/aws_s3/metrics/snapshot/s3_bucket_size.ts diff --git a/x-pack/plugins/infra/common/inventory_models/aws_s3/metrics/snapshot/s3_download_bytes.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/aws_s3/metrics/snapshot/s3_download_bytes.ts similarity index 100% rename from x-pack/plugins/infra/common/inventory_models/aws_s3/metrics/snapshot/s3_download_bytes.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/aws_s3/metrics/snapshot/s3_download_bytes.ts diff --git a/x-pack/plugins/infra/common/inventory_models/aws_s3/metrics/snapshot/s3_number_of_objects.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/aws_s3/metrics/snapshot/s3_number_of_objects.ts similarity index 100% rename from x-pack/plugins/infra/common/inventory_models/aws_s3/metrics/snapshot/s3_number_of_objects.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/aws_s3/metrics/snapshot/s3_number_of_objects.ts diff --git a/x-pack/plugins/infra/common/inventory_models/aws_s3/metrics/snapshot/s3_total_requests.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/aws_s3/metrics/snapshot/s3_total_requests.ts similarity index 100% rename from x-pack/plugins/infra/common/inventory_models/aws_s3/metrics/snapshot/s3_total_requests.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/aws_s3/metrics/snapshot/s3_total_requests.ts diff --git a/x-pack/plugins/infra/common/inventory_models/aws_s3/metrics/snapshot/s3_upload_bytes.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/aws_s3/metrics/snapshot/s3_upload_bytes.ts similarity index 100% rename from x-pack/plugins/infra/common/inventory_models/aws_s3/metrics/snapshot/s3_upload_bytes.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/aws_s3/metrics/snapshot/s3_upload_bytes.ts diff --git a/x-pack/plugins/infra/common/inventory_models/aws_s3/metrics/tsvb/aws_s3_bucket_size.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/aws_s3/metrics/tsvb/aws_s3_bucket_size.ts similarity index 100% rename from x-pack/plugins/infra/common/inventory_models/aws_s3/metrics/tsvb/aws_s3_bucket_size.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/aws_s3/metrics/tsvb/aws_s3_bucket_size.ts diff --git a/x-pack/plugins/infra/common/inventory_models/aws_s3/metrics/tsvb/aws_s3_download_bytes.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/aws_s3/metrics/tsvb/aws_s3_download_bytes.ts similarity index 100% rename from x-pack/plugins/infra/common/inventory_models/aws_s3/metrics/tsvb/aws_s3_download_bytes.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/aws_s3/metrics/tsvb/aws_s3_download_bytes.ts diff --git a/x-pack/plugins/infra/common/inventory_models/aws_s3/metrics/tsvb/aws_s3_number_of_objects.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/aws_s3/metrics/tsvb/aws_s3_number_of_objects.ts similarity index 100% rename from x-pack/plugins/infra/common/inventory_models/aws_s3/metrics/tsvb/aws_s3_number_of_objects.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/aws_s3/metrics/tsvb/aws_s3_number_of_objects.ts diff --git a/x-pack/plugins/infra/common/inventory_models/aws_s3/metrics/tsvb/aws_s3_total_requests.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/aws_s3/metrics/tsvb/aws_s3_total_requests.ts similarity index 100% rename from x-pack/plugins/infra/common/inventory_models/aws_s3/metrics/tsvb/aws_s3_total_requests.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/aws_s3/metrics/tsvb/aws_s3_total_requests.ts diff --git a/x-pack/plugins/infra/common/inventory_models/aws_s3/metrics/tsvb/aws_s3_upload_bytes.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/aws_s3/metrics/tsvb/aws_s3_upload_bytes.ts similarity index 100% rename from x-pack/plugins/infra/common/inventory_models/aws_s3/metrics/tsvb/aws_s3_upload_bytes.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/aws_s3/metrics/tsvb/aws_s3_upload_bytes.ts diff --git a/x-pack/plugins/infra/common/inventory_models/aws_sqs/index.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/aws_sqs/index.ts similarity index 80% rename from x-pack/plugins/infra/common/inventory_models/aws_sqs/index.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/aws_sqs/index.ts index 8d7a133d99788..739b7e41403dc 100644 --- a/x-pack/plugins/infra/common/inventory_models/aws_sqs/index.ts +++ b/x-pack/plugins/metrics_data_access/common/inventory_models/aws_sqs/index.ts @@ -13,12 +13,15 @@ export { awsSQSSnapshotMetricTypes } from './metrics'; export const awsSQS: InventoryModel = { id: 'awsSQS', - displayName: i18n.translate('xpack.infra.inventoryModels.awsSQS.displayName', { + displayName: i18n.translate('xpack.metricsData.inventoryModels.awsSQS.displayName', { defaultMessage: 'SQS Queues', }), - singularDisplayName: i18n.translate('xpack.infra.inventoryModels.awsSQS.singularDisplayName', { - defaultMessage: 'SQS Queue', - }), + singularDisplayName: i18n.translate( + 'xpack.metricsData.inventoryModels.awsSQS.singularDisplayName', + { + defaultMessage: 'SQS Queue', + } + ), requiredModule: 'aws', crosslinkSupport: { details: true, diff --git a/x-pack/plugins/infra/common/inventory_models/aws_sqs/metrics/index.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/aws_sqs/metrics/index.ts similarity index 100% rename from x-pack/plugins/infra/common/inventory_models/aws_sqs/metrics/index.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/aws_sqs/metrics/index.ts diff --git a/x-pack/plugins/infra/common/inventory_models/aws_sqs/metrics/snapshot/sqs_messages_delayed.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/aws_sqs/metrics/snapshot/sqs_messages_delayed.ts similarity index 100% rename from x-pack/plugins/infra/common/inventory_models/aws_sqs/metrics/snapshot/sqs_messages_delayed.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/aws_sqs/metrics/snapshot/sqs_messages_delayed.ts diff --git a/x-pack/plugins/infra/common/inventory_models/aws_sqs/metrics/snapshot/sqs_messages_empty.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/aws_sqs/metrics/snapshot/sqs_messages_empty.ts similarity index 100% rename from x-pack/plugins/infra/common/inventory_models/aws_sqs/metrics/snapshot/sqs_messages_empty.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/aws_sqs/metrics/snapshot/sqs_messages_empty.ts diff --git a/x-pack/plugins/infra/common/inventory_models/aws_sqs/metrics/snapshot/sqs_messages_sent.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/aws_sqs/metrics/snapshot/sqs_messages_sent.ts similarity index 100% rename from x-pack/plugins/infra/common/inventory_models/aws_sqs/metrics/snapshot/sqs_messages_sent.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/aws_sqs/metrics/snapshot/sqs_messages_sent.ts diff --git a/x-pack/plugins/infra/common/inventory_models/aws_sqs/metrics/snapshot/sqs_messages_visible.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/aws_sqs/metrics/snapshot/sqs_messages_visible.ts similarity index 100% rename from x-pack/plugins/infra/common/inventory_models/aws_sqs/metrics/snapshot/sqs_messages_visible.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/aws_sqs/metrics/snapshot/sqs_messages_visible.ts diff --git a/x-pack/plugins/infra/common/inventory_models/aws_sqs/metrics/snapshot/sqs_oldest_message.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/aws_sqs/metrics/snapshot/sqs_oldest_message.ts similarity index 100% rename from x-pack/plugins/infra/common/inventory_models/aws_sqs/metrics/snapshot/sqs_oldest_message.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/aws_sqs/metrics/snapshot/sqs_oldest_message.ts diff --git a/x-pack/plugins/infra/common/inventory_models/aws_sqs/metrics/tsvb/aws_sqs_messages_delayed.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/aws_sqs/metrics/tsvb/aws_sqs_messages_delayed.ts similarity index 100% rename from x-pack/plugins/infra/common/inventory_models/aws_sqs/metrics/tsvb/aws_sqs_messages_delayed.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/aws_sqs/metrics/tsvb/aws_sqs_messages_delayed.ts diff --git a/x-pack/plugins/infra/common/inventory_models/aws_sqs/metrics/tsvb/aws_sqs_messages_empty.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/aws_sqs/metrics/tsvb/aws_sqs_messages_empty.ts similarity index 100% rename from x-pack/plugins/infra/common/inventory_models/aws_sqs/metrics/tsvb/aws_sqs_messages_empty.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/aws_sqs/metrics/tsvb/aws_sqs_messages_empty.ts diff --git a/x-pack/plugins/infra/common/inventory_models/aws_sqs/metrics/tsvb/aws_sqs_messages_sent.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/aws_sqs/metrics/tsvb/aws_sqs_messages_sent.ts similarity index 100% rename from x-pack/plugins/infra/common/inventory_models/aws_sqs/metrics/tsvb/aws_sqs_messages_sent.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/aws_sqs/metrics/tsvb/aws_sqs_messages_sent.ts diff --git a/x-pack/plugins/infra/common/inventory_models/aws_sqs/metrics/tsvb/aws_sqs_messages_visible.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/aws_sqs/metrics/tsvb/aws_sqs_messages_visible.ts similarity index 100% rename from x-pack/plugins/infra/common/inventory_models/aws_sqs/metrics/tsvb/aws_sqs_messages_visible.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/aws_sqs/metrics/tsvb/aws_sqs_messages_visible.ts diff --git a/x-pack/plugins/infra/common/inventory_models/aws_sqs/metrics/tsvb/aws_sqs_oldest_message.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/aws_sqs/metrics/tsvb/aws_sqs_oldest_message.ts similarity index 100% rename from x-pack/plugins/infra/common/inventory_models/aws_sqs/metrics/tsvb/aws_sqs_oldest_message.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/aws_sqs/metrics/tsvb/aws_sqs_oldest_message.ts diff --git a/x-pack/plugins/infra/common/inventory_models/container/index.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/container/index.ts similarity index 80% rename from x-pack/plugins/infra/common/inventory_models/container/index.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/container/index.ts index eb16a6a577a03..e50d020d1d4f7 100644 --- a/x-pack/plugins/infra/common/inventory_models/container/index.ts +++ b/x-pack/plugins/metrics_data_access/common/inventory_models/container/index.ts @@ -13,12 +13,15 @@ export { containerSnapshotMetricTypes } from './metrics'; export const container: InventoryModel = { id: 'container', - displayName: i18n.translate('xpack.infra.inventoryModel.container.displayName', { + displayName: i18n.translate('xpack.metricsData.inventoryModel.container.displayName', { defaultMessage: 'Docker Containers', }), - singularDisplayName: i18n.translate('xpack.infra.inventoryModel.container.singularDisplayName', { - defaultMessage: 'Docker Container', - }), + singularDisplayName: i18n.translate( + 'xpack.metricsData.inventoryModel.container.singularDisplayName', + { + defaultMessage: 'Docker Container', + } + ), requiredModule: 'docker', crosslinkSupport: { details: true, diff --git a/x-pack/plugins/infra/common/inventory_models/container/metrics/index.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/container/metrics/index.ts similarity index 100% rename from x-pack/plugins/infra/common/inventory_models/container/metrics/index.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/container/metrics/index.ts diff --git a/x-pack/plugins/infra/common/inventory_models/container/metrics/snapshot/cpu.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/container/metrics/snapshot/cpu.ts similarity index 100% rename from x-pack/plugins/infra/common/inventory_models/container/metrics/snapshot/cpu.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/container/metrics/snapshot/cpu.ts diff --git a/x-pack/plugins/infra/common/inventory_models/container/metrics/snapshot/memory.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/container/metrics/snapshot/memory.ts similarity index 100% rename from x-pack/plugins/infra/common/inventory_models/container/metrics/snapshot/memory.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/container/metrics/snapshot/memory.ts diff --git a/x-pack/plugins/infra/common/inventory_models/container/metrics/snapshot/rx.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/container/metrics/snapshot/rx.ts similarity index 100% rename from x-pack/plugins/infra/common/inventory_models/container/metrics/snapshot/rx.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/container/metrics/snapshot/rx.ts diff --git a/x-pack/plugins/infra/common/inventory_models/container/metrics/snapshot/tx.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/container/metrics/snapshot/tx.ts similarity index 100% rename from x-pack/plugins/infra/common/inventory_models/container/metrics/snapshot/tx.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/container/metrics/snapshot/tx.ts diff --git a/x-pack/plugins/infra/common/inventory_models/container/metrics/tsvb/container_cpu_kernel.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/container/metrics/tsvb/container_cpu_kernel.ts similarity index 100% rename from x-pack/plugins/infra/common/inventory_models/container/metrics/tsvb/container_cpu_kernel.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/container/metrics/tsvb/container_cpu_kernel.ts diff --git a/x-pack/plugins/infra/common/inventory_models/container/metrics/tsvb/container_cpu_usage.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/container/metrics/tsvb/container_cpu_usage.ts similarity index 100% rename from x-pack/plugins/infra/common/inventory_models/container/metrics/tsvb/container_cpu_usage.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/container/metrics/tsvb/container_cpu_usage.ts diff --git a/x-pack/plugins/infra/common/inventory_models/container/metrics/tsvb/container_disk_io_bytes.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/container/metrics/tsvb/container_disk_io_bytes.ts similarity index 100% rename from x-pack/plugins/infra/common/inventory_models/container/metrics/tsvb/container_disk_io_bytes.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/container/metrics/tsvb/container_disk_io_bytes.ts diff --git a/x-pack/plugins/infra/common/inventory_models/container/metrics/tsvb/container_diskio_ops.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/container/metrics/tsvb/container_diskio_ops.ts similarity index 100% rename from x-pack/plugins/infra/common/inventory_models/container/metrics/tsvb/container_diskio_ops.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/container/metrics/tsvb/container_diskio_ops.ts diff --git a/x-pack/plugins/infra/common/inventory_models/container/metrics/tsvb/container_k8s_cpu_usage.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/container/metrics/tsvb/container_k8s_cpu_usage.ts similarity index 100% rename from x-pack/plugins/infra/common/inventory_models/container/metrics/tsvb/container_k8s_cpu_usage.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/container/metrics/tsvb/container_k8s_cpu_usage.ts diff --git a/x-pack/plugins/infra/common/inventory_models/container/metrics/tsvb/container_k8s_memory_usage.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/container/metrics/tsvb/container_k8s_memory_usage.ts similarity index 100% rename from x-pack/plugins/infra/common/inventory_models/container/metrics/tsvb/container_k8s_memory_usage.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/container/metrics/tsvb/container_k8s_memory_usage.ts diff --git a/x-pack/plugins/infra/common/inventory_models/container/metrics/tsvb/container_k8s_overview.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/container/metrics/tsvb/container_k8s_overview.ts similarity index 100% rename from x-pack/plugins/infra/common/inventory_models/container/metrics/tsvb/container_k8s_overview.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/container/metrics/tsvb/container_k8s_overview.ts diff --git a/x-pack/plugins/infra/common/inventory_models/container/metrics/tsvb/container_memory.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/container/metrics/tsvb/container_memory.ts similarity index 100% rename from x-pack/plugins/infra/common/inventory_models/container/metrics/tsvb/container_memory.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/container/metrics/tsvb/container_memory.ts diff --git a/x-pack/plugins/infra/common/inventory_models/container/metrics/tsvb/container_network_traffic.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/container/metrics/tsvb/container_network_traffic.ts similarity index 100% rename from x-pack/plugins/infra/common/inventory_models/container/metrics/tsvb/container_network_traffic.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/container/metrics/tsvb/container_network_traffic.ts diff --git a/x-pack/plugins/infra/common/inventory_models/container/metrics/tsvb/container_overview.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/container/metrics/tsvb/container_overview.ts similarity index 100% rename from x-pack/plugins/infra/common/inventory_models/container/metrics/tsvb/container_overview.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/container/metrics/tsvb/container_overview.ts diff --git a/x-pack/plugins/infra/common/inventory_models/create_tsvb_model.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/create_tsvb_model.ts similarity index 100% rename from x-pack/plugins/infra/common/inventory_models/create_tsvb_model.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/create_tsvb_model.ts diff --git a/x-pack/plugins/infra/common/inventory_models/host/index.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/host/index.ts similarity index 56% rename from x-pack/plugins/infra/common/inventory_models/host/index.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/host/index.ts index 18af8bbfadc99..0b7389b74537d 100644 --- a/x-pack/plugins/infra/common/inventory_models/host/index.ts +++ b/x-pack/plugins/metrics_data_access/common/inventory_models/host/index.ts @@ -8,17 +8,24 @@ import { i18n } from '@kbn/i18n'; import { metrics } from './metrics'; import { InventoryModel } from '../types'; +import { + aws as awsRequiredMetrics, + nginx as nginxRequireMetrics, +} from '../shared/metrics/required_metrics'; export { hostSnapshotMetricTypes } from './metrics'; export const host: InventoryModel = { id: 'host', - displayName: i18n.translate('xpack.infra.inventoryModel.host.displayName', { + displayName: i18n.translate('xpack.metricsData.inventoryModel.host.displayName', { defaultMessage: 'Hosts', }), - singularDisplayName: i18n.translate('xpack.infra.inventoryModels.host.singularDisplayName', { - defaultMessage: 'Host', - }), + singularDisplayName: i18n.translate( + 'xpack.metricsData.inventoryModels.host.singularDisplayName', + { + defaultMessage: 'Host', + } + ), requiredModule: 'system', crosslinkSupport: { details: true, @@ -34,5 +41,19 @@ export const host: InventoryModel = { cloudProvider: 'cloud.provider', }, metrics, + requiredMetrics: [ + 'hostSystemOverview', + 'hostCpuUsage', + 'hostLoad', + 'hostMemoryUsage', + 'hostNetworkTraffic', + 'hostK8sOverview', + 'hostK8sCpuCap', + 'hostK8sMemoryCap', + 'hostK8sDiskCap', + 'hostK8sPodCap', + ...awsRequiredMetrics, + ...nginxRequireMetrics, + ], tooltipMetrics: ['cpu', 'memory', 'tx', 'rx'], }; diff --git a/x-pack/plugins/infra/common/inventory_models/host/metrics/index.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/host/metrics/index.ts similarity index 54% rename from x-pack/plugins/infra/common/inventory_models/host/metrics/index.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/host/metrics/index.ts index 3eff64ccb6a7a..e59aaefb2b82b 100644 --- a/x-pack/plugins/infra/common/inventory_models/host/metrics/index.ts +++ b/x-pack/plugins/metrics_data_access/common/inventory_models/host/metrics/index.ts @@ -18,6 +18,24 @@ import { normalizedLoad1m } from './snapshot/normalized_load_1m'; import { rx } from './snapshot/rx'; import { tx } from './snapshot/tx'; +import { hostSystemOverview } from './tsvb/host_system_overview'; +import { hostCpuUsage } from './tsvb/host_cpu_usage'; +import { hostLoad } from './tsvb/host_load'; +import { hostMemoryUsage } from './tsvb/host_memory_usage'; +import { hostNetworkTraffic } from './tsvb/host_network_traffic'; +import { hostFilesystem } from './tsvb/host_filesystem'; + +import { hostK8sOverview } from './tsvb/host_k8s_overview'; +import { hostK8sCpuCap } from './tsvb/host_k8s_cpu_cap'; +import { hostK8sPodCap } from './tsvb/host_k8s_pod_cap'; +import { hostK8sDiskCap } from './tsvb/host_k8s_disk_cap'; +import { hostK8sMemoryCap } from './tsvb/host_k8s_memory_cap'; + +import { hostDockerTop5ByMemory } from './tsvb/host_docker_top_5_by_memory'; +import { hostDockerTop5ByCpu } from './tsvb/host_docker_top_5_by_cpu'; +import { hostDockerOverview } from './tsvb/host_docker_overview'; +import { hostDockerInfo } from './tsvb/host_docker_info'; + import { InventoryMetrics } from '../../types'; const exposedHostSnapshotMetrics = { @@ -41,6 +59,23 @@ export const hostSnapshotMetricTypes = Object.keys(exposedHostSnapshotMetrics) a >; export const metrics: InventoryMetrics = { + tsvb: { + hostSystemOverview, + hostCpuUsage, + hostLoad, + hostMemoryUsage, + hostNetworkTraffic, + hostFilesystem, + hostK8sOverview, + hostK8sCpuCap, + hostK8sPodCap, + hostK8sDiskCap, + hostK8sMemoryCap, + hostDockerOverview, + hostDockerInfo, + hostDockerTop5ByMemory, + hostDockerTop5ByCpu, + }, snapshot: hostSnapshotMetrics, defaultSnapshot: 'cpu', defaultTimeRangeInSeconds: 3600, // 1 hour diff --git a/x-pack/plugins/infra/common/inventory_models/host/metrics/snapshot/cpu.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/host/metrics/snapshot/cpu.ts similarity index 100% rename from x-pack/plugins/infra/common/inventory_models/host/metrics/snapshot/cpu.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/host/metrics/snapshot/cpu.ts diff --git a/x-pack/plugins/infra/common/inventory_models/host/metrics/snapshot/disk_latency.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/host/metrics/snapshot/disk_latency.ts similarity index 100% rename from x-pack/plugins/infra/common/inventory_models/host/metrics/snapshot/disk_latency.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/host/metrics/snapshot/disk_latency.ts diff --git a/x-pack/plugins/infra/common/inventory_models/host/metrics/snapshot/disk_space_usage.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/host/metrics/snapshot/disk_space_usage.ts similarity index 100% rename from x-pack/plugins/infra/common/inventory_models/host/metrics/snapshot/disk_space_usage.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/host/metrics/snapshot/disk_space_usage.ts diff --git a/x-pack/plugins/infra/common/inventory_models/host/metrics/snapshot/load.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/host/metrics/snapshot/load.ts similarity index 100% rename from x-pack/plugins/infra/common/inventory_models/host/metrics/snapshot/load.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/host/metrics/snapshot/load.ts diff --git a/x-pack/plugins/infra/common/inventory_models/host/metrics/snapshot/log_rate.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/host/metrics/snapshot/log_rate.ts similarity index 100% rename from x-pack/plugins/infra/common/inventory_models/host/metrics/snapshot/log_rate.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/host/metrics/snapshot/log_rate.ts diff --git a/x-pack/plugins/infra/common/inventory_models/host/metrics/snapshot/memory.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/host/metrics/snapshot/memory.ts similarity index 100% rename from x-pack/plugins/infra/common/inventory_models/host/metrics/snapshot/memory.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/host/metrics/snapshot/memory.ts diff --git a/x-pack/plugins/infra/common/inventory_models/host/metrics/snapshot/memory_free.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/host/metrics/snapshot/memory_free.ts similarity index 100% rename from x-pack/plugins/infra/common/inventory_models/host/metrics/snapshot/memory_free.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/host/metrics/snapshot/memory_free.ts diff --git a/x-pack/plugins/infra/common/inventory_models/host/metrics/snapshot/memory_total.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/host/metrics/snapshot/memory_total.ts similarity index 100% rename from x-pack/plugins/infra/common/inventory_models/host/metrics/snapshot/memory_total.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/host/metrics/snapshot/memory_total.ts diff --git a/x-pack/plugins/infra/common/inventory_models/host/metrics/snapshot/normalized_load_1m.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/host/metrics/snapshot/normalized_load_1m.ts similarity index 100% rename from x-pack/plugins/infra/common/inventory_models/host/metrics/snapshot/normalized_load_1m.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/host/metrics/snapshot/normalized_load_1m.ts diff --git a/x-pack/plugins/infra/common/inventory_models/host/metrics/snapshot/rx.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/host/metrics/snapshot/rx.ts similarity index 100% rename from x-pack/plugins/infra/common/inventory_models/host/metrics/snapshot/rx.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/host/metrics/snapshot/rx.ts diff --git a/x-pack/plugins/infra/common/inventory_models/host/metrics/snapshot/tx.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/host/metrics/snapshot/tx.ts similarity index 100% rename from x-pack/plugins/infra/common/inventory_models/host/metrics/snapshot/tx.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/host/metrics/snapshot/tx.ts diff --git a/x-pack/plugins/metrics_data_access/common/inventory_models/host/metrics/tsvb/host_cpu_usage.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/host/metrics/tsvb/host_cpu_usage.ts new file mode 100644 index 0000000000000..bcafeb4ebc4cf --- /dev/null +++ b/x-pack/plugins/metrics_data_access/common/inventory_models/host/metrics/tsvb/host_cpu_usage.ts @@ -0,0 +1,254 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { TSVBMetricModelCreator, TSVBMetricModel } from '../../../types'; + +export const hostCpuUsage: TSVBMetricModelCreator = ( + timeField, + indexPattern, + interval +): TSVBMetricModel => ({ + id: 'hostCpuUsage', + requires: ['system.cpu'], + index_pattern: indexPattern, + interval, + time_field: timeField, + type: 'timeseries', + series: [ + { + id: 'user', + metrics: [ + { + field: 'system.cpu.user.pct', + id: 'avg-cpu-user', + type: 'avg', + }, + { + field: 'system.cpu.cores', + id: 'max-cpu-cores', + type: 'max', + }, + { + id: 'calc-avg-cores', + script: 'params.avg / params.cores', + type: 'calculation', + variables: [ + { + field: 'max-cpu-cores', + id: 'var-cores', + name: 'cores', + }, + { + field: 'avg-cpu-user', + id: 'var-avg', + name: 'avg', + }, + ], + }, + ], + split_mode: 'everything', + }, + { + id: 'system', + metrics: [ + { + field: 'system.cpu.system.pct', + id: 'avg-cpu-system', + type: 'avg', + }, + { + field: 'system.cpu.cores', + id: 'max-cpu-cores', + type: 'max', + }, + { + id: 'calc-avg-cores', + script: 'params.avg / params.cores', + type: 'calculation', + variables: [ + { + field: 'max-cpu-cores', + id: 'var-cores', + name: 'cores', + }, + { + field: 'avg-cpu-system', + id: 'var-avg', + name: 'avg', + }, + ], + }, + ], + split_mode: 'everything', + }, + { + id: 'steal', + metrics: [ + { + field: 'system.cpu.steal.pct', + id: 'avg-cpu-steal', + type: 'avg', + }, + { + field: 'system.cpu.cores', + id: 'max-cpu-cores', + type: 'max', + }, + { + id: 'calc-avg-cores', + script: 'params.avg / params.cores', + type: 'calculation', + variables: [ + { + field: 'avg-cpu-steal', + id: 'var-avg', + name: 'avg', + }, + { + field: 'max-cpu-cores', + id: 'var-cores', + name: 'cores', + }, + ], + }, + ], + split_mode: 'everything', + }, + { + id: 'irq', + metrics: [ + { + field: 'system.cpu.irq.pct', + id: 'avg-cpu-irq', + type: 'avg', + }, + { + field: 'system.cpu.cores', + id: 'max-cpu-cores', + type: 'max', + }, + { + id: 'calc-avg-cores', + script: 'params.avg / params.cores', + type: 'calculation', + variables: [ + { + field: 'max-cpu-cores', + id: 'var-cores', + name: 'cores', + }, + { + field: 'avg-cpu-irq', + id: 'var-avg', + name: 'avg', + }, + ], + }, + ], + split_mode: 'everything', + }, + { + id: 'softirq', + metrics: [ + { + field: 'system.cpu.softirq.pct', + id: 'avg-cpu-softirq', + type: 'avg', + }, + { + field: 'system.cpu.cores', + id: 'max-cpu-cores', + type: 'max', + }, + { + id: 'calc-avg-cores', + script: 'params.avg / params.cores', + type: 'calculation', + variables: [ + { + field: 'max-cpu-cores', + id: 'var-cores', + name: 'cores', + }, + { + field: 'avg-cpu-softirq', + id: 'var-avg', + name: 'avg', + }, + ], + }, + ], + split_mode: 'everything', + }, + { + id: 'iowait', + metrics: [ + { + field: 'system.cpu.iowait.pct', + id: 'avg-cpu-iowait', + type: 'avg', + }, + { + field: 'system.cpu.cores', + id: 'max-cpu-cores', + type: 'max', + }, + { + id: 'calc-avg-cores', + script: 'params.avg / params.cores', + type: 'calculation', + variables: [ + { + field: 'max-cpu-cores', + id: 'var-cores', + name: 'cores', + }, + { + field: 'avg-cpu-iowait', + id: 'var-avg', + name: 'avg', + }, + ], + }, + ], + split_mode: 'everything', + }, + { + id: 'nice', + metrics: [ + { + field: 'system.cpu.nice.pct', + id: 'avg-cpu-nice', + type: 'avg', + }, + { + field: 'system.cpu.cores', + id: 'max-cpu-cores', + type: 'max', + }, + { + id: 'calc-avg-cores', + script: 'params.avg / params.cores', + type: 'calculation', + variables: [ + { + field: 'max-cpu-cores', + id: 'var-cores', + name: 'cores', + }, + { + field: 'avg-cpu-nice', + id: 'var-avg', + name: 'avg', + }, + ], + }, + ], + split_mode: 'everything', + }, + ], +}); diff --git a/x-pack/plugins/metrics_data_access/common/inventory_models/host/metrics/tsvb/host_docker_info.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/host/metrics/tsvb/host_docker_info.ts new file mode 100644 index 0000000000000..4cc2b574362d7 --- /dev/null +++ b/x-pack/plugins/metrics_data_access/common/inventory_models/host/metrics/tsvb/host_docker_info.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 { TSVBMetricModelCreator, TSVBMetricModel } from '../../../types'; + +export const hostDockerInfo: TSVBMetricModelCreator = ( + timeField, + indexPattern, + interval +): TSVBMetricModel => ({ + id: 'hostDockerInfo', + requires: ['docker.info'], + index_pattern: indexPattern, + interval, + time_field: timeField, + type: 'timeseries', + series: [ + { + id: 'running', + metrics: [ + { + field: 'docker.info.containers.running', + id: 'max-running', + type: 'max', + }, + ], + split_mode: 'everything', + }, + { + id: 'paused', + metrics: [ + { + field: 'docker.info.containers.paused', + id: 'max-paused', + type: 'max', + }, + ], + split_mode: 'everything', + }, + { + id: 'stopped', + metrics: [ + { + field: 'docker.info.containers.stopped', + id: 'max-stopped', + type: 'max', + }, + ], + split_mode: 'everything', + }, + ], +}); diff --git a/x-pack/plugins/metrics_data_access/common/inventory_models/host/metrics/tsvb/host_docker_overview.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/host/metrics/tsvb/host_docker_overview.ts new file mode 100644 index 0000000000000..df56a21dbf5b7 --- /dev/null +++ b/x-pack/plugins/metrics_data_access/common/inventory_models/host/metrics/tsvb/host_docker_overview.ts @@ -0,0 +1,67 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { TSVBMetricModelCreator, TSVBMetricModel } from '../../../types'; + +export const hostDockerOverview: TSVBMetricModelCreator = ( + timeField, + indexPattern, + interval +): TSVBMetricModel => ({ + id: 'hostDockerOverview', + requires: ['docker.info'], + index_pattern: indexPattern, + interval, + time_field: timeField, + type: 'top_n', + series: [ + { + id: 'total', + metrics: [ + { + field: 'docker.info.containers.total', + id: 'max-total', + type: 'max', + }, + ], + split_mode: 'everything', + }, + { + id: 'running', + metrics: [ + { + field: 'docker.info.containers.running', + id: 'max-running', + type: 'max', + }, + ], + split_mode: 'everything', + }, + { + id: 'paused', + metrics: [ + { + field: 'docker.info.containers.paused', + id: 'max-paused', + type: 'max', + }, + ], + split_mode: 'everything', + }, + { + id: 'stopped', + metrics: [ + { + field: 'docker.info.containers.stopped', + id: 'max-stopped', + type: 'max', + }, + ], + split_mode: 'everything', + }, + ], +}); diff --git a/x-pack/plugins/metrics_data_access/common/inventory_models/host/metrics/tsvb/host_docker_top_5_by_cpu.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/host/metrics/tsvb/host_docker_top_5_by_cpu.ts new file mode 100644 index 0000000000000..fd9eb97419736 --- /dev/null +++ b/x-pack/plugins/metrics_data_access/common/inventory_models/host/metrics/tsvb/host_docker_top_5_by_cpu.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 { TSVBMetricModelCreator, TSVBMetricModel } from '../../../types'; + +export const hostDockerTop5ByCpu: TSVBMetricModelCreator = ( + timeField, + indexPattern, + interval +): TSVBMetricModel => ({ + id: 'hostDockerTop5ByCpu', + requires: ['docker.cpu'], + index_pattern: indexPattern, + interval, + time_field: timeField, + type: 'timeseries', + series: [ + { + id: 'avg-cpu', + metrics: [ + { + field: 'docker.cpu.total.pct', + id: 'avg-cpu-metric', + type: 'avg', + }, + ], + split_mode: 'terms', + terms_field: 'container.name', + terms_order_by: 'avg-cpu', + terms_size: 5, + }, + ], +}); diff --git a/x-pack/plugins/metrics_data_access/common/inventory_models/host/metrics/tsvb/host_docker_top_5_by_memory.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/host/metrics/tsvb/host_docker_top_5_by_memory.ts new file mode 100644 index 0000000000000..cad828671d232 --- /dev/null +++ b/x-pack/plugins/metrics_data_access/common/inventory_models/host/metrics/tsvb/host_docker_top_5_by_memory.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 { TSVBMetricModelCreator, TSVBMetricModel } from '../../../types'; + +export const hostDockerTop5ByMemory: TSVBMetricModelCreator = ( + timeField, + indexPattern, + interval +): TSVBMetricModel => ({ + id: 'hostDockerTop5ByMemory', + requires: ['docker.memory'], + index_pattern: indexPattern, + interval, + time_field: timeField, + type: 'timeseries', + series: [ + { + id: 'avg-memory', + metrics: [ + { + field: 'docker.memory.usage.pct', + id: 'avg-memory-metric', + type: 'avg', + }, + ], + split_mode: 'terms', + terms_field: 'container.name', + terms_order_by: 'avg-memory', + terms_size: 5, + }, + ], +}); diff --git a/x-pack/plugins/metrics_data_access/common/inventory_models/host/metrics/tsvb/host_filesystem.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/host/metrics/tsvb/host_filesystem.ts new file mode 100644 index 0000000000000..ce284345410fc --- /dev/null +++ b/x-pack/plugins/metrics_data_access/common/inventory_models/host/metrics/tsvb/host_filesystem.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 { TSVBMetricModelCreator, TSVBMetricModel } from '../../../types'; + +export const hostFilesystem: TSVBMetricModelCreator = ( + timeField, + indexPattern, + interval +): TSVBMetricModel => ({ + id: 'hostFilesystem', + requires: ['system.filesystem'], + filter: 'system.filesystem.device_name:\\/*', + index_pattern: indexPattern, + time_field: timeField, + interval, + type: 'timeseries', + series: [ + { + id: 'used', + metrics: [ + { + field: 'system.filesystem.used.pct', + id: 'avg-filesystem-used', + type: 'avg', + }, + ], + split_mode: 'terms', + terms_field: 'system.filesystem.device_name', + terms_order_by: 'used', + terms_size: 5, + }, + ], +}); diff --git a/x-pack/plugins/metrics_data_access/common/inventory_models/host/metrics/tsvb/host_k8s_cpu_cap.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/host/metrics/tsvb/host_k8s_cpu_cap.ts new file mode 100644 index 0000000000000..d33e4cdeb34cd --- /dev/null +++ b/x-pack/plugins/metrics_data_access/common/inventory_models/host/metrics/tsvb/host_k8s_cpu_cap.ts @@ -0,0 +1,58 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { TSVBMetricModelCreator, TSVBMetricModel } from '../../../types'; + +export const hostK8sCpuCap: TSVBMetricModelCreator = ( + timeField, + indexPattern, + interval +): TSVBMetricModel => ({ + id: 'hostK8sCpuCap', + map_field_to: 'kubernetes.node.name', + requires: ['kubernetes.node'], + index_pattern: indexPattern, + interval, + time_field: timeField, + type: 'timeseries', + series: [ + { + id: 'capacity', + metrics: [ + { + field: 'kubernetes.node.cpu.allocatable.cores', + id: 'max-cpu-cap', + type: 'max', + }, + { + id: 'calc-nanocores', + type: 'calculation', + variables: [ + { + id: 'var-cores', + field: 'max-cpu-cap', + name: 'cores', + }, + ], + script: 'params.cores * 1000000000', + }, + ], + split_mode: 'everything', + }, + { + id: 'used', + metrics: [ + { + field: 'kubernetes.node.cpu.usage.nanocores', + id: 'avg-cpu-usage', + type: 'avg', + }, + ], + split_mode: 'everything', + }, + ], +}); diff --git a/x-pack/plugins/metrics_data_access/common/inventory_models/host/metrics/tsvb/host_k8s_disk_cap.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/host/metrics/tsvb/host_k8s_disk_cap.ts new file mode 100644 index 0000000000000..e9e512a136631 --- /dev/null +++ b/x-pack/plugins/metrics_data_access/common/inventory_models/host/metrics/tsvb/host_k8s_disk_cap.ts @@ -0,0 +1,45 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { TSVBMetricModelCreator, TSVBMetricModel } from '../../../types'; +export const hostK8sDiskCap: TSVBMetricModelCreator = ( + timeField, + indexPattern, + interval +): TSVBMetricModel => ({ + id: 'hostK8sDiskCap', + map_field_to: 'kubernetes.node.name', + requires: ['kubernetes.node'], + index_pattern: indexPattern, + interval, + time_field: timeField, + type: 'timeseries', + series: [ + { + id: 'capacity', + metrics: [ + { + field: 'kubernetes.node.fs.capacity.bytes', + id: 'max-fs-cap', + type: 'max', + }, + ], + split_mode: 'everything', + }, + { + id: 'used', + metrics: [ + { + field: 'kubernetes.node.fs.used.bytes', + id: 'avg-fs-used', + type: 'avg', + }, + ], + split_mode: 'everything', + }, + ], +}); diff --git a/x-pack/plugins/metrics_data_access/common/inventory_models/host/metrics/tsvb/host_k8s_memory_cap.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/host/metrics/tsvb/host_k8s_memory_cap.ts new file mode 100644 index 0000000000000..ccc227ef1854e --- /dev/null +++ b/x-pack/plugins/metrics_data_access/common/inventory_models/host/metrics/tsvb/host_k8s_memory_cap.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 { TSVBMetricModelCreator, TSVBMetricModel } from '../../../types'; + +export const hostK8sMemoryCap: TSVBMetricModelCreator = ( + timeField, + indexPattern, + interval +): TSVBMetricModel => ({ + id: 'hostK8sMemoryCap', + map_field_to: 'kubernetes.node.name', + requires: ['kubernetes.node'], + index_pattern: indexPattern, + interval, + time_field: timeField, + type: 'timeseries', + series: [ + { + id: 'capacity', + metrics: [ + { + field: 'kubernetes.node.memory.allocatable.bytes', + id: 'max-memory-cap', + type: 'max', + }, + ], + split_mode: 'everything', + }, + { + id: 'used', + metrics: [ + { + field: 'kubernetes.node.memory.usage.bytes', + id: 'avg-memory-usage', + type: 'avg', + }, + ], + split_mode: 'everything', + }, + ], +}); diff --git a/x-pack/plugins/metrics_data_access/common/inventory_models/host/metrics/tsvb/host_k8s_overview.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/host/metrics/tsvb/host_k8s_overview.ts new file mode 100644 index 0000000000000..2da74d50dff1b --- /dev/null +++ b/x-pack/plugins/metrics_data_access/common/inventory_models/host/metrics/tsvb/host_k8s_overview.ts @@ -0,0 +1,155 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { TSVBMetricModelCreator, TSVBMetricModel } from '../../../types'; + +export const hostK8sOverview: TSVBMetricModelCreator = ( + timeField, + indexPattern, + interval +): TSVBMetricModel => ({ + id: 'hostK8sOverview', + requires: ['kubernetes'], + index_pattern: indexPattern, + interval, + time_field: timeField, + type: 'top_n', + series: [ + { + id: 'cpucap', + split_mode: 'everything', + metrics: [ + { + field: 'kubernetes.node.cpu.allocatable.cores', + id: 'max-cpu-cap', + type: 'max', + }, + { + field: 'kubernetes.node.cpu.usage.nanocores', + id: 'avg-cpu-usage', + type: 'avg', + }, + { + id: 'calc-used-cap', + script: 'params.used / (params.cap * 1000000000)', + type: 'calculation', + variables: [ + { + field: 'max-cpu-cap', + id: 'var-cap', + name: 'cap', + }, + { + field: 'avg-cpu-usage', + id: 'var-used', + name: 'used', + }, + ], + }, + ], + }, + { + id: 'diskcap', + metrics: [ + { + field: 'kubernetes.node.fs.capacity.bytes', + id: 'max-fs-cap', + type: 'max', + }, + { + field: 'kubernetes.node.fs.used.bytes', + id: 'avg-fs-used', + type: 'avg', + }, + { + id: 'calc-used-cap', + script: 'params.used / params.cap', + type: 'calculation', + variables: [ + { + field: 'max-fs-cap', + id: 'var-cap', + name: 'cap', + }, + { + field: 'avg-fs-used', + id: 'var-used', + name: 'used', + }, + ], + }, + ], + split_mode: 'everything', + }, + { + id: 'memorycap', + metrics: [ + { + field: 'kubernetes.node.memory.allocatable.bytes', + id: 'max-memory-cap', + type: 'max', + }, + { + field: 'kubernetes.node.memory.usage.bytes', + id: 'avg-memory-usage', + type: 'avg', + }, + { + id: 'calc-used-cap', + script: 'params.used / params.cap', + type: 'calculation', + variables: [ + { + field: 'max-memory-cap', + id: 'var-cap', + name: 'cap', + }, + { + field: 'avg-memory-usage', + id: 'var-used', + name: 'used', + }, + ], + }, + ], + split_mode: 'everything', + }, + { + id: 'podcap', + metrics: [ + { + field: 'kubernetes.node.pod.capacity.total', + id: 'max-pod-cap', + type: 'max', + }, + { + field: 'kubernetes.pod.uid', + id: 'card-pod-name', + type: 'cardinality', + }, + { + id: 'calc-used-cap', + script: 'params.used / params.cap', + type: 'calculation', + variables: [ + { + field: 'max-pod-cap', + id: 'var-cap', + name: 'cap', + }, + { + field: 'card-pod-name', + id: 'var-used', + name: 'used', + }, + ], + }, + ], + split_mode: 'everything', + }, + ], +}); diff --git a/x-pack/plugins/metrics_data_access/common/inventory_models/host/metrics/tsvb/host_k8s_pod_cap.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/host/metrics/tsvb/host_k8s_pod_cap.ts new file mode 100644 index 0000000000000..85cb798eaf9b9 --- /dev/null +++ b/x-pack/plugins/metrics_data_access/common/inventory_models/host/metrics/tsvb/host_k8s_pod_cap.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 { TSVBMetricModelCreator, TSVBMetricModel } from '../../../types'; + +export const hostK8sPodCap: TSVBMetricModelCreator = ( + timeField, + indexPattern, + interval +): TSVBMetricModel => ({ + id: 'hostK8sPodCap', + requires: ['kubernetes.node'], + map_field_to: 'kubernetes.node.name', + index_pattern: indexPattern, + interval, + time_field: timeField, + type: 'timeseries', + + series: [ + { + id: 'capacity', + metrics: [ + { + field: 'kubernetes.node.pod.allocatable.total', + id: 'max-pod-cap', + type: 'max', + }, + ], + split_mode: 'everything', + }, + { + id: 'used', + metrics: [ + { + field: 'kubernetes.pod.uid', + id: 'avg-pod', + type: 'cardinality', + }, + ], + split_mode: 'everything', + }, + ], +}); diff --git a/x-pack/plugins/metrics_data_access/common/inventory_models/host/metrics/tsvb/host_load.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/host/metrics/tsvb/host_load.ts new file mode 100644 index 0000000000000..bef170c743e6c --- /dev/null +++ b/x-pack/plugins/metrics_data_access/common/inventory_models/host/metrics/tsvb/host_load.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 { TSVBMetricModelCreator, TSVBMetricModel } from '../../../types'; + +export const hostLoad: TSVBMetricModelCreator = ( + timeField, + indexPattern, + interval +): TSVBMetricModel => ({ + id: 'hostLoad', + requires: ['system.cpu'], + index_pattern: indexPattern, + interval, + time_field: timeField, + type: 'timeseries', + series: [ + { + id: 'load_1m', + metrics: [ + { + field: 'system.load.1', + id: 'avg-load-1m', + type: 'avg', + }, + ], + split_mode: 'everything', + }, + { + id: 'load_5m', + metrics: [ + { + field: 'system.load.5', + id: 'avg-load-5m', + type: 'avg', + }, + ], + split_mode: 'everything', + }, + { + id: 'load_15m', + metrics: [ + { + field: 'system.load.15', + id: 'avg-load-15m', + type: 'avg', + }, + ], + split_mode: 'everything', + }, + ], +}); diff --git a/x-pack/plugins/metrics_data_access/common/inventory_models/host/metrics/tsvb/host_memory_usage.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/host/metrics/tsvb/host_memory_usage.ts new file mode 100644 index 0000000000000..bda81dea4bd28 --- /dev/null +++ b/x-pack/plugins/metrics_data_access/common/inventory_models/host/metrics/tsvb/host_memory_usage.ts @@ -0,0 +1,78 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { TSVBMetricModelCreator, TSVBMetricModel } from '../../../types'; + +export const hostMemoryUsage: TSVBMetricModelCreator = ( + timeField, + indexPattern, + interval +): TSVBMetricModel => ({ + id: 'hostMemoryUsage', + requires: ['system.memory'], + index_pattern: indexPattern, + interval, + time_field: timeField, + type: 'timeseries', + series: [ + { + id: 'free', + metrics: [ + { + field: 'system.memory.free', + id: 'avg-memory-free', + type: 'avg', + }, + ], + split_mode: 'everything', + }, + { + id: 'used', + metrics: [ + { + field: 'system.memory.actual.used.bytes', + id: 'avg-memory-used', + type: 'avg', + }, + ], + split_mode: 'everything', + }, + { + id: 'cache', + metrics: [ + { + field: 'system.memory.actual.used.bytes', + id: 'avg-memory-actual-used', + type: 'avg', + }, + { + field: 'system.memory.used.bytes', + id: 'avg-memory-used', + type: 'avg', + }, + { + id: 'calc-used-actual', + script: 'params.used - params.actual', + type: 'calculation', + variables: [ + { + field: 'avg-memory-actual-used', + id: 'var-actual', + name: 'actual', + }, + { + field: 'avg-memory-used', + id: 'var-used', + name: 'used', + }, + ], + }, + ], + split_mode: 'everything', + }, + ], +}); diff --git a/x-pack/plugins/metrics_data_access/common/inventory_models/host/metrics/tsvb/host_network_traffic.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/host/metrics/tsvb/host_network_traffic.ts new file mode 100644 index 0000000000000..b3dfc5e91ba0a --- /dev/null +++ b/x-pack/plugins/metrics_data_access/common/inventory_models/host/metrics/tsvb/host_network_traffic.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 { TSVBMetricModelCreator, TSVBMetricModel } from '../../../types'; + +export const hostNetworkTraffic: TSVBMetricModelCreator = ( + timeField, + indexPattern, + interval +): TSVBMetricModel => ({ + id: 'hostNetworkTraffic', + requires: ['system.network'], + index_pattern: indexPattern, + interval, + time_field: timeField, + type: 'timeseries', + series: [ + { + id: 'tx', + metrics: [ + { + field: 'host.network.egress.bytes', + id: 'avg-net-out', + type: 'avg', + }, + { + id: 'max-period', + type: 'max', + field: 'metricset.period', + }, + { + id: '3216b170-f192-11ec-a8e3-dd984b7213e2', + type: 'calculation', + variables: [ + { + id: '34e64c30-f192-11ec-a8e3-dd984b7213e2', + name: 'value', + field: 'avg-net-out', + }, + { + id: '3886cb80-f192-11ec-a8e3-dd984b7213e2', + name: 'period', + field: 'max-period', + }, + ], + script: 'params.value / (params.period / 1000)', + }, + ], + filter: { + language: 'kuery', + query: 'host.network.egress.bytes : * ', + }, + split_mode: 'everything', + }, + { + id: 'rx', + metrics: [ + { + field: 'host.network.ingress.bytes', + id: 'avg-net-in', + type: 'avg', + }, + { + id: 'calc-invert-rate', + script: 'params.rate * -1', + type: 'calculation', + variables: [ + { + field: 'avg-net-in', + id: 'var-rate', + name: 'rate', + }, + ], + }, + { + id: 'max-period', + type: 'max', + field: 'metricset.period', + }, + { + id: '3216b170-f192-11ec-a8e3-dd984b7213e2', + type: 'calculation', + variables: [ + { + id: '34e64c30-f192-11ec-a8e3-dd984b7213e2', + name: 'value', + field: 'calc-invert-rate', + }, + { + id: '3886cb80-f192-11ec-a8e3-dd984b7213e2', + name: 'period', + field: 'max-period', + }, + ], + script: 'params.value / (params.period / 1000)', + }, + ], + filter: { + language: 'kuery', + query: 'host.network.ingress.bytes : * ', + }, + split_mode: 'everything', + }, + ], +}); diff --git a/x-pack/plugins/metrics_data_access/common/inventory_models/host/metrics/tsvb/host_system_overview.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/host/metrics/tsvb/host_system_overview.ts new file mode 100644 index 0000000000000..69ebd0aa35947 --- /dev/null +++ b/x-pack/plugins/metrics_data_access/common/inventory_models/host/metrics/tsvb/host_system_overview.ts @@ -0,0 +1,130 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { TSVBMetricModelCreator, TSVBMetricModel } from '../../../types'; + +export const hostSystemOverview: TSVBMetricModelCreator = ( + timeField, + indexPattern, + interval +): TSVBMetricModel => ({ + id: 'hostSystemOverview', + requires: ['system.cpu', 'system.memory', 'system.load', 'system.network'], + index_pattern: indexPattern, + interval, + time_field: timeField, + type: 'top_n', + series: [ + { + id: 'cpu', + split_mode: 'everything', + metrics: [ + { + field: 'system.cpu.total.norm.pct', + id: 'avg-cpu-total', + type: 'avg', + }, + ], + }, + { + id: 'load', + split_mode: 'everything', + metrics: [ + { + field: 'system.load.5', + id: 'avg-load-5m', + type: 'avg', + }, + ], + }, + { + id: 'memory', + split_mode: 'everything', + metrics: [ + { + field: 'system.memory.actual.used.pct', + id: 'avg-memory-actual-used', + type: 'avg', + }, + ], + }, + { + id: 'rx', + metrics: [ + { + field: 'host.network.ingress.bytes', + id: 'avg-net-in', + type: 'avg', + }, + { + id: 'max-period', + type: 'max', + field: 'metricset.period', + }, + { + id: '3216b170-f192-11ec-a8e3-dd984b7213e2', + type: 'calculation', + variables: [ + { + id: '34e64c30-f192-11ec-a8e3-dd984b7213e2', + name: 'value', + field: 'avg-net-in', + }, + { + id: '3886cb80-f192-11ec-a8e3-dd984b7213e2', + name: 'period', + field: 'max-period', + }, + ], + script: 'params.value / (params.period / 1000)', + }, + ], + filter: { + language: 'kuery', + query: 'host.network.ingress.bytes : * ', + }, + split_mode: 'everything', + }, + { + id: 'tx', + metrics: [ + { + field: 'host.network.egress.bytes', + id: 'avg-net-out', + type: 'avg', + }, + { + id: 'max-period', + type: 'max', + field: 'metricset.period', + }, + { + id: '3216b170-f192-11ec-a8e3-dd984b7213e2', + type: 'calculation', + variables: [ + { + id: '34e64c30-f192-11ec-a8e3-dd984b7213e2', + name: 'value', + field: 'avg-net-out', + }, + { + id: '3886cb80-f192-11ec-a8e3-dd984b7213e2', + name: 'period', + field: 'max-period', + }, + ], + script: 'params.value / (params.period / 1000)', + }, + ], + filter: { + language: 'kuery', + query: 'host.network.egress.bytes : * ', + }, + split_mode: 'everything', + }, + ], +}); diff --git a/x-pack/plugins/infra/common/inventory_models/index.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/index.ts similarity index 95% rename from x-pack/plugins/infra/common/inventory_models/index.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/index.ts index 81f89be8cd6a6..6d683f287c991 100644 --- a/x-pack/plugins/infra/common/inventory_models/index.ts +++ b/x-pack/plugins/metrics_data_access/common/inventory_models/index.ts @@ -23,7 +23,7 @@ export const findInventoryModel = (type: InventoryItemType) => { const model = inventoryModels.find((m) => m.id === type); if (!model) { throw new Error( - i18n.translate('xpack.infra.inventoryModels.findInventoryModel.error', { + i18n.translate('xpack.metricsData.inventoryModels.findInventoryModel.error', { defaultMessage: "The inventory model you've attempted to find does not exist", }) ); diff --git a/x-pack/plugins/infra/common/inventory_models/metrics.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/metrics.ts similarity index 100% rename from x-pack/plugins/infra/common/inventory_models/metrics.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/metrics.ts diff --git a/x-pack/plugins/infra/common/inventory_models/pod/index.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/pod/index.ts similarity index 85% rename from x-pack/plugins/infra/common/inventory_models/pod/index.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/pod/index.ts index b7a2cb776c6db..3a8cf778c00f3 100644 --- a/x-pack/plugins/infra/common/inventory_models/pod/index.ts +++ b/x-pack/plugins/metrics_data_access/common/inventory_models/pod/index.ts @@ -14,10 +14,10 @@ export { podSnapshotMetricTypes } from './metrics'; export const pod: InventoryModel = { id: 'pod', - displayName: i18n.translate('xpack.infra.inventoryModel.pod.displayName', { + displayName: i18n.translate('xpack.metricsData.inventoryModel.pod.displayName', { defaultMessage: 'Kubernetes Pods', }), - singularDisplayName: i18n.translate('xpack.infra.inventoryModels.pod.singularDisplayName', { + singularDisplayName: i18n.translate('xpack.metricsData.inventoryModels.pod.singularDisplayName', { defaultMessage: 'Kubernetes Pod', }), requiredModule: 'kubernetes', diff --git a/x-pack/plugins/infra/common/inventory_models/pod/metrics/index.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/pod/metrics/index.ts similarity index 100% rename from x-pack/plugins/infra/common/inventory_models/pod/metrics/index.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/pod/metrics/index.ts diff --git a/x-pack/plugins/infra/common/inventory_models/pod/metrics/snapshot/cpu.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/pod/metrics/snapshot/cpu.ts similarity index 100% rename from x-pack/plugins/infra/common/inventory_models/pod/metrics/snapshot/cpu.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/pod/metrics/snapshot/cpu.ts diff --git a/x-pack/plugins/infra/common/inventory_models/pod/metrics/snapshot/memory.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/pod/metrics/snapshot/memory.ts similarity index 100% rename from x-pack/plugins/infra/common/inventory_models/pod/metrics/snapshot/memory.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/pod/metrics/snapshot/memory.ts diff --git a/x-pack/plugins/infra/common/inventory_models/pod/metrics/snapshot/rx.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/pod/metrics/snapshot/rx.ts similarity index 100% rename from x-pack/plugins/infra/common/inventory_models/pod/metrics/snapshot/rx.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/pod/metrics/snapshot/rx.ts diff --git a/x-pack/plugins/infra/common/inventory_models/pod/metrics/snapshot/tx.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/pod/metrics/snapshot/tx.ts similarity index 100% rename from x-pack/plugins/infra/common/inventory_models/pod/metrics/snapshot/tx.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/pod/metrics/snapshot/tx.ts diff --git a/x-pack/plugins/infra/common/inventory_models/pod/metrics/tsvb/pod_cpu_usage.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/pod/metrics/tsvb/pod_cpu_usage.ts similarity index 100% rename from x-pack/plugins/infra/common/inventory_models/pod/metrics/tsvb/pod_cpu_usage.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/pod/metrics/tsvb/pod_cpu_usage.ts diff --git a/x-pack/plugins/infra/common/inventory_models/pod/metrics/tsvb/pod_log_usage.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/pod/metrics/tsvb/pod_log_usage.ts similarity index 100% rename from x-pack/plugins/infra/common/inventory_models/pod/metrics/tsvb/pod_log_usage.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/pod/metrics/tsvb/pod_log_usage.ts diff --git a/x-pack/plugins/infra/common/inventory_models/pod/metrics/tsvb/pod_memory_usage.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/pod/metrics/tsvb/pod_memory_usage.ts similarity index 100% rename from x-pack/plugins/infra/common/inventory_models/pod/metrics/tsvb/pod_memory_usage.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/pod/metrics/tsvb/pod_memory_usage.ts diff --git a/x-pack/plugins/infra/common/inventory_models/pod/metrics/tsvb/pod_network_traffic.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/pod/metrics/tsvb/pod_network_traffic.ts similarity index 100% rename from x-pack/plugins/infra/common/inventory_models/pod/metrics/tsvb/pod_network_traffic.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/pod/metrics/tsvb/pod_network_traffic.ts diff --git a/x-pack/plugins/infra/common/inventory_models/pod/metrics/tsvb/pod_overview.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/pod/metrics/tsvb/pod_overview.ts similarity index 100% rename from x-pack/plugins/infra/common/inventory_models/pod/metrics/tsvb/pod_overview.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/pod/metrics/tsvb/pod_overview.ts diff --git a/x-pack/plugins/infra/common/inventory_models/shared/metrics/index.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/shared/metrics/index.ts similarity index 64% rename from x-pack/plugins/infra/common/inventory_models/shared/metrics/index.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/shared/metrics/index.ts index 2dac80de51161..775dff525b7f5 100644 --- a/x-pack/plugins/infra/common/inventory_models/shared/metrics/index.ts +++ b/x-pack/plugins/metrics_data_access/common/inventory_models/shared/metrics/index.ts @@ -10,6 +10,12 @@ import { nginxActiveConnections } from './tsvb/nginx_active_connections'; import { nginxHits } from './tsvb/nginx_hits'; import { nginxRequestsPerConnection } from './tsvb/nginx_requests_per_connection'; +import { awsCpuUtilization } from './tsvb/aws_cpu_utilization'; +import { awsDiskioBytes } from './tsvb/aws_diskio_bytes'; +import { awsDiskioOps } from './tsvb/aws_diskio_ops'; +import { awsNetworkBytes } from './tsvb/aws_network_bytes'; +import { awsNetworkPackets } from './tsvb/aws_network_packets'; +import { awsOverview } from './tsvb/aws_overview'; import { InventoryMetrics } from '../../types'; import { count } from './snapshot/count'; @@ -19,6 +25,12 @@ export const metrics: InventoryMetrics = { nginxHits, nginxRequestRate, nginxRequestsPerConnection, + awsCpuUtilization, + awsDiskioBytes, + awsDiskioOps, + awsNetworkBytes, + awsNetworkPackets, + awsOverview, }, snapshot: { count, diff --git a/x-pack/plugins/infra/common/inventory_models/shared/metrics/required_metrics.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/shared/metrics/required_metrics.ts similarity index 72% rename from x-pack/plugins/infra/common/inventory_models/shared/metrics/required_metrics.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/shared/metrics/required_metrics.ts index 172b48a1ba68d..5b29fc93e0d0c 100644 --- a/x-pack/plugins/infra/common/inventory_models/shared/metrics/required_metrics.ts +++ b/x-pack/plugins/metrics_data_access/common/inventory_models/shared/metrics/required_metrics.ts @@ -13,3 +13,12 @@ export const nginx: InventoryMetric[] = [ 'nginxActiveConnections', 'nginxRequestsPerConnection', ]; + +export const aws: InventoryMetric[] = [ + 'awsOverview', + 'awsCpuUtilization', + 'awsNetworkBytes', + 'awsNetworkPackets', + 'awsDiskioOps', + 'awsDiskioBytes', +]; diff --git a/x-pack/plugins/infra/common/inventory_models/shared/metrics/snapshot/count.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/shared/metrics/snapshot/count.ts similarity index 100% rename from x-pack/plugins/infra/common/inventory_models/shared/metrics/snapshot/count.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/shared/metrics/snapshot/count.ts diff --git a/x-pack/plugins/infra/common/inventory_models/shared/metrics/snapshot/network_traffic.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/shared/metrics/snapshot/network_traffic.ts similarity index 100% rename from x-pack/plugins/infra/common/inventory_models/shared/metrics/snapshot/network_traffic.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/shared/metrics/snapshot/network_traffic.ts diff --git a/x-pack/plugins/infra/common/inventory_models/shared/metrics/snapshot/network_traffic_with_interfaces.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/shared/metrics/snapshot/network_traffic_with_interfaces.ts similarity index 100% rename from x-pack/plugins/infra/common/inventory_models/shared/metrics/snapshot/network_traffic_with_interfaces.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/shared/metrics/snapshot/network_traffic_with_interfaces.ts diff --git a/x-pack/plugins/infra/common/inventory_models/shared/metrics/snapshot/rate.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/shared/metrics/snapshot/rate.ts similarity index 100% rename from x-pack/plugins/infra/common/inventory_models/shared/metrics/snapshot/rate.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/shared/metrics/snapshot/rate.ts diff --git a/x-pack/plugins/metrics_data_access/common/inventory_models/shared/metrics/tsvb/aws_cpu_utilization.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/shared/metrics/tsvb/aws_cpu_utilization.ts new file mode 100644 index 0000000000000..51b9a4cfc7b3f --- /dev/null +++ b/x-pack/plugins/metrics_data_access/common/inventory_models/shared/metrics/tsvb/aws_cpu_utilization.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 { TSVBMetricModelCreator, TSVBMetricModel } from '../../../types'; + +export const awsCpuUtilization: TSVBMetricModelCreator = ( + timeField, + indexPattern +): TSVBMetricModel => ({ + id: 'awsCpuUtilization', + requires: ['aws.ec2'], + map_field_to: 'cloud.instance.id', + id_type: 'cloud', + index_pattern: indexPattern, + interval: '>=5m', + time_field: timeField, + type: 'timeseries', + series: [ + { + id: 'cpu-util', + metrics: [ + { + field: 'aws.ec2.cpu.total.pct', + id: 'avg-cpu-util', + type: 'avg', + }, + ], + split_mode: 'everything', + }, + ], +}); diff --git a/x-pack/plugins/metrics_data_access/common/inventory_models/shared/metrics/tsvb/aws_diskio_bytes.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/shared/metrics/tsvb/aws_diskio_bytes.ts new file mode 100644 index 0000000000000..5224545c006b7 --- /dev/null +++ b/x-pack/plugins/metrics_data_access/common/inventory_models/shared/metrics/tsvb/aws_diskio_bytes.ts @@ -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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { TSVBMetricModelCreator, TSVBMetricModel } from '../../../types'; + +export const awsDiskioBytes: TSVBMetricModelCreator = ( + timeField, + indexPattern +): TSVBMetricModel => ({ + id: 'awsDiskioBytes', + requires: ['aws.ec2'], + index_pattern: indexPattern, + map_field_to: 'cloud.instance.id', + id_type: 'cloud', + interval: '>=5m', + time_field: timeField, + type: 'timeseries', + series: [ + { + id: 'writes', + metrics: [ + { + field: 'aws.ec2.diskio.write.bytes', + id: 'sum-diskio-out', + type: 'sum', + }, + { + id: 'csum-sum-diskio-out', + field: 'sum-diskio-out', + type: 'cumulative_sum', + }, + { + id: 'deriv-csum-sum-diskio-out', + unit: '1s', + type: 'derivative', + field: 'csum-sum-diskio-out', + }, + { + id: 'posonly-deriv-csum-sum-diskio-out', + field: 'deriv-csum-sum-diskio-out', + type: 'positive_only', + }, + ], + split_mode: 'everything', + }, + { + id: 'reads', + metrics: [ + { + field: 'aws.ec2.diskio.read.bytes', + id: 'sum-diskio-in', + type: 'sum', + }, + { + id: 'csum-sum-diskio-in', + field: 'sum-diskio-in', + type: 'cumulative_sum', + }, + { + id: 'deriv-csum-sum-diskio-in', + unit: '1s', + type: 'derivative', + field: 'csum-sum-diskio-in', + }, + { + id: 'posonly-deriv-csum-sum-diskio-in', + field: 'deriv-csum-sum-diskio-in', + type: 'positive_only', + }, + { + id: 'inverted-posonly-deriv-csum-sum-diskio-in', + type: 'calculation', + variables: [{ id: 'var-rate', name: 'rate', field: 'posonly-deriv-csum-sum-diskio-in' }], + script: 'params.rate * -1', + }, + ], + split_mode: 'everything', + }, + ], +}); diff --git a/x-pack/plugins/metrics_data_access/common/inventory_models/shared/metrics/tsvb/aws_diskio_ops.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/shared/metrics/tsvb/aws_diskio_ops.ts new file mode 100644 index 0000000000000..c362a6d88c27a --- /dev/null +++ b/x-pack/plugins/metrics_data_access/common/inventory_models/shared/metrics/tsvb/aws_diskio_ops.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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { TSVBMetricModelCreator, TSVBMetricModel } from '../../../types'; + +export const awsDiskioOps: TSVBMetricModelCreator = (timeField, indexPattern): TSVBMetricModel => ({ + id: 'awsDiskioOps', + requires: ['aws.ec2'], + index_pattern: indexPattern, + map_field_to: 'cloud.instance.id', + id_type: 'cloud', + interval: '>=5m', + time_field: timeField, + type: 'timeseries', + series: [ + { + id: 'writes', + metrics: [ + { + field: 'aws.ec2.diskio.write.count', + id: 'sum-diskio-writes', + type: 'sum', + }, + { + id: 'csum-sum-diskio-writes', + field: 'sum-diskio-writes', + type: 'cumulative_sum', + }, + { + id: 'deriv-csum-sum-diskio-writes', + unit: '1s', + type: 'derivative', + field: 'csum-sum-diskio-writes', + }, + { + id: 'posonly-deriv-csum-sum-diskio-writes', + field: 'deriv-csum-sum-diskio-writes', + type: 'positive_only', + }, + ], + split_mode: 'everything', + }, + { + id: 'reads', + metrics: [ + { + field: 'aws.ec2.diskio.read.count', + id: 'sum-diskio-reads', + type: 'sum', + }, + { + id: 'csum-sum-diskio-reads', + field: 'sum-diskio-reads', + type: 'cumulative_sum', + }, + { + id: 'deriv-csum-sum-diskio-reads', + unit: '1s', + type: 'derivative', + field: 'csum-sum-diskio-reads', + }, + { + id: 'posonly-deriv-csum-sum-diskio-reads', + field: 'deriv-csum-sum-diskio-reads', + type: 'positive_only', + }, + { + id: 'inverted-posonly-deriv-csum-sum-diskio-reads', + type: 'calculation', + variables: [ + { id: 'var-rate', name: 'rate', field: 'posonly-deriv-csum-sum-diskio-reads' }, + ], + script: 'params.rate * -1', + }, + ], + split_mode: 'everything', + }, + ], +}); diff --git a/x-pack/plugins/metrics_data_access/common/inventory_models/shared/metrics/tsvb/aws_network_bytes.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/shared/metrics/tsvb/aws_network_bytes.ts new file mode 100644 index 0000000000000..b142feb95450c --- /dev/null +++ b/x-pack/plugins/metrics_data_access/common/inventory_models/shared/metrics/tsvb/aws_network_bytes.ts @@ -0,0 +1,86 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { TSVBMetricModelCreator, TSVBMetricModel } from '../../../types'; + +// see discussion in: https://github.com/elastic/kibana/issues/42687 + +export const awsNetworkBytes: TSVBMetricModelCreator = ( + timeField, + indexPattern +): TSVBMetricModel => ({ + id: 'awsNetworkBytes', + requires: ['aws.ec2'], + index_pattern: indexPattern, + map_field_to: 'cloud.instance.id', + id_type: 'cloud', + interval: '>=5m', + time_field: timeField, + type: 'timeseries', + series: [ + { + id: 'tx', + metrics: [ + { + field: 'aws.ec2.network.out.bytes', + id: 'sum-net-out', + type: 'sum', + }, + { + id: 'csum-sum-net-out', + field: 'sum-net-out', + type: 'cumulative_sum', + }, + { + id: 'deriv-csum-sum-net-out', + unit: '1s', + type: 'derivative', + field: 'csum-sum-net-out', + }, + { + id: 'posonly-deriv-csum-sum-net-out', + field: 'deriv-csum-sum-net-out', + type: 'positive_only', + }, + ], + split_mode: 'everything', + }, + { + id: 'rx', + metrics: [ + { + field: 'aws.ec2.network.in.bytes', + id: 'sum-net-in', + type: 'sum', + }, + { + id: 'csum-sum-net-in', + field: 'sum-net-in', + type: 'cumulative_sum', + }, + { + id: 'deriv-csum-sum-net-in', + unit: '1s', + type: 'derivative', + field: 'csum-sum-net-in', + }, + { + id: 'posonly-deriv-csum-sum-net-in', + field: 'deriv-csum-sum-net-in', + type: 'positive_only', + }, + { + id: 'inverted-posonly-deriv-csum-sum-net-in', + type: 'calculation', + variables: [{ id: 'var-rate', name: 'rate', field: 'posonly-deriv-csum-sum-net-in' }], + script: 'params.rate * -1', + }, + ], + split_mode: 'everything', + }, + ], +}); diff --git a/x-pack/plugins/metrics_data_access/common/inventory_models/shared/metrics/tsvb/aws_network_packets.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/shared/metrics/tsvb/aws_network_packets.ts new file mode 100644 index 0000000000000..9d39582b66864 --- /dev/null +++ b/x-pack/plugins/metrics_data_access/common/inventory_models/shared/metrics/tsvb/aws_network_packets.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 { TSVBMetricModelCreator, TSVBMetricModel } from '../../../types'; + +export const awsNetworkPackets: TSVBMetricModelCreator = ( + timeField, + indexPattern +): TSVBMetricModel => ({ + id: 'awsNetworkPackets', + requires: ['aws.ec2'], + index_pattern: indexPattern, + map_field_to: 'cloud.instance.id', + id_type: 'cloud', + interval: '>=5m', + time_field: timeField, + type: 'timeseries', + series: [ + { + id: 'packets-out', + metrics: [ + { + field: 'aws.ec2.network.out.packets', + id: 'avg-net-out', + type: 'avg', + }, + ], + split_mode: 'everything', + }, + { + id: 'packets-in', + metrics: [ + { + field: 'aws.ec2.network.in.packets', + id: 'avg-net-in', + type: 'avg', + }, + { + id: 'inverted-avg-net-in', + type: 'calculation', + variables: [{ id: 'var-avg', name: 'avg', field: 'avg-net-in' }], + script: 'params.avg * -1', + }, + ], + split_mode: 'everything', + }, + ], +}); diff --git a/x-pack/plugins/metrics_data_access/common/inventory_models/shared/metrics/tsvb/aws_overview.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/shared/metrics/tsvb/aws_overview.ts new file mode 100644 index 0000000000000..3fe12d62d3352 --- /dev/null +++ b/x-pack/plugins/metrics_data_access/common/inventory_models/shared/metrics/tsvb/aws_overview.ts @@ -0,0 +1,65 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { TSVBMetricModelCreator, TSVBMetricModel } from '../../../types'; + +export const awsOverview: TSVBMetricModelCreator = (timeField, indexPattern): TSVBMetricModel => ({ + id: 'awsOverview', + requires: ['aws.ec2'], + index_pattern: indexPattern, + map_field_to: 'cloud.instance.id', + id_type: 'cloud', + interval: '>=5m', + time_field: timeField, + type: 'top_n', + series: [ + { + id: 'cpu-util', + split_mode: 'everything', + metrics: [ + { + field: 'aws.ec2.cpu.total.pct', + id: 'cpu-total-pct', + type: 'max', + }, + ], + }, + { + id: 'status-check-failed', + split_mode: 'everything', + metrics: [ + { + field: 'aws.ec2.status.check_failed', + id: 'status-check-failed', + type: 'max', + }, + ], + }, + { + id: 'packets-out', + split_mode: 'everything', + metrics: [ + { + field: 'aws.ec2.network.out.packets', + id: 'network-out-packets', + type: 'avg', + }, + ], + }, + { + id: 'packets-in', + split_mode: 'everything', + metrics: [ + { + field: 'aws.ec2.network.in.packets', + id: 'network-in-packets', + type: 'avg', + }, + ], + }, + ], +}); diff --git a/x-pack/plugins/infra/common/inventory_models/shared/metrics/tsvb/nginx_active_connections.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/shared/metrics/tsvb/nginx_active_connections.ts similarity index 100% rename from x-pack/plugins/infra/common/inventory_models/shared/metrics/tsvb/nginx_active_connections.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/shared/metrics/tsvb/nginx_active_connections.ts diff --git a/x-pack/plugins/infra/common/inventory_models/shared/metrics/tsvb/nginx_hits.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/shared/metrics/tsvb/nginx_hits.ts similarity index 100% rename from x-pack/plugins/infra/common/inventory_models/shared/metrics/tsvb/nginx_hits.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/shared/metrics/tsvb/nginx_hits.ts diff --git a/x-pack/plugins/infra/common/inventory_models/shared/metrics/tsvb/nginx_request_rate.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/shared/metrics/tsvb/nginx_request_rate.ts similarity index 100% rename from x-pack/plugins/infra/common/inventory_models/shared/metrics/tsvb/nginx_request_rate.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/shared/metrics/tsvb/nginx_request_rate.ts diff --git a/x-pack/plugins/infra/common/inventory_models/shared/metrics/tsvb/nginx_requests_per_connection.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/shared/metrics/tsvb/nginx_requests_per_connection.ts similarity index 100% rename from x-pack/plugins/infra/common/inventory_models/shared/metrics/tsvb/nginx_requests_per_connection.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/shared/metrics/tsvb/nginx_requests_per_connection.ts diff --git a/x-pack/plugins/infra/common/inventory_models/types.ts b/x-pack/plugins/metrics_data_access/common/inventory_models/types.ts similarity index 93% rename from x-pack/plugins/infra/common/inventory_models/types.ts rename to x-pack/plugins/metrics_data_access/common/inventory_models/types.ts index fd52c1c230c17..5bc36429e2ba2 100644 --- a/x-pack/plugins/infra/common/inventory_models/types.ts +++ b/x-pack/plugins/metrics_data_access/common/inventory_models/types.ts @@ -37,6 +37,21 @@ export type InventoryFormatterType = rt.TypeOf; export type InventoryItemType = rt.TypeOf; export const InventoryMetricRT = rt.keyof({ + hostSystemOverview: null, + hostCpuUsage: null, + hostFilesystem: null, + hostK8sOverview: null, + hostK8sCpuCap: null, + hostK8sDiskCap: null, + hostK8sMemoryCap: null, + hostK8sPodCap: null, + hostLoad: null, + hostMemoryUsage: null, + hostNetworkTraffic: null, + hostDockerOverview: null, + hostDockerInfo: null, + hostDockerTop5ByCpu: null, + hostDockerTop5ByMemory: null, podOverview: null, podCpuUsage: null, podMemoryUsage: null, @@ -56,6 +71,12 @@ export const InventoryMetricRT = rt.keyof({ nginxRequestRate: null, nginxActiveConnections: null, nginxRequestsPerConnection: null, + awsOverview: null, + awsCpuUtilization: null, + awsNetworkBytes: null, + awsNetworkPackets: null, + awsDiskioBytes: null, + awsDiskioOps: null, awsEC2CpuUtilization: null, awsEC2NetworkTraffic: null, awsEC2DiskIOBytes: null, @@ -356,7 +377,7 @@ export const SnapshotMetricTypeRT = rt.keyof(SnapshotMetricTypeKeys); export type SnapshotMetricType = rt.TypeOf; export interface InventoryMetrics { - tsvb?: { [name: string]: TSVBMetricModelCreator }; + tsvb: { [name: string]: TSVBMetricModelCreator }; snapshot: { [name: string]: MetricsUIAggregation | undefined }; defaultSnapshot: SnapshotMetricType; /** This is used by the inventory view to calculate the appropriate amount of time for the metrics detail page. Some metris like awsS3 require multiple days where others like host only need an hour.*/ @@ -382,7 +403,7 @@ export interface InventoryModel { uptime: boolean; }; metrics: InventoryMetrics; - requiredMetrics?: InventoryMetric[]; + requiredMetrics: InventoryMetric[]; tooltipMetrics: SnapshotMetricType[]; nodeFilter?: object[]; } diff --git a/x-pack/plugins/metrics_data_access/common/metrics_explorer_views/types.ts b/x-pack/plugins/metrics_data_access/common/metrics_explorer_views/types.ts new file mode 100644 index 0000000000000..46e18753c8a6f --- /dev/null +++ b/x-pack/plugins/metrics_data_access/common/metrics_explorer_views/types.ts @@ -0,0 +1,136 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { isoToEpochRt, nonEmptyStringRt } from '@kbn/io-ts-utils'; +import * as rt from 'io-ts'; +import { Color } from '../color_palette'; +import { + metricsExplorerAggregationRT, + metricsExplorerMetricRT, +} from '../http_api/metrics_explorer'; + +export const inventorySortOptionRT = rt.type({ + by: rt.keyof({ name: null, value: null }), + direction: rt.keyof({ asc: null, desc: null }), +}); + +export enum MetricsExplorerChartType { + line = 'line', + area = 'area', + bar = 'bar', +} + +export enum MetricsExplorerYAxisMode { + fromZero = 'fromZero', + auto = 'auto', +} + +export const metricsExplorerChartOptionsRT = rt.type({ + yAxisMode: rt.keyof( + Object.fromEntries(Object.values(MetricsExplorerYAxisMode).map((v) => [v, null])) as Record< + MetricsExplorerYAxisMode, + null + > + ), + type: rt.keyof( + Object.fromEntries(Object.values(MetricsExplorerChartType).map((v) => [v, null])) as Record< + MetricsExplorerChartType, + null + > + ), + stack: rt.boolean, +}); + +export const metricsExplorerTimeOptionsRT = rt.type({ + from: rt.string, + to: rt.string, + interval: rt.string, +}); +const metricsExplorerOptionsMetricRT = rt.intersection([ + metricsExplorerMetricRT, + rt.partial({ + rate: rt.boolean, + color: rt.keyof( + Object.fromEntries(Object.values(Color).map((c) => [c, null])) as Record + ), + label: rt.string, + }), +]); + +export const metricExplorerOptionsRequiredRT = rt.type({ + aggregation: metricsExplorerAggregationRT, + metrics: rt.array(metricsExplorerOptionsMetricRT), +}); + +export const metricExplorerOptionsOptionalRT = rt.partial({ + limit: rt.number, + groupBy: rt.union([rt.string, rt.array(rt.string)]), + filterQuery: rt.string, + source: rt.string, + forceInterval: rt.boolean, + dropLastBucket: rt.boolean, +}); +export const metricsExplorerOptionsRT = rt.intersection([ + metricExplorerOptionsRequiredRT, + metricExplorerOptionsOptionalRT, +]); + +export const metricExplorerViewStateRT = rt.type({ + chartOptions: metricsExplorerChartOptionsRT, + currentTimerange: metricsExplorerTimeOptionsRT, + options: metricsExplorerOptionsRT, +}); + +export const metricsExplorerViewBasicAttributesRT = rt.type({ + name: nonEmptyStringRt, +}); + +const metricsExplorerViewFlagsRT = rt.partial({ isDefault: rt.boolean, isStatic: rt.boolean }); + +export const metricsExplorerViewAttributesRT = rt.intersection([ + metricExplorerViewStateRT, + metricsExplorerViewBasicAttributesRT, + metricsExplorerViewFlagsRT, +]); + +const singleMetricsExplorerViewAttributesRT = rt.exact( + rt.intersection([metricsExplorerViewBasicAttributesRT, metricsExplorerViewFlagsRT]) +); + +export const metricsExplorerViewRT = rt.exact( + rt.intersection([ + rt.type({ + id: rt.string, + attributes: metricsExplorerViewAttributesRT, + }), + rt.partial({ + updatedAt: isoToEpochRt, + version: rt.string, + }), + ]) +); + +export const singleMetricsExplorerViewRT = rt.exact( + rt.intersection([ + rt.type({ + id: rt.string, + attributes: singleMetricsExplorerViewAttributesRT, + }), + rt.partial({ + updatedAt: isoToEpochRt, + version: rt.string, + }), + ]) +); + +export type MetricsExplorerChartOptions = rt.TypeOf; +export type MetricsExplorerOptions = rt.TypeOf; +export type MetricsExplorerOptionsMetric = rt.TypeOf; +export type MetricsExplorerViewState = rt.TypeOf; +export type MetricsExplorerTimeOptions = rt.TypeOf; +export type MetricsExplorerViewAttributes = rt.TypeOf; +export type MetricsExplorerView = rt.TypeOf; diff --git a/x-pack/plugins/metrics_data_access/common/runtime_types.ts b/x-pack/plugins/metrics_data_access/common/runtime_types.ts new file mode 100644 index 0000000000000..d6d0336eafdd7 --- /dev/null +++ b/x-pack/plugins/metrics_data_access/common/runtime_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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { fold } from 'fp-ts/lib/Either'; +import { identity } from 'fp-ts/lib/function'; +import { pipe } from 'fp-ts/lib/pipeable'; +import { Context, Errors, IntersectionType, Type, UnionType, ValidationError } from 'io-ts'; + +type ErrorFactory = (message: string) => Error; + +const getErrorPath = ([first, ...rest]: Context): string[] => { + if (typeof first === 'undefined') { + return []; + } else if (first.type instanceof IntersectionType) { + const [, ...next] = rest; + return getErrorPath(next); + } else if (first.type instanceof UnionType) { + const [, ...next] = rest; + return [first.key, ...getErrorPath(next)]; + } + + return [first.key, ...getErrorPath(rest)]; +}; + +const getErrorType = ({ context }: ValidationError) => + context[context.length - 1]?.type?.name ?? 'unknown'; + +const formatError = (error: ValidationError) => + error.message ?? + `in ${getErrorPath(error.context).join('/')}: ${JSON.stringify( + error.value + )} does not match expected type ${getErrorType(error)}`; + +export const formatErrors = (errors: ValidationError[]) => + `Failed to validate: \n${errors.map((error) => ` ${formatError(error)}`).join('\n')}`; + +export const createPlainError = (message: string) => new Error(message); + +export const throwErrors = (createError: ErrorFactory) => (errors: Errors) => { + throw createError(formatErrors(errors)); +}; + +export const decodeOrThrow = + ( + runtimeType: Type, + createError: ErrorFactory = createPlainError + ) => + (inputValue: InputValue) => + pipe(runtimeType.decode(inputValue), fold(throwErrors(createError), identity)); diff --git a/x-pack/plugins/metrics_data_access/common/utility_types.ts b/x-pack/plugins/metrics_data_access/common/utility_types.ts new file mode 100644 index 0000000000000..8c7280ff54a85 --- /dev/null +++ b/x-pack/plugins/metrics_data_access/common/utility_types.ts @@ -0,0 +1,52 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export type Pick2 = { + [P1 in K1]: { [P2 in K2]: T[K1][P2] }; +}; +export type Pick3 = { + [P1 in K1]: { [P2 in K2]: { [P3 in K3]: T[K1][K2][P3] } }; +}; + +export type MandatoryProperty = T & { + [prop in Prop]-?: NonNullable; +}; + +/** + * Portions of below code are derived from https://github.com/tycho01/typical + * under the MIT License + * + * Copyright (c) 2017 Thomas Crockett + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + */ + +export type DeepPartial = T extends any[] + ? DeepPartialArray + : T extends object + ? DeepPartialObject + : T; + +// eslint-disable-next-line @typescript-eslint/no-empty-interface +interface DeepPartialArray extends Array> {} + +type DeepPartialObject = { [P in keyof T]+?: DeepPartial }; + +export type ObjectValues = Array; + +export type ObjectEntry = [keyof T, T[keyof T]]; +export type ObjectEntries = Array>; + +export type UnwrapPromise> = T extends Promise ? Value : never; diff --git a/x-pack/plugins/metrics_data_access/kibana.jsonc b/x-pack/plugins/metrics_data_access/kibana.jsonc index 6c721fe1734c1..6842ec7d4a724 100644 --- a/x-pack/plugins/metrics_data_access/kibana.jsonc +++ b/x-pack/plugins/metrics_data_access/kibana.jsonc @@ -6,10 +6,15 @@ "plugin": { "id": "metricsDataAccess", "server": true, - "browser": false, + "browser": true, "configPath": ["xpack", "metrics_data_access"], - "requiredPlugins": [], - "requiredBundles": [], - "extraPublicDirs": [] + "requiredPlugins": [ + "data", + "observabilityShared" + ], + "requiredBundles": [ + "kibanaReact" + ], + "extraPublicDirs": ["common"] } } diff --git a/x-pack/plugins/metrics_data_access/public/apps/common_providers.tsx b/x-pack/plugins/metrics_data_access/public/apps/common_providers.tsx new file mode 100644 index 0000000000000..48f28bf895e19 --- /dev/null +++ b/x-pack/plugins/metrics_data_access/public/apps/common_providers.tsx @@ -0,0 +1,28 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { AppMountParameters, CoreStart } from '@kbn/core/public'; +import React from 'react'; +import { KibanaThemeProvider } from '@kbn/kibana-react-plugin/public'; +import { useKibanaContextForPluginProvider } from '../hooks/use_kibana'; + +export interface CoreProvidersProps { + core: CoreStart; + theme$: AppMountParameters['theme$']; +} + +export const CoreProviders: React.FC = ({ children, core, theme$ }) => { + const KibanaContextProviderForPlugin = useKibanaContextForPluginProvider(core); + + return ( + + + {children} + + + ); +}; diff --git a/x-pack/plugins/metrics_data_access/public/components/empty_states/index.tsx b/x-pack/plugins/metrics_data_access/public/components/empty_states/index.tsx new file mode 100644 index 0000000000000..e01b1c0ebdd0a --- /dev/null +++ b/x-pack/plugins/metrics_data_access/public/components/empty_states/index.tsx @@ -0,0 +1,11 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export * from './no_metric_indices'; +export { NoData } from './no_data'; +export { NoIndices } from './no_indices'; +export { NoRemoteCluster } from './no_remote_cluster'; diff --git a/x-pack/plugins/metrics_data_access/public/components/empty_states/no_data.tsx b/x-pack/plugins/metrics_data_access/public/components/empty_states/no_data.tsx new file mode 100644 index 0000000000000..0fc2af08d1e5f --- /dev/null +++ b/x-pack/plugins/metrics_data_access/public/components/empty_states/no_data.tsx @@ -0,0 +1,49 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { EuiButton, EuiEmptyPrompt } from '@elastic/eui'; +import React from 'react'; + +import { euiStyled } from '@kbn/kibana-react-plugin/common'; + +interface NoDataProps { + titleText: string; + bodyText: string; + refetchText: string; + onRefetch: () => void; + testString?: string; +} + +export const NoData: React.FC = ({ + titleText, + bodyText, + refetchText, + onRefetch, + testString, +}) => ( + {titleText}} + titleSize="m" + body={

{bodyText}

} + actions={ + + {refetchText} + + } + data-test-subj={testString} + /> +); + +const CenteredEmptyPrompt = euiStyled(EuiEmptyPrompt)` + align-self: center; +`; diff --git a/x-pack/plugins/metrics_data_access/public/components/empty_states/no_indices.tsx b/x-pack/plugins/metrics_data_access/public/components/empty_states/no_indices.tsx new file mode 100644 index 0000000000000..1ee82a9ad7cff --- /dev/null +++ b/x-pack/plugins/metrics_data_access/public/components/empty_states/no_indices.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 React from 'react'; +import styled from '@emotion/styled'; +import { EuiEmptyPromptProps } from '@elastic/eui'; +import { KibanaPageTemplate } from '@kbn/shared-ux-page-kibana-template'; + +interface NoIndicesProps extends Omit { + body: string; + title: string; +} + +// Represents a fully constructed page, including page template. +export const NoIndices: React.FC = ({ body, title, ...rest }) => { + return ( + {title}} + body={{body}} + {...rest} + /> + ); +}; + +const PreLineText = styled.p` + white-space: pre-line; +`; diff --git a/x-pack/plugins/metrics_data_access/public/components/empty_states/no_metric_indices.tsx b/x-pack/plugins/metrics_data_access/public/components/empty_states/no_metric_indices.tsx new file mode 100644 index 0000000000000..ce6d237567bda --- /dev/null +++ b/x-pack/plugins/metrics_data_access/public/components/empty_states/no_metric_indices.tsx @@ -0,0 +1,28 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { i18n } from '@kbn/i18n'; + +export const noMetricIndicesPromptPrimaryActionTitle = i18n.translate( + 'xpack.metricsData.metrics.noDataConfig.beatsCard.title', + { + defaultMessage: 'Add a metrics integration', + } +); + +export const noMetricIndicesPromptDescription = i18n.translate( + 'xpack.metricsData.metrics.noDataConfig.beatsCard.description', + { + defaultMessage: + 'Use Beats to send metrics data to Elasticsearch. We make it easy with modules for many popular systems and apps.', + } +); + +export const noMetricIndicesPromptTitle = i18n.translate( + 'xpack.metricsData.metrics.noDataConfig.promptTitle', + { defaultMessage: 'Add metrics data' } +); diff --git a/x-pack/plugins/metrics_data_access/public/components/empty_states/no_remote_cluster.tsx b/x-pack/plugins/metrics_data_access/public/components/empty_states/no_remote_cluster.tsx new file mode 100644 index 0000000000000..d2f84b42d38d5 --- /dev/null +++ b/x-pack/plugins/metrics_data_access/public/components/empty_states/no_remote_cluster.tsx @@ -0,0 +1,41 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { EuiButton } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { useLinkProps } from '@kbn/observability-shared-plugin/public'; +import { NoIndices } from './no_indices'; + +export const NoRemoteCluster = () => { + const settingLinkProps = useLinkProps({ app: 'metrics', pathname: '/settings' }); + + const goToSettings = ( + + {i18n.translate('xpack.metricsData.hostsPage.goToMetricsSettings', { + defaultMessage: 'Check settings', + })} + + ); + + return ( + + ); +}; diff --git a/x-pack/plugins/infra/public/components/infrastructure_node_metrics_tables/README.md b/x-pack/plugins/metrics_data_access/public/components/infrastructure_node_metrics_tables/README.md similarity index 100% rename from x-pack/plugins/infra/public/components/infrastructure_node_metrics_tables/README.md rename to x-pack/plugins/metrics_data_access/public/components/infrastructure_node_metrics_tables/README.md diff --git a/x-pack/plugins/infra/public/components/infrastructure_node_metrics_tables/container/container_metrics_table.stories.tsx b/x-pack/plugins/metrics_data_access/public/components/infrastructure_node_metrics_tables/container/container_metrics_table.stories.tsx similarity index 100% rename from x-pack/plugins/infra/public/components/infrastructure_node_metrics_tables/container/container_metrics_table.stories.tsx rename to x-pack/plugins/metrics_data_access/public/components/infrastructure_node_metrics_tables/container/container_metrics_table.stories.tsx diff --git a/x-pack/plugins/infra/public/components/infrastructure_node_metrics_tables/container/container_metrics_table.test.tsx b/x-pack/plugins/metrics_data_access/public/components/infrastructure_node_metrics_tables/container/container_metrics_table.test.tsx similarity index 76% rename from x-pack/plugins/infra/public/components/infrastructure_node_metrics_tables/container/container_metrics_table.test.tsx rename to x-pack/plugins/metrics_data_access/public/components/infrastructure_node_metrics_tables/container/container_metrics_table.test.tsx index 0698aa9d651da..41fea5a1cfa92 100644 --- a/x-pack/plugins/infra/public/components/infrastructure_node_metrics_tables/container/container_metrics_table.test.tsx +++ b/x-pack/plugins/metrics_data_access/public/components/infrastructure_node_metrics_tables/container/container_metrics_table.test.tsx @@ -5,23 +5,17 @@ * 2.0. */ -import type { HttpFetchOptions } from '@kbn/core/public'; import { MetricsExplorerSeries } from '../../../../common/http_api'; import { CoreProviders } from '../../../apps/common_providers'; import { render, screen, waitFor } from '@testing-library/react'; import React from 'react'; -import type { - DataResponseMock, - NodeMetricsTableFetchMock, - SourceResponseMock, -} from '../test_helpers'; -import { createStartServicesAccessorMock } from '../test_helpers'; +import { createStartServicesAccessorMock, createMetricsClientMock } from '../test_helpers'; import { ContainerMetricsTable } from './container_metrics_table'; import { createLazyContainerMetricsTable } from './create_lazy_container_metrics_table'; import IntegratedContainerMetricsTable from './integrated_container_metrics_table'; import { metricByField } from './use_container_metrics_table'; -jest.mock('../../../pages/link_to', () => ({ +jest.mock('../../../pages/link_to/use_node_details_redirect', () => ({ useNodeDetailsRedirect: jest.fn(() => ({ getNodeDetailUrl: jest.fn(() => ({ app: 'metrics', @@ -50,14 +44,24 @@ describe('ContainerMetricsTable', () => { }, }; - const fetchMock = createFetchMock(); + const mockData = { + series: [ + createContainer('some-container', 76, 3671700000), + createContainer('some-other-container', 67, 716300000), + ], + }; + const getMetricsClient = () => createMetricsClientMock(mockData); const loadingIndicatorTestId = 'metricsTableLoadingContent'; describe('createLazyContainerMetricsTable', () => { it('should lazily load and render the table', async () => { - const { fetch, getStartServices } = createStartServicesAccessorMock(fetchMock); - const LazyContainerMetricsTable = createLazyContainerMetricsTable(getStartServices); + const metricsClient = getMetricsClient(); + const { getStartServices } = createStartServicesAccessorMock(); + const LazyContainerMetricsTable = createLazyContainerMetricsTable( + getStartServices()[0], + metricsClient + ); render(); @@ -66,9 +70,15 @@ describe('ContainerMetricsTable', () => { // Using longer time out since resolving dynamic import can be slow // https://github.com/facebook/jest/issues/10933 - await waitFor(() => expect(fetch).toHaveBeenCalledTimes(2), { - timeout: 10000, - }); + await waitFor( + () => { + expect(metricsClient.metricsIndices).toHaveBeenCalledTimes(1); + expect(metricsClient.metricsExplorer).toHaveBeenCalledTimes(1); + }, + { + timeout: 10000, + } + ); expect(screen.queryByTestId(loadingIndicatorTestId)).not.toBeInTheDocument(); expect(screen.queryByTestId('containerMetricsTable')).toBeInTheDocument(); @@ -77,25 +87,30 @@ describe('ContainerMetricsTable', () => { describe('IntegratedContainerMetricsTable', () => { it('should render a single row of data', async () => { - const { coreProvidersPropsMock, fetch } = createStartServicesAccessorMock(fetchMock); + const { coreProvidersPropsMock } = createStartServicesAccessorMock(); + const metricsClient = getMetricsClient(); const { findByText } = render( ); - await waitFor(() => expect(fetch).toHaveBeenCalledTimes(2)); + await waitFor(() => { + expect(metricsClient.metricsIndices).toHaveBeenCalledTimes(1); + expect(metricsClient.metricsExplorer).toHaveBeenCalledTimes(1); + }); expect(await findByText(/some-container/)).toBeInTheDocument(); }); }); it('should render a loading indicator on first load', () => { - const { coreProvidersPropsMock } = createStartServicesAccessorMock(jest.fn()); + const { coreProvidersPropsMock } = createStartServicesAccessorMock(); const { queryByTestId } = render( @@ -114,7 +129,7 @@ describe('ContainerMetricsTable', () => { }); it('should render a prompt when indices are missing', () => { - const { coreProvidersPropsMock } = createStartServicesAccessorMock(jest.fn()); + const { coreProvidersPropsMock } = createStartServicesAccessorMock(); const { queryByTestId } = render( @@ -133,37 +148,6 @@ describe('ContainerMetricsTable', () => { }); }); -function createFetchMock(): NodeMetricsTableFetchMock { - const sourceMock: SourceResponseMock = { - source: { - configuration: { - metricAlias: 'some-index-pattern', - }, - status: { - metricIndicesExist: true, - }, - }, - }; - - const mockData: DataResponseMock = { - series: [ - createContainer('some-container', 76, 3671700000), - createContainer('some-other-container', 67, 716300000), - ], - }; - - return (path: string, _options: HttpFetchOptions) => { - // options can be used to read body for filter clause - if (path === '/api/metrics/source/default') { - return Promise.resolve(sourceMock); - } else if (path === '/api/infra/metrics_explorer') { - return Promise.resolve(mockData); - } - - throw new Error('Unexpected URL called in test'); - }; -} - function createContainer( name: string, cpuUsagePct: number, diff --git a/x-pack/plugins/infra/public/components/infrastructure_node_metrics_tables/container/container_metrics_table.tsx b/x-pack/plugins/metrics_data_access/public/components/infrastructure_node_metrics_tables/container/container_metrics_table.tsx similarity index 87% rename from x-pack/plugins/infra/public/components/infrastructure_node_metrics_tables/container/container_metrics_table.tsx rename to x-pack/plugins/metrics_data_access/public/components/infrastructure_node_metrics_tables/container/container_metrics_table.tsx index c4273733aacb9..9448c106b39ed 100644 --- a/x-pack/plugins/infra/public/components/infrastructure_node_metrics_tables/container/container_metrics_table.tsx +++ b/x-pack/plugins/metrics_data_access/public/components/infrastructure_node_metrics_tables/container/container_metrics_table.tsx @@ -78,7 +78,7 @@ export const ContainerMetricsTable = (props: ContainerMetricsTableProps) => { return ( <> { > { return [ { - name: i18n.translate('xpack.infra.metricsTable.container.idColumnHeader', { + name: i18n.translate('xpack.metricsData.metricsTable.container.idColumnHeader', { defaultMessage: 'Id', }), field: 'id', @@ -129,7 +132,7 @@ function containerNodeColumns( }, { name: i18n.translate( - 'xpack.infra.metricsTable.container.averageCpuUsagePercentColumnHeader', + 'xpack.metricsData.metricsTable.container.averageCpuUsagePercentColumnHeader', { defaultMessage: 'CPU usage (avg.)', } @@ -142,7 +145,7 @@ function containerNodeColumns( }, { name: i18n.translate( - 'xpack.infra.metricsTable.container.averageMemoryUsageMegabytesColumnHeader', + 'xpack.metricsData.metricsTable.container.averageMemoryUsageMegabytesColumnHeader', { defaultMessage: 'Memory usage(avg.)', } diff --git a/x-pack/plugins/infra/public/components/infrastructure_node_metrics_tables/container/create_lazy_container_metrics_table.tsx b/x-pack/plugins/metrics_data_access/public/components/infrastructure_node_metrics_tables/container/create_lazy_container_metrics_table.tsx similarity index 59% rename from x-pack/plugins/infra/public/components/infrastructure_node_metrics_tables/container/create_lazy_container_metrics_table.tsx rename to x-pack/plugins/metrics_data_access/public/components/infrastructure_node_metrics_tables/container/create_lazy_container_metrics_table.tsx index b88c6c17a0a0d..d187c88bcbba5 100644 --- a/x-pack/plugins/infra/public/components/infrastructure_node_metrics_tables/container/create_lazy_container_metrics_table.tsx +++ b/x-pack/plugins/metrics_data_access/public/components/infrastructure_node_metrics_tables/container/create_lazy_container_metrics_table.tsx @@ -5,28 +5,22 @@ * 2.0. */ +import { CoreStart } from '@kbn/core/public'; import React, { lazy, Suspense } from 'react'; -import { InfraClientStartServices } from '../../../types'; -import type { SourceProviderProps, UseNodeMetricsTableOptions } from '../shared'; +import { MetricsDataClient } from '../../../lib/metrics_client'; +import type { NodeMetricsTableProps } from '../shared'; const LazyIntegratedContainerMetricsTable = lazy( () => import('./integrated_container_metrics_table') ); -export function createLazyContainerMetricsTable(getStartServices: () => InfraClientStartServices) { - return ({ - timerange, - filterClauseDsl, - sourceId, - }: UseNodeMetricsTableOptions & Partial) => { - const [core, plugins, pluginStart] = getStartServices(); - +export function createLazyContainerMetricsTable(core: CoreStart, metricsClient: MetricsDataClient) { + return ({ timerange, filterClauseDsl, sourceId }: NodeMetricsTableProps) => { return ( ; } @@ -21,13 +28,16 @@ function ContainerMetricsTableWithProviders({ timerange, filterClauseDsl, sourceId, + metricsClient, ...coreProvidersProps }: IntegratedNodeMetricsTableProps) { return ( - - - + ); } diff --git a/x-pack/plugins/infra/public/components/infrastructure_node_metrics_tables/container/use_container_metrics_table.test.ts b/x-pack/plugins/metrics_data_access/public/components/infrastructure_node_metrics_tables/container/use_container_metrics_table.test.ts similarity index 93% rename from x-pack/plugins/infra/public/components/infrastructure_node_metrics_tables/container/use_container_metrics_table.test.ts rename to x-pack/plugins/metrics_data_access/public/components/infrastructure_node_metrics_tables/container/use_container_metrics_table.test.ts index 97044636cc7a1..ec22fe1df6f91 100644 --- a/x-pack/plugins/infra/public/components/infrastructure_node_metrics_tables/container/use_container_metrics_table.test.ts +++ b/x-pack/plugins/metrics_data_access/public/components/infrastructure_node_metrics_tables/container/use_container_metrics_table.test.ts @@ -8,6 +8,7 @@ import { useContainerMetricsTable } from './use_container_metrics_table'; import { useInfrastructureNodeMetrics } from '../shared'; import { renderHook } from '@testing-library/react-hooks'; +import { createMetricsClientMock } from '../test_helpers'; jest.mock('../shared', () => ({ ...jest.requireActual('../shared'), @@ -36,6 +37,7 @@ describe('useContainerMetricsTable hook', () => { useContainerMetricsTable({ timerange: { from: 'now-30d', to: 'now' }, filterClauseDsl, + metricsClient: createMetricsClientMock({}), }) ); diff --git a/x-pack/plugins/infra/public/components/infrastructure_node_metrics_tables/container/use_container_metrics_table.ts b/x-pack/plugins/metrics_data_access/public/components/infrastructure_node_metrics_tables/container/use_container_metrics_table.ts similarity index 99% rename from x-pack/plugins/infra/public/components/infrastructure_node_metrics_tables/container/use_container_metrics_table.ts rename to x-pack/plugins/metrics_data_access/public/components/infrastructure_node_metrics_tables/container/use_container_metrics_table.ts index 5f60d1751ee96..62795c6f473d3 100644 --- a/x-pack/plugins/infra/public/components/infrastructure_node_metrics_tables/container/use_container_metrics_table.ts +++ b/x-pack/plugins/metrics_data_access/public/components/infrastructure_node_metrics_tables/container/use_container_metrics_table.ts @@ -55,6 +55,7 @@ export interface ContainerNodeMetricsRow { export function useContainerMetricsTable({ timerange, filterClauseDsl, + metricsClient, }: UseNodeMetricsTableOptions) { const [currentPageIndex, setCurrentPageIndex] = useState(0); const [sortState, setSortState] = useState>({ @@ -73,6 +74,7 @@ export function useContainerMetricsTable({ transform: seriesToContainerNodeMetricsRow, sortState, currentPageIndex, + metricsClient, }); return { diff --git a/x-pack/plugins/infra/public/components/infrastructure_node_metrics_tables/host/create_lazy_host_metrics_table.tsx b/x-pack/plugins/metrics_data_access/public/components/infrastructure_node_metrics_tables/host/create_lazy_host_metrics_table.tsx similarity index 58% rename from x-pack/plugins/infra/public/components/infrastructure_node_metrics_tables/host/create_lazy_host_metrics_table.tsx rename to x-pack/plugins/metrics_data_access/public/components/infrastructure_node_metrics_tables/host/create_lazy_host_metrics_table.tsx index 7041d7daeeb08..43cdda7ff777f 100644 --- a/x-pack/plugins/infra/public/components/infrastructure_node_metrics_tables/host/create_lazy_host_metrics_table.tsx +++ b/x-pack/plugins/metrics_data_access/public/components/infrastructure_node_metrics_tables/host/create_lazy_host_metrics_table.tsx @@ -5,26 +5,20 @@ * 2.0. */ +import { CoreStart } from '@kbn/core/public'; import React, { lazy, Suspense } from 'react'; -import { InfraClientStartServices } from '../../../types'; -import type { SourceProviderProps, UseNodeMetricsTableOptions } from '../shared'; +import { MetricsDataClient } from '../../../lib/metrics_client'; +import type { NodeMetricsTableProps } from '../shared'; const LazyIntegratedHostMetricsTable = lazy(() => import('./integrated_host_metrics_table')); -export function createLazyHostMetricsTable(getStartServices: () => InfraClientStartServices) { - return ({ - timerange, - filterClauseDsl, - sourceId, - }: UseNodeMetricsTableOptions & Partial) => { - const [core, plugins, pluginStart] = getStartServices(); - +export function createLazyHostMetricsTable(core: CoreStart, metricsClient: MetricsDataClient) { + return ({ timerange, filterClauseDsl, sourceId }: NodeMetricsTableProps) => { return ( ({ +jest.mock('../../../pages/link_to/use_node_details_redirect', () => ({ useNodeDetailsRedirect: jest.fn(() => ({ getNodeDetailUrl: jest.fn(() => ({ app: 'metrics', @@ -50,14 +44,21 @@ describe('HostMetricsTable', () => { }, }; - const fetchMock = createFetchMock(); + const mockData = { + series: [ + createHost('some-host', 6, 76, 3671700000, 24), + createHost('some-other-host', 12, 67, 7176300000, 42), + ], + }; + const getMetricsClient = () => createMetricsClientMock(mockData); const loadingIndicatorTestId = 'metricsTableLoadingContent'; describe('createLazyHostMetricsTable', () => { it('should lazily load and render the table', async () => { - const { fetch, getStartServices } = createStartServicesAccessorMock(fetchMock); - const LazyHostMetricsTable = createLazyHostMetricsTable(getStartServices); + const { getStartServices } = createStartServicesAccessorMock(); + const metricsClient = getMetricsClient(); + const LazyHostMetricsTable = createLazyHostMetricsTable(getStartServices()[0], metricsClient); render(); @@ -66,9 +67,15 @@ describe('HostMetricsTable', () => { // Using longer time out since resolving dynamic import can be slow // https://github.com/facebook/jest/issues/10933 - await waitFor(() => expect(fetch).toHaveBeenCalledTimes(2), { - timeout: 10000, - }); + await waitFor( + () => { + expect(metricsClient.metricsIndices).toHaveBeenCalledTimes(1); + expect(metricsClient.metricsExplorer).toHaveBeenCalledTimes(1); + }, + { + timeout: 10000, + } + ); expect(screen.queryByTestId(loadingIndicatorTestId)).not.toBeInTheDocument(); expect(screen.queryByTestId('hostMetricsTable')).toBeInTheDocument(); @@ -77,25 +84,30 @@ describe('HostMetricsTable', () => { describe('IntegratedHostMetricsTable', () => { it('should render a single row of data', async () => { - const { coreProvidersPropsMock, fetch } = createStartServicesAccessorMock(fetchMock); + const { coreProvidersPropsMock } = createStartServicesAccessorMock(); + const metricsClient = getMetricsClient(); const { findByText } = render( ); - await waitFor(() => expect(fetch).toHaveBeenCalledTimes(2)); + await waitFor(() => { + expect(metricsClient.metricsIndices).toHaveBeenCalledTimes(1); + expect(metricsClient.metricsExplorer).toHaveBeenCalledTimes(1); + }); expect(await findByText(/some-host/)).toBeInTheDocument(); }); }); it('should render a loading indicator on first load', () => { - const { coreProvidersPropsMock } = createStartServicesAccessorMock(jest.fn()); + const { coreProvidersPropsMock } = createStartServicesAccessorMock(); const { queryByTestId } = render( @@ -114,7 +126,7 @@ describe('HostMetricsTable', () => { }); it('should render a prompt when indices are missing', () => { - const { coreProvidersPropsMock } = createStartServicesAccessorMock(jest.fn()); + const { coreProvidersPropsMock } = createStartServicesAccessorMock(); const { queryByTestId } = render( @@ -133,37 +145,6 @@ describe('HostMetricsTable', () => { }); }); -function createFetchMock(): NodeMetricsTableFetchMock { - const sourceMock: SourceResponseMock = { - source: { - configuration: { - metricAlias: 'some-index-pattern', - }, - status: { - metricIndicesExist: true, - }, - }, - }; - - const mockData: DataResponseMock = { - series: [ - createHost('some-host', 6, 76, 3671700000, 24), - createHost('some-other-host', 12, 67, 7176300000, 42), - ], - }; - - return (path: string, _options: HttpFetchOptions) => { - // options can be used to read body for filter clause - if (path === '/api/metrics/source/default') { - return Promise.resolve(sourceMock); - } else if (path === '/api/infra/metrics_explorer') { - return Promise.resolve(mockData); - } - - throw new Error('Unexpected URL called in test'); - }; -} - function createHost( name: string, coreCount: number, diff --git a/x-pack/plugins/infra/public/components/infrastructure_node_metrics_tables/host/host_metrics_table.tsx b/x-pack/plugins/metrics_data_access/public/components/infrastructure_node_metrics_tables/host/host_metrics_table.tsx similarity index 84% rename from x-pack/plugins/infra/public/components/infrastructure_node_metrics_tables/host/host_metrics_table.tsx rename to x-pack/plugins/metrics_data_access/public/components/infrastructure_node_metrics_tables/host/host_metrics_table.tsx index 53e3576a732b0..17f142af87e79 100644 --- a/x-pack/plugins/infra/public/components/infrastructure_node_metrics_tables/host/host_metrics_table.tsx +++ b/x-pack/plugins/metrics_data_access/public/components/infrastructure_node_metrics_tables/host/host_metrics_table.tsx @@ -78,7 +78,7 @@ export const HostMetricsTable = (props: HostMetricsTableProps) => { return ( <> { > { return [ { - name: i18n.translate('xpack.infra.metricsTable.host.nameColumnHeader', { + name: i18n.translate('xpack.metricsData.metricsTable.host.nameColumnHeader', { defaultMessage: 'Name', }), field: 'name', @@ -126,7 +126,7 @@ function hostMetricsColumns( ), }, { - name: i18n.translate('xpack.infra.metricsTable.host.CpuCountColumnHeader', { + name: i18n.translate('xpack.metricsData.metricsTable.host.CpuCountColumnHeader', { defaultMessage: '# of CPUs', }), field: 'cpuCount', @@ -134,9 +134,12 @@ function hostMetricsColumns( render: (cpuCount: number) => , }, { - name: i18n.translate('xpack.infra.metricsTable.host.averageCpuUsagePercentColumnHeader', { - defaultMessage: 'CPU usage (avg.)', - }), + name: i18n.translate( + 'xpack.metricsData.metricsTable.host.averageCpuUsagePercentColumnHeader', + { + defaultMessage: 'CPU usage (avg.)', + } + ), field: 'averageCpuUsagePercent', align: 'right', render: (averageCpuUsagePercent: number) => ( @@ -144,7 +147,7 @@ function hostMetricsColumns( ), }, { - name: i18n.translate('xpack.infra.metricsTable.host.totalMemoryMegabytesColumnHeader', { + name: i18n.translate('xpack.metricsData.metricsTable.host.totalMemoryMegabytesColumnHeader', { defaultMessage: 'Memory total', }), field: 'totalMemoryMegabytes', @@ -154,9 +157,12 @@ function hostMetricsColumns( ), }, { - name: i18n.translate('xpack.infra.metricsTable.host.averageMemoryUsagePercentColumnHeader', { - defaultMessage: 'Memory usage (avg.)', - }), + name: i18n.translate( + 'xpack.metricsData.metricsTable.host.averageMemoryUsagePercentColumnHeader', + { + defaultMessage: 'Memory usage (avg.)', + } + ), field: 'averageMemoryUsagePercent', align: 'right', render: (averageMemoryUsagePercent: number) => ( diff --git a/x-pack/plugins/infra/public/components/infrastructure_node_metrics_tables/host/index.ts b/x-pack/plugins/metrics_data_access/public/components/infrastructure_node_metrics_tables/host/index.ts similarity index 100% rename from x-pack/plugins/infra/public/components/infrastructure_node_metrics_tables/host/index.ts rename to x-pack/plugins/metrics_data_access/public/components/infrastructure_node_metrics_tables/host/index.ts diff --git a/x-pack/plugins/infra/public/components/infrastructure_node_metrics_tables/host/integrated_host_metrics_table.tsx b/x-pack/plugins/metrics_data_access/public/components/infrastructure_node_metrics_tables/host/integrated_host_metrics_table.tsx similarity index 75% rename from x-pack/plugins/infra/public/components/infrastructure_node_metrics_tables/host/integrated_host_metrics_table.tsx rename to x-pack/plugins/metrics_data_access/public/components/infrastructure_node_metrics_tables/host/integrated_host_metrics_table.tsx index ca274a1ef805f..ff3a8d9220d94 100644 --- a/x-pack/plugins/infra/public/components/infrastructure_node_metrics_tables/host/integrated_host_metrics_table.tsx +++ b/x-pack/plugins/metrics_data_access/public/components/infrastructure_node_metrics_tables/host/integrated_host_metrics_table.tsx @@ -7,13 +7,16 @@ import React from 'react'; import { CoreProviders } from '../../../apps/common_providers'; -import { SourceProvider } from '../../../containers/metrics_source'; import type { IntegratedNodeMetricsTableProps, UseNodeMetricsTableOptions } from '../shared'; import { HostMetricsTable } from './host_metrics_table'; import { useHostMetricsTable } from './use_host_metrics_table'; -function HookedHostMetricsTable({ timerange, filterClauseDsl }: UseNodeMetricsTableOptions) { - const hostMetricsTableProps = useHostMetricsTable({ timerange, filterClauseDsl }); +function HookedHostMetricsTable({ + timerange, + filterClauseDsl, + metricsClient, +}: UseNodeMetricsTableOptions) { + const hostMetricsTableProps = useHostMetricsTable({ timerange, filterClauseDsl, metricsClient }); return ; } @@ -21,13 +24,16 @@ function HostMetricsTableWithProviders({ timerange, filterClauseDsl, sourceId, + metricsClient, ...coreProvidersProps }: IntegratedNodeMetricsTableProps) { return ( - - - + ); } diff --git a/x-pack/plugins/infra/public/components/infrastructure_node_metrics_tables/host/use_host_metrics_table.test.ts b/x-pack/plugins/metrics_data_access/public/components/infrastructure_node_metrics_tables/host/use_host_metrics_table.test.ts similarity index 93% rename from x-pack/plugins/infra/public/components/infrastructure_node_metrics_tables/host/use_host_metrics_table.test.ts rename to x-pack/plugins/metrics_data_access/public/components/infrastructure_node_metrics_tables/host/use_host_metrics_table.test.ts index 2956ed2d8bc87..f34fccc6e442e 100644 --- a/x-pack/plugins/infra/public/components/infrastructure_node_metrics_tables/host/use_host_metrics_table.test.ts +++ b/x-pack/plugins/metrics_data_access/public/components/infrastructure_node_metrics_tables/host/use_host_metrics_table.test.ts @@ -8,6 +8,7 @@ import { useHostMetricsTable } from './use_host_metrics_table'; import { useInfrastructureNodeMetrics } from '../shared'; import { renderHook } from '@testing-library/react-hooks'; +import { createMetricsClientMock } from '../test_helpers'; jest.mock('../shared', () => ({ ...jest.requireActual('../shared'), @@ -43,6 +44,7 @@ describe('useHostMetricsTable hook', () => { useHostMetricsTable({ timerange: { from: 'now-30d', to: 'now' }, filterClauseDsl, + metricsClient: createMetricsClientMock({}), }) ); diff --git a/x-pack/plugins/infra/public/components/infrastructure_node_metrics_tables/host/use_host_metrics_table.ts b/x-pack/plugins/metrics_data_access/public/components/infrastructure_node_metrics_tables/host/use_host_metrics_table.ts similarity index 97% rename from x-pack/plugins/infra/public/components/infrastructure_node_metrics_tables/host/use_host_metrics_table.ts rename to x-pack/plugins/metrics_data_access/public/components/infrastructure_node_metrics_tables/host/use_host_metrics_table.ts index 9492df0b533e6..a43c0c971010a 100644 --- a/x-pack/plugins/infra/public/components/infrastructure_node_metrics_tables/host/use_host_metrics_table.ts +++ b/x-pack/plugins/metrics_data_access/public/components/infrastructure_node_metrics_tables/host/use_host_metrics_table.ts @@ -58,7 +58,11 @@ export interface HostNodeMetricsRow { averageMemoryUsagePercent: number | null; } -export function useHostMetricsTable({ timerange, filterClauseDsl }: UseNodeMetricsTableOptions) { +export function useHostMetricsTable({ + timerange, + filterClauseDsl, + metricsClient, +}: UseNodeMetricsTableOptions) { const [currentPageIndex, setCurrentPageIndex] = useState(0); const [sortState, setSortState] = useState>({ field: 'averageCpuUsagePercent', @@ -76,6 +80,7 @@ export function useHostMetricsTable({ timerange, filterClauseDsl }: UseNodeMetri transform: seriesToHostNodeMetricsRow, sortState, currentPageIndex, + metricsClient, }); return { diff --git a/x-pack/plugins/infra/public/components/infrastructure_node_metrics_tables/index.ts b/x-pack/plugins/metrics_data_access/public/components/infrastructure_node_metrics_tables/index.ts similarity index 100% rename from x-pack/plugins/infra/public/components/infrastructure_node_metrics_tables/index.ts rename to x-pack/plugins/metrics_data_access/public/components/infrastructure_node_metrics_tables/index.ts diff --git a/x-pack/plugins/infra/public/components/infrastructure_node_metrics_tables/pod/create_lazy_pod_metrics_table.tsx b/x-pack/plugins/metrics_data_access/public/components/infrastructure_node_metrics_tables/pod/create_lazy_pod_metrics_table.tsx similarity index 58% rename from x-pack/plugins/infra/public/components/infrastructure_node_metrics_tables/pod/create_lazy_pod_metrics_table.tsx rename to x-pack/plugins/metrics_data_access/public/components/infrastructure_node_metrics_tables/pod/create_lazy_pod_metrics_table.tsx index b539bdec63621..ef96c255773f6 100644 --- a/x-pack/plugins/infra/public/components/infrastructure_node_metrics_tables/pod/create_lazy_pod_metrics_table.tsx +++ b/x-pack/plugins/metrics_data_access/public/components/infrastructure_node_metrics_tables/pod/create_lazy_pod_metrics_table.tsx @@ -5,26 +5,20 @@ * 2.0. */ +import { CoreStart } from '@kbn/core/public'; import React, { lazy, Suspense } from 'react'; -import { InfraClientStartServices } from '../../../types'; -import type { SourceProviderProps, UseNodeMetricsTableOptions } from '../shared'; +import { MetricsDataClient } from '../../../lib/metrics_client'; +import type { NodeMetricsTableProps } from '../shared'; const LazyIntegratedPodMetricsTable = lazy(() => import('./integrated_pod_metrics_table')); -export function createLazyPodMetricsTable(getStartServices: () => InfraClientStartServices) { - return ({ - timerange, - filterClauseDsl, - sourceId, - }: UseNodeMetricsTableOptions & Partial) => { - const [core, plugins, pluginStart] = getStartServices(); - +export function createLazyPodMetricsTable(core: CoreStart, metricsClient: MetricsDataClient) { + return ({ timerange, filterClauseDsl, sourceId }: NodeMetricsTableProps) => { return ( ; } @@ -21,13 +24,16 @@ function PodMetricsTableWithProviders({ timerange, filterClauseDsl, sourceId, + metricsClient, ...coreProvidersProps }: IntegratedNodeMetricsTableProps) { return ( - - - + ); } diff --git a/x-pack/plugins/infra/public/components/infrastructure_node_metrics_tables/pod/pod_metrics_table.stories.tsx b/x-pack/plugins/metrics_data_access/public/components/infrastructure_node_metrics_tables/pod/pod_metrics_table.stories.tsx similarity index 100% rename from x-pack/plugins/infra/public/components/infrastructure_node_metrics_tables/pod/pod_metrics_table.stories.tsx rename to x-pack/plugins/metrics_data_access/public/components/infrastructure_node_metrics_tables/pod/pod_metrics_table.stories.tsx diff --git a/x-pack/plugins/infra/public/components/infrastructure_node_metrics_tables/pod/pod_metrics_table.test.tsx b/x-pack/plugins/metrics_data_access/public/components/infrastructure_node_metrics_tables/pod/pod_metrics_table.test.tsx similarity index 76% rename from x-pack/plugins/infra/public/components/infrastructure_node_metrics_tables/pod/pod_metrics_table.test.tsx rename to x-pack/plugins/metrics_data_access/public/components/infrastructure_node_metrics_tables/pod/pod_metrics_table.test.tsx index 27f60b1906003..23399440d4096 100644 --- a/x-pack/plugins/infra/public/components/infrastructure_node_metrics_tables/pod/pod_metrics_table.test.tsx +++ b/x-pack/plugins/metrics_data_access/public/components/infrastructure_node_metrics_tables/pod/pod_metrics_table.test.tsx @@ -5,23 +5,17 @@ * 2.0. */ -import type { HttpFetchOptions } from '@kbn/core/public'; import { CoreProviders } from '../../../apps/common_providers'; import { render, screen, waitFor } from '@testing-library/react'; import React from 'react'; import type { MetricsExplorerSeries } from '../../../../common/http_api'; -import type { - DataResponseMock, - NodeMetricsTableFetchMock, - SourceResponseMock, -} from '../test_helpers'; -import { createStartServicesAccessorMock } from '../test_helpers'; +import { createStartServicesAccessorMock, createMetricsClientMock } from '../test_helpers'; import { createLazyPodMetricsTable } from './create_lazy_pod_metrics_table'; import IntegratedPodMetricsTable from './integrated_pod_metrics_table'; import { PodMetricsTable } from './pod_metrics_table'; import { metricByField } from './use_pod_metrics_table'; -jest.mock('../../../pages/link_to', () => ({ +jest.mock('../../../pages/link_to/use_node_details_redirect', () => ({ useNodeDetailsRedirect: jest.fn(() => ({ getNodeDetailUrl: jest.fn(() => ({ app: 'metrics', @@ -50,14 +44,21 @@ describe('PodMetricsTable', () => { }, }; - const fetchMock = createFetchMock(); + const mockData = { + series: [ + createPod('358d96e3-026f-4440-a487-f6c2301884c0', 'some-pod', 76, 3671700000), + createPod('358d96e3-026f-4440-a487-f6c2301884c1', 'some-other-pod', 67, 716300000), + ], + }; + const getMetricsClient = () => createMetricsClientMock(mockData); const loadingIndicatorTestId = 'metricsTableLoadingContent'; describe('createLazyPodMetricsTable', () => { it('should lazily load and render the table', async () => { - const { fetch, getStartServices } = createStartServicesAccessorMock(fetchMock); - const LazyPodMetricsTable = createLazyPodMetricsTable(getStartServices); + const { getStartServices } = createStartServicesAccessorMock(); + const metricsClient = getMetricsClient(); + const LazyPodMetricsTable = createLazyPodMetricsTable(getStartServices()[0], metricsClient); render(); @@ -66,9 +67,15 @@ describe('PodMetricsTable', () => { // Using longer time out since resolving dynamic import can be slow // https://github.com/facebook/jest/issues/10933 - await waitFor(() => expect(fetch).toHaveBeenCalledTimes(2), { - timeout: 10000, - }); + await waitFor( + () => { + expect(metricsClient.metricsIndices).toHaveBeenCalledTimes(1); + expect(metricsClient.metricsExplorer).toHaveBeenCalledTimes(1); + }, + { + timeout: 10000, + } + ); expect(screen.queryByTestId(loadingIndicatorTestId)).not.toBeInTheDocument(); expect(screen.queryByTestId('podMetricsTable')).toBeInTheDocument(); @@ -77,25 +84,30 @@ describe('PodMetricsTable', () => { describe('IntegratedPodMetricsTable', () => { it('should render a single row of data', async () => { - const { coreProvidersPropsMock, fetch } = createStartServicesAccessorMock(fetchMock); + const { coreProvidersPropsMock } = createStartServicesAccessorMock(); + const metricsClient = getMetricsClient(); const { findByText } = render( ); - await waitFor(() => expect(fetch).toHaveBeenCalledTimes(2)); + await waitFor(() => { + expect(metricsClient.metricsIndices).toHaveBeenCalledTimes(1); + expect(metricsClient.metricsExplorer).toHaveBeenCalledTimes(1); + }); expect(await findByText(/some-pod/)).toBeInTheDocument(); }); }); it('should render a loading indicator on first load', () => { - const { coreProvidersPropsMock } = createStartServicesAccessorMock(jest.fn()); + const { coreProvidersPropsMock } = createStartServicesAccessorMock(); const { queryByTestId } = render( @@ -114,7 +126,7 @@ describe('PodMetricsTable', () => { }); it('should render a prompt when indices are missing', () => { - const { coreProvidersPropsMock } = createStartServicesAccessorMock(jest.fn()); + const { coreProvidersPropsMock } = createStartServicesAccessorMock(); const { queryByTestId } = render( @@ -133,37 +145,6 @@ describe('PodMetricsTable', () => { }); }); -function createFetchMock(): NodeMetricsTableFetchMock { - const sourceMock: SourceResponseMock = { - source: { - configuration: { - metricAlias: 'some-index-pattern', - }, - status: { - metricIndicesExist: true, - }, - }, - }; - - const mockData: DataResponseMock = { - series: [ - createPod('358d96e3-026f-4440-a487-f6c2301884c0', 'some-pod', 76, 3671700000), - createPod('358d96e3-026f-4440-a487-f6c2301884c1', 'some-other-pod', 67, 716300000), - ], - }; - - return (path: string, _options: HttpFetchOptions) => { - // options can be used to read body for filter clause - if (path === '/api/metrics/source/default') { - return Promise.resolve(sourceMock); - } else if (path === '/api/infra/metrics_explorer') { - return Promise.resolve(mockData); - } - - throw new Error('Unexpected URL called in test'); - }; -} - function createPod( id: string, name: string, diff --git a/x-pack/plugins/infra/public/components/infrastructure_node_metrics_tables/pod/pod_metrics_table.tsx b/x-pack/plugins/metrics_data_access/public/components/infrastructure_node_metrics_tables/pod/pod_metrics_table.tsx similarity index 86% rename from x-pack/plugins/infra/public/components/infrastructure_node_metrics_tables/pod/pod_metrics_table.tsx rename to x-pack/plugins/metrics_data_access/public/components/infrastructure_node_metrics_tables/pod/pod_metrics_table.tsx index 22e6b6a27d214..ee3745e05f720 100644 --- a/x-pack/plugins/infra/public/components/infrastructure_node_metrics_tables/pod/pod_metrics_table.tsx +++ b/x-pack/plugins/metrics_data_access/public/components/infrastructure_node_metrics_tables/pod/pod_metrics_table.tsx @@ -76,7 +76,7 @@ export const PodMetricsTable = (props: PodMetricsTableProps) => { return ( <> { > { return [ { - name: i18n.translate('xpack.infra.metricsTable.pod.nameColumnHeader', { + name: i18n.translate('xpack.metricsData.metricsTable.pod.nameColumnHeader', { defaultMessage: 'Name', }), field: 'name', @@ -126,9 +126,12 @@ function podNodeColumns( }, }, { - name: i18n.translate('xpack.infra.metricsTable.pod.averageCpuUsagePercentColumnHeader', { - defaultMessage: 'CPU usage (avg.)', - }), + name: i18n.translate( + 'xpack.metricsData.metricsTable.pod.averageCpuUsagePercentColumnHeader', + { + defaultMessage: 'CPU usage (avg.)', + } + ), field: 'averageCpuUsagePercent', align: 'right', render: (averageCpuUsagePercent: number) => ( @@ -136,9 +139,12 @@ function podNodeColumns( ), }, { - name: i18n.translate('xpack.infra.metricsTable.pod.averageMemoryUsageMegabytesColumnHeader', { - defaultMessage: 'Memory usage (avg.)', - }), + name: i18n.translate( + 'xpack.metricsData.metricsTable.pod.averageMemoryUsageMegabytesColumnHeader', + { + defaultMessage: 'Memory usage (avg.)', + } + ), field: 'averageMemoryUsageMegabytes', align: 'right', render: (averageMemoryUsageMegabytes: number) => ( diff --git a/x-pack/plugins/infra/public/components/infrastructure_node_metrics_tables/pod/use_pod_metrics_table.test.ts b/x-pack/plugins/metrics_data_access/public/components/infrastructure_node_metrics_tables/pod/use_pod_metrics_table.test.ts similarity index 93% rename from x-pack/plugins/infra/public/components/infrastructure_node_metrics_tables/pod/use_pod_metrics_table.test.ts rename to x-pack/plugins/metrics_data_access/public/components/infrastructure_node_metrics_tables/pod/use_pod_metrics_table.test.ts index d7edd86771ed7..fc6d14b03d08b 100644 --- a/x-pack/plugins/infra/public/components/infrastructure_node_metrics_tables/pod/use_pod_metrics_table.test.ts +++ b/x-pack/plugins/metrics_data_access/public/components/infrastructure_node_metrics_tables/pod/use_pod_metrics_table.test.ts @@ -8,6 +8,7 @@ import { usePodMetricsTable } from './use_pod_metrics_table'; import { useInfrastructureNodeMetrics } from '../shared'; import { renderHook } from '@testing-library/react-hooks'; +import { createMetricsClientMock } from '../test_helpers'; jest.mock('../shared', () => ({ ...jest.requireActual('../shared'), @@ -36,6 +37,7 @@ describe('usePodMetricsTable hook', () => { usePodMetricsTable({ timerange: { from: 'now-30d', to: 'now' }, filterClauseDsl, + metricsClient: createMetricsClientMock({}), }) ); diff --git a/x-pack/plugins/infra/public/components/infrastructure_node_metrics_tables/pod/use_pod_metrics_table.ts b/x-pack/plugins/metrics_data_access/public/components/infrastructure_node_metrics_tables/pod/use_pod_metrics_table.ts similarity index 97% rename from x-pack/plugins/infra/public/components/infrastructure_node_metrics_tables/pod/use_pod_metrics_table.ts rename to x-pack/plugins/metrics_data_access/public/components/infrastructure_node_metrics_tables/pod/use_pod_metrics_table.ts index bec98ebcc6d18..1dbc584996502 100644 --- a/x-pack/plugins/infra/public/components/infrastructure_node_metrics_tables/pod/use_pod_metrics_table.ts +++ b/x-pack/plugins/metrics_data_access/public/components/infrastructure_node_metrics_tables/pod/use_pod_metrics_table.ts @@ -51,7 +51,11 @@ export interface PodNodeMetricsRow { averageMemoryUsageMegabytes: number | null; } -export function usePodMetricsTable({ timerange, filterClauseDsl }: UseNodeMetricsTableOptions) { +export function usePodMetricsTable({ + timerange, + filterClauseDsl, + metricsClient, +}: UseNodeMetricsTableOptions) { const [currentPageIndex, setCurrentPageIndex] = useState(0); const [sortState, setSortState] = useState>({ field: 'averageCpuUsagePercent', @@ -69,6 +73,7 @@ export function usePodMetricsTable({ timerange, filterClauseDsl }: UseNodeMetric transform: seriesToPodNodeMetricsRow, sortState, currentPageIndex, + metricsClient, }); return { diff --git a/x-pack/plugins/infra/public/components/infrastructure_node_metrics_tables/shared/components/assets/no_results_dark.svg b/x-pack/plugins/metrics_data_access/public/components/infrastructure_node_metrics_tables/shared/components/assets/no_results_dark.svg similarity index 100% rename from x-pack/plugins/infra/public/components/infrastructure_node_metrics_tables/shared/components/assets/no_results_dark.svg rename to x-pack/plugins/metrics_data_access/public/components/infrastructure_node_metrics_tables/shared/components/assets/no_results_dark.svg diff --git a/x-pack/plugins/infra/public/components/infrastructure_node_metrics_tables/shared/components/assets/no_results_light.svg b/x-pack/plugins/metrics_data_access/public/components/infrastructure_node_metrics_tables/shared/components/assets/no_results_light.svg similarity index 100% rename from x-pack/plugins/infra/public/components/infrastructure_node_metrics_tables/shared/components/assets/no_results_light.svg rename to x-pack/plugins/metrics_data_access/public/components/infrastructure_node_metrics_tables/shared/components/assets/no_results_light.svg diff --git a/x-pack/plugins/infra/public/components/infrastructure_node_metrics_tables/shared/components/error_content.tsx b/x-pack/plugins/metrics_data_access/public/components/infrastructure_node_metrics_tables/shared/components/error_content.tsx similarity index 100% rename from x-pack/plugins/infra/public/components/infrastructure_node_metrics_tables/shared/components/error_content.tsx rename to x-pack/plugins/metrics_data_access/public/components/infrastructure_node_metrics_tables/shared/components/error_content.tsx diff --git a/x-pack/plugins/infra/public/components/infrastructure_node_metrics_tables/shared/components/index.ts b/x-pack/plugins/metrics_data_access/public/components/infrastructure_node_metrics_tables/shared/components/index.ts similarity index 100% rename from x-pack/plugins/infra/public/components/infrastructure_node_metrics_tables/shared/components/index.ts rename to x-pack/plugins/metrics_data_access/public/components/infrastructure_node_metrics_tables/shared/components/index.ts diff --git a/x-pack/plugins/infra/public/components/infrastructure_node_metrics_tables/shared/components/metrics_node_details_link.tsx b/x-pack/plugins/metrics_data_access/public/components/infrastructure_node_metrics_tables/shared/components/metrics_node_details_link.tsx similarity index 83% rename from x-pack/plugins/infra/public/components/infrastructure_node_metrics_tables/shared/components/metrics_node_details_link.tsx rename to x-pack/plugins/metrics_data_access/public/components/infrastructure_node_metrics_tables/shared/components/metrics_node_details_link.tsx index 59a9cad5d672f..10ecf3dc42626 100644 --- a/x-pack/plugins/infra/public/components/infrastructure_node_metrics_tables/shared/components/metrics_node_details_link.tsx +++ b/x-pack/plugins/metrics_data_access/public/components/infrastructure_node_metrics_tables/shared/components/metrics_node_details_link.tsx @@ -10,8 +10,7 @@ import { EuiLink } from '@elastic/eui'; import React from 'react'; import { useLinkProps } from '@kbn/observability-shared-plugin/public'; import type { InventoryItemType } from '../../../../../common/inventory_models/types'; -import { useNodeDetailsRedirect } from '../../../../pages/link_to'; -import type { MetricsExplorerTimeOptions } from '../../../../pages/metrics/metrics_explorer/hooks/use_metrics_explorer_options'; +import { useNodeDetailsRedirect } from '../../../../pages/link_to/use_node_details_redirect'; type ExtractStrict = Extract; @@ -19,7 +18,7 @@ interface MetricsNodeDetailsLinkProps { id: string; label: string; nodeType: ExtractStrict; - timerange: Pick; + timerange: { from: string; to: string }; } export const MetricsNodeDetailsLink = ({ @@ -31,12 +30,11 @@ export const MetricsNodeDetailsLink = ({ const { getNodeDetailUrl } = useNodeDetailsRedirect(); const linkProps = useLinkProps( getNodeDetailUrl({ - assetType: nodeType, - assetId: id, + nodeType, + nodeId: id, search: { from: parse(timerange.from)?.valueOf(), to: parse(timerange.to)?.valueOf(), - name: id, }, }) ); diff --git a/x-pack/plugins/infra/public/components/infrastructure_node_metrics_tables/shared/components/no_data_content.tsx b/x-pack/plugins/metrics_data_access/public/components/infrastructure_node_metrics_tables/shared/components/no_data_content.tsx similarity index 86% rename from x-pack/plugins/infra/public/components/infrastructure_node_metrics_tables/shared/components/no_data_content.tsx rename to x-pack/plugins/metrics_data_access/public/components/infrastructure_node_metrics_tables/shared/components/no_data_content.tsx index 4b1eea3fe03d1..1fd0622aa26cc 100644 --- a/x-pack/plugins/infra/public/components/infrastructure_node_metrics_tables/shared/components/no_data_content.tsx +++ b/x-pack/plugins/metrics_data_access/public/components/infrastructure_node_metrics_tables/shared/components/no_data_content.tsx @@ -35,7 +35,7 @@ export const MetricsTableLoadingContent = () => ( title={

@@ -73,25 +73,25 @@ export const MetricsTableEmptyIndicesContent = () => { @@ -104,7 +104,7 @@ export const MetricsTableEmptyIndicesContent = () => { title={

@@ -128,6 +128,6 @@ const NoResultsIllustration = () => { }; const noResultsIllustrationAlternativeText = i18n.translate( - 'xpack.infra.metricsTable.noResultsIllustrationAlternativeText', + 'xpack.metricsData.metricsTable.noResultsIllustrationAlternativeText', { defaultMessage: 'A magnifying glass with an exclamation mark' } ); diff --git a/x-pack/plugins/infra/public/components/infrastructure_node_metrics_tables/shared/components/number_cell.tsx b/x-pack/plugins/metrics_data_access/public/components/infrastructure_node_metrics_tables/shared/components/number_cell.tsx similarity index 92% rename from x-pack/plugins/infra/public/components/infrastructure_node_metrics_tables/shared/components/number_cell.tsx rename to x-pack/plugins/metrics_data_access/public/components/infrastructure_node_metrics_tables/shared/components/number_cell.tsx index 77898a08268a0..d52f23f4c2b45 100644 --- a/x-pack/plugins/infra/public/components/infrastructure_node_metrics_tables/shared/components/number_cell.tsx +++ b/x-pack/plugins/metrics_data_access/public/components/infrastructure_node_metrics_tables/shared/components/number_cell.tsx @@ -19,7 +19,7 @@ export function NumberCell({ value, unit }: NumberCellProps) { return ( diff --git a/x-pack/plugins/infra/public/components/infrastructure_node_metrics_tables/shared/components/stepwise_pagination.tsx b/x-pack/plugins/metrics_data_access/public/components/infrastructure_node_metrics_tables/shared/components/stepwise_pagination.tsx similarity index 100% rename from x-pack/plugins/infra/public/components/infrastructure_node_metrics_tables/shared/components/stepwise_pagination.tsx rename to x-pack/plugins/metrics_data_access/public/components/infrastructure_node_metrics_tables/shared/components/stepwise_pagination.tsx diff --git a/x-pack/plugins/infra/public/components/infrastructure_node_metrics_tables/shared/hooks/helpers.ts b/x-pack/plugins/metrics_data_access/public/components/infrastructure_node_metrics_tables/shared/hooks/helpers.ts similarity index 100% rename from x-pack/plugins/infra/public/components/infrastructure_node_metrics_tables/shared/hooks/helpers.ts rename to x-pack/plugins/metrics_data_access/public/components/infrastructure_node_metrics_tables/shared/hooks/helpers.ts diff --git a/x-pack/plugins/infra/public/components/infrastructure_node_metrics_tables/shared/hooks/index.ts b/x-pack/plugins/metrics_data_access/public/components/infrastructure_node_metrics_tables/shared/hooks/index.ts similarity index 100% rename from x-pack/plugins/infra/public/components/infrastructure_node_metrics_tables/shared/hooks/index.ts rename to x-pack/plugins/metrics_data_access/public/components/infrastructure_node_metrics_tables/shared/hooks/index.ts diff --git a/x-pack/plugins/infra/public/components/infrastructure_node_metrics_tables/shared/hooks/metrics_to_api_options.test.ts b/x-pack/plugins/metrics_data_access/public/components/infrastructure_node_metrics_tables/shared/hooks/metrics_to_api_options.test.ts similarity index 96% rename from x-pack/plugins/infra/public/components/infrastructure_node_metrics_tables/shared/hooks/metrics_to_api_options.test.ts rename to x-pack/plugins/metrics_data_access/public/components/infrastructure_node_metrics_tables/shared/hooks/metrics_to_api_options.test.ts index 79402b8813e08..88c4701bd4bf8 100644 --- a/x-pack/plugins/infra/public/components/infrastructure_node_metrics_tables/shared/hooks/metrics_to_api_options.test.ts +++ b/x-pack/plugins/metrics_data_access/public/components/infrastructure_node_metrics_tables/shared/hooks/metrics_to_api_options.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { MetricsExplorerOptions } from '../../../../pages/metrics/metrics_explorer/hooks/use_metrics_explorer_options'; +import type { MetricsExplorerOptions } from '../../../../../common/metrics_explorer_views/types'; import { createMetricByFieldLookup, MetricsQueryOptions, diff --git a/x-pack/plugins/infra/public/components/infrastructure_node_metrics_tables/shared/hooks/metrics_to_api_options.ts b/x-pack/plugins/metrics_data_access/public/components/infrastructure_node_metrics_tables/shared/hooks/metrics_to_api_options.ts similarity index 98% rename from x-pack/plugins/infra/public/components/infrastructure_node_metrics_tables/shared/hooks/metrics_to_api_options.ts rename to x-pack/plugins/metrics_data_access/public/components/infrastructure_node_metrics_tables/shared/hooks/metrics_to_api_options.ts index 3c99290518474..45f37069b7bb7 100644 --- a/x-pack/plugins/infra/public/components/infrastructure_node_metrics_tables/shared/hooks/metrics_to_api_options.ts +++ b/x-pack/plugins/metrics_data_access/public/components/infrastructure_node_metrics_tables/shared/hooks/metrics_to_api_options.ts @@ -10,7 +10,7 @@ import { ObjectValues } from '../../../../../common/utility_types'; import type { MetricsExplorerOptions, MetricsExplorerOptionsMetric, -} from '../../../../pages/metrics/metrics_explorer/hooks/use_metrics_explorer_options'; +} from '../../../../../common/metrics_explorer_views/types'; /* They key part of this file is the function 'createFieldLookup'. diff --git a/x-pack/plugins/infra/public/components/infrastructure_node_metrics_tables/shared/hooks/use_infrastructure_node_metrics.ts b/x-pack/plugins/metrics_data_access/public/components/infrastructure_node_metrics_tables/shared/hooks/use_infrastructure_node_metrics.ts similarity index 72% rename from x-pack/plugins/infra/public/components/infrastructure_node_metrics_tables/shared/hooks/use_infrastructure_node_metrics.ts rename to x-pack/plugins/metrics_data_access/public/components/infrastructure_node_metrics_tables/shared/hooks/use_infrastructure_node_metrics.ts index 95e388d3aae64..9360e4feb7c97 100644 --- a/x-pack/plugins/infra/public/components/infrastructure_node_metrics_tables/shared/hooks/use_infrastructure_node_metrics.ts +++ b/x-pack/plugins/metrics_data_access/public/components/infrastructure_node_metrics_tables/shared/hooks/use_infrastructure_node_metrics.ts @@ -7,31 +7,68 @@ import { parse } from '@kbn/datemath'; import { useEffect, useMemo, useState } from 'react'; -import { useKibana } from '@kbn/kibana-react-plugin/public'; import type { MetricsExplorerRequestBody, MetricsExplorerResponse, MetricsExplorerSeries, } from '../../../../../common/http_api/metrics_explorer'; -import { useSourceContext } from '../../../../containers/metrics_source'; import type { MetricsExplorerOptions, MetricsExplorerTimeOptions, -} from '../../../../pages/metrics/metrics_explorer/hooks/use_metrics_explorer_options'; +} from '../../../../../common/metrics_explorer_views/types'; import { useTrackedPromise } from '../../../../utils/use_tracked_promise'; import { NodeMetricsTableData } from '../types'; +import { MetricsDataClient } from '../../../../lib/metrics_client'; export interface SortState { field: keyof T; direction: 'asc' | 'desc'; } +export const useMetricIndices = ({ metricsClient }: { metricsClient: MetricsDataClient }) => { + const [metricIndices, setMetricIndices] = useState< + { metricIndices: string; metricIndicesExist: boolean } | undefined + >(undefined); + + const [metricIndicesRequest, getMetricIndices] = useTrackedPromise( + { + cancelPreviousOn: 'resolution', + createPromise: () => { + return metricsClient.metricsIndices(); + }, + onResolve: (response) => { + if (response) { + setMetricIndices(response); + } + }, + }, + [metricsClient] + ); + + useEffect(() => { + getMetricIndices(); + }, [getMetricIndices, metricsClient]); + + const hasFailedLoading = metricIndicesRequest.state === 'rejected'; + const isUninitialized = metricIndicesRequest.state === 'uninitialized'; + const isLoading = metricIndicesRequest.state === 'pending'; + + return { + isLoading, + isUninitialized, + errorMessage: hasFailedLoading ? `${metricIndicesRequest.value}` : undefined, + metricIndicesExist: metricIndices?.metricIndicesExist, + metricIndices: metricIndices?.metricIndices, + }; +}; + interface UseInfrastructureNodeMetricsOptions { metricsExplorerOptions: MetricsExplorerOptions; timerange: Pick; transform: (series: MetricsExplorerSeries) => T; sortState: SortState; currentPageIndex: number; + metricsClient: MetricsDataClient; } const NODE_COUNT_LIMIT = 10000; @@ -48,52 +85,59 @@ const nullData: MetricsExplorerResponse = { export const useInfrastructureNodeMetrics = ( options: UseInfrastructureNodeMetricsOptions ) => { - const { metricsExplorerOptions, timerange, transform, sortState, currentPageIndex } = options; + const { + metricsExplorerOptions, + timerange, + transform, + sortState, + currentPageIndex, + metricsClient, + } = options; const [transformedNodes, setTransformedNodes] = useState([]); - const fetch = useKibanaHttpFetch(); - const { source, isLoadingSource, loadSourceRequest, metricIndicesExist } = useSourceContext(); + const { + metricIndices, + metricIndicesExist, + isLoading: metricIndicesLoading, + errorMessage: metricIndicesError, + } = useMetricIndices({ metricsClient }); const timerangeWithInterval = useTimerangeWithInterval(timerange); const [fetchNodesRequest, fetchNodes] = useTrackedPromise( { - createPromise: (): Promise => { - if (!source) { + createPromise: async (): Promise => { + if (!metricIndices) { return Promise.resolve(nullData); } - const request: MetricsExplorerRequestBody = { metrics: metricsExplorerOptions.metrics, groupBy: metricsExplorerOptions.groupBy, limit: NODE_COUNT_LIMIT, - indexPattern: source.configuration.metricAlias, + indexPattern: metricIndices, filterQuery: metricsExplorerOptions.filterQuery, timerange: timerangeWithInterval, }; - return fetch('/api/infra/metrics_explorer', { - method: 'POST', - body: JSON.stringify(request), - }); + return metricsClient.metricsExplorer(request); }, onResolve: (response: MetricsExplorerResponse) => { setTransformedNodes(response.series.map(transform)); }, cancelPreviousOn: 'creation', }, - [source, metricsExplorerOptions, timerangeWithInterval] + [metricIndices, metricsExplorerOptions, timerangeWithInterval] ); const isLoadingNodes = fetchNodesRequest.state === 'pending' || fetchNodesRequest.state === 'uninitialized'; - const isLoading = isLoadingSource || isLoadingNodes; + const isLoading = metricIndicesLoading || isLoadingNodes; const errors = useMemo( () => [ - ...(loadSourceRequest.state === 'rejected' ? [wrapAsError(loadSourceRequest.value)] : []), + ...(metricIndicesError ? [wrapAsError(metricIndicesError)] : []), ...(fetchNodesRequest.state === 'rejected' ? [wrapAsError(fetchNodesRequest.value)] : []), ], - [fetchNodesRequest, loadSourceRequest] + [fetchNodesRequest, metricIndicesError] ); useEffect(() => { @@ -136,17 +180,6 @@ export const useInfrastructureNodeMetrics = ( }; }; -function useKibanaHttpFetch() { - const kibana = useKibana(); - const fetch = kibana.services.http?.fetch; - - if (!fetch) { - throw new Error('Could not find Kibana HTTP fetch'); - } - - return fetch; -} - function useTimerangeWithInterval(timerange: Pick) { return useMemo(() => { const from = parse(timerange.from); diff --git a/x-pack/plugins/infra/public/components/infrastructure_node_metrics_tables/shared/index.ts b/x-pack/plugins/metrics_data_access/public/components/infrastructure_node_metrics_tables/shared/index.ts similarity index 97% rename from x-pack/plugins/infra/public/components/infrastructure_node_metrics_tables/shared/index.ts rename to x-pack/plugins/metrics_data_access/public/components/infrastructure_node_metrics_tables/shared/index.ts index bb2a0d7a0e8ba..6c23aa2203108 100644 --- a/x-pack/plugins/infra/public/components/infrastructure_node_metrics_tables/shared/index.ts +++ b/x-pack/plugins/metrics_data_access/public/components/infrastructure_node_metrics_tables/shared/index.ts @@ -28,4 +28,5 @@ export type { NodeMetricsTableData, SourceProviderProps, UseNodeMetricsTableOptions, + NodeMetricsTableProps, } from './types'; diff --git a/x-pack/plugins/infra/public/components/infrastructure_node_metrics_tables/shared/types.ts b/x-pack/plugins/metrics_data_access/public/components/infrastructure_node_metrics_tables/shared/types.ts similarity index 79% rename from x-pack/plugins/infra/public/components/infrastructure_node_metrics_tables/shared/types.ts rename to x-pack/plugins/metrics_data_access/public/components/infrastructure_node_metrics_tables/shared/types.ts index 36fb29c57ecc5..21023f0b3a71b 100644 --- a/x-pack/plugins/infra/public/components/infrastructure_node_metrics_tables/shared/types.ts +++ b/x-pack/plugins/metrics_data_access/public/components/infrastructure_node_metrics_tables/shared/types.ts @@ -7,11 +7,12 @@ import type { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import type { CoreProvidersProps } from '../../../apps/common_providers'; -import type { MetricsExplorerTimeOptions } from '../../../pages/metrics/metrics_explorer/hooks/use_metrics_explorer_options'; +import type { MetricsDataClient } from '../../../lib/metrics_client'; export interface UseNodeMetricsTableOptions { - timerange: Pick; + timerange: { from: string; to: string }; filterClauseDsl?: QueryDslQueryContainer; + metricsClient: MetricsDataClient; } export interface SourceProviderProps { @@ -22,6 +23,9 @@ export type IntegratedNodeMetricsTableProps = UseNodeMetricsTableOptions & SourceProviderProps & CoreProvidersProps; +export type NodeMetricsTableProps = Omit & + Partial; + export type NodeMetricsTableData = | { state: 'unknown'; diff --git a/x-pack/plugins/infra/public/components/infrastructure_node_metrics_tables/test_helpers.ts b/x-pack/plugins/metrics_data_access/public/components/infrastructure_node_metrics_tables/test_helpers.ts similarity index 55% rename from x-pack/plugins/infra/public/components/infrastructure_node_metrics_tables/test_helpers.ts rename to x-pack/plugins/metrics_data_access/public/components/infrastructure_node_metrics_tables/test_helpers.ts index a84ecd94e3182..310f1e8074b9f 100644 --- a/x-pack/plugins/infra/public/components/infrastructure_node_metrics_tables/test_helpers.ts +++ b/x-pack/plugins/metrics_data_access/public/components/infrastructure_node_metrics_tables/test_helpers.ts @@ -10,38 +10,24 @@ import { coreMock } from '@kbn/core/public/mocks'; import { I18nProvider } from '@kbn/i18n-react'; import { DeepPartial } from 'utility-types'; import type { MetricsExplorerResponse } from '../../../common/http_api/metrics_explorer'; -import type { MetricsSourceConfigurationResponse } from '../../../common/metrics_sources'; import type { CoreProvidersProps } from '../../apps/common_providers'; -import type { - InfraClientStartDeps, - InfraClientStartExports, - InfraClientStartServices, -} from '../../types'; +import { MetricsDataClient } from '../../lib/metrics_client'; -export type SourceResponseMock = DeepPartial; export type DataResponseMock = DeepPartial; export type NodeMetricsTableFetchMock = ( path: string, options: HttpFetchOptions -) => Promise; +) => Promise; -export function createStartServicesAccessorMock(fetchMock: NodeMetricsTableFetchMock) { +export function createStartServicesAccessorMock() { const core = coreMock.createStart(); - // @ts-expect-error core.http.fetch has overloads, Jest/TypeScript only picks the first definition when mocking - core.http.fetch.mockImplementation(fetchMock); core.i18n.Context.mockImplementation(I18nProvider as () => JSX.Element); const coreProvidersPropsMock: CoreProvidersProps = { core, - pluginStart: {} as InfraClientStartExports, - plugins: {} as InfraClientStartDeps, theme$: core.theme.theme$, }; - const getStartServices = (): InfraClientStartServices => [ - coreProvidersPropsMock.core, - coreProvidersPropsMock.plugins, - coreProvidersPropsMock.pluginStart, - ]; + const getStartServices = () => [coreProvidersPropsMock.core]; return { coreProvidersPropsMock, @@ -49,3 +35,12 @@ export function createStartServicesAccessorMock(fetchMock: NodeMetricsTableFetch getStartServices, }; } + +export function createMetricsClientMock(metricsExplorerData: any) { + return { + metricsIndices: jest + .fn() + .mockResolvedValue({ metricIndices: 'metrics-*', metricIndicesExist: true }), + metricsExplorer: jest.fn().mockResolvedValue(metricsExplorerData), + } as unknown as MetricsDataClient; +} diff --git a/x-pack/plugins/metrics_data_access/public/hooks/use_kibana.tsx b/x-pack/plugins/metrics_data_access/public/hooks/use_kibana.tsx new file mode 100644 index 0000000000000..c99caa3f4c266 --- /dev/null +++ b/x-pack/plugins/metrics_data_access/public/hooks/use_kibana.tsx @@ -0,0 +1,30 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { useMemo } from 'react'; +import { CoreStart } from '@kbn/core/public'; +import { + createKibanaReactContext, + KibanaReactContextValue, + useKibana, +} from '@kbn/kibana-react-plugin/public'; + +export type PluginKibanaContextValue = CoreStart; + +export const createKibanaContextForPlugin = (core: CoreStart) => + createKibanaReactContext({ + ...core, + }); + +export const useKibanaContextForPlugin = + useKibana as () => KibanaReactContextValue; + +export const useKibanaContextForPluginProvider = (core: CoreStart) => { + const { Provider } = useMemo(() => createKibanaContextForPlugin(core), [core]); + + return Provider; +}; diff --git a/x-pack/plugins/metrics_data_access/public/index.ts b/x-pack/plugins/metrics_data_access/public/index.ts new file mode 100644 index 0000000000000..cbe678e91e6a3 --- /dev/null +++ b/x-pack/plugins/metrics_data_access/public/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 { PluginInitializer, PluginInitializerContext } from '@kbn/core/public'; +import { Plugin } from './plugin'; +import { MetricsDataPluginSetup, MetricsDataPluginStart } from './types'; + +export const plugin: PluginInitializer = ( + context: PluginInitializerContext +) => { + return new Plugin(context); +}; + +export type { MetricsDataPluginSetup, MetricsDataPluginStart }; diff --git a/x-pack/plugins/metrics_data_access/public/lib/metrics_client.ts b/x-pack/plugins/metrics_data_access/public/lib/metrics_client.ts new file mode 100644 index 0000000000000..a2688dcea4d86 --- /dev/null +++ b/x-pack/plugins/metrics_data_access/public/lib/metrics_client.ts @@ -0,0 +1,28 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { HttpStart } from '@kbn/core/public'; +import { + MetricsExplorerRequestBody, + MetricsExplorerResponse, +} from '../../common/http_api/metrics_explorer'; + +export class MetricsDataClient { + constructor(private readonly http: HttpStart) {} + + async metricsExplorer(body: MetricsExplorerRequestBody) { + return this.http.post('/api/infra/metrics_explorer', { + body: JSON.stringify(body), + }); + } + + async metricsIndices() { + return this.http.get<{ metricIndices: string; metricIndicesExist: boolean }>( + '/api/metrics/indices' + ); + } +} diff --git a/x-pack/plugins/metrics_data_access/public/pages/link_to/index.ts b/x-pack/plugins/metrics_data_access/public/pages/link_to/index.ts new file mode 100644 index 0000000000000..f23d0e7fa1e93 --- /dev/null +++ b/x-pack/plugins/metrics_data_access/public/pages/link_to/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 { useNodeDetailsRedirect } from './use_node_details_redirect'; diff --git a/x-pack/plugins/metrics_data_access/public/pages/link_to/use_node_details_redirect.ts b/x-pack/plugins/metrics_data_access/public/pages/link_to/use_node_details_redirect.ts new file mode 100644 index 0000000000000..7d9c813f97479 --- /dev/null +++ b/x-pack/plugins/metrics_data_access/public/pages/link_to/use_node_details_redirect.ts @@ -0,0 +1,70 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { useCallback } from 'react'; +import { useLocation } from 'react-router-dom'; +import type { LinkDescriptor } from '@kbn/observability-shared-plugin/public'; +import useObservable from 'react-use/lib/useObservable'; +import type { InventoryItemType } from '../../../common/inventory_models/types'; +import { useKibanaContextForPlugin } from '../../hooks/use_kibana'; + +interface QueryParams { + from?: number; + to?: number; + assetName?: string; +} + +export const useNodeDetailsRedirect = () => { + const location = useLocation(); + const { + services: { + application: { currentAppId$ }, + }, + } = useKibanaContextForPlugin(); + + const appId = useObservable(currentAppId$); + const getNodeDetailUrl = useCallback( + ({ + nodeType, + nodeId, + search, + }: { + nodeType: InventoryItemType; + nodeId: string; + search: QueryParams; + }): LinkDescriptor => { + const { to, from, ...rest } = search; + + return { + app: 'metrics', + pathname: `link-to/${nodeType}-detail/${nodeId}`, + search: { + ...rest, + ...(to && from + ? { + to: `${to}`, + from: `${from}`, + } + : undefined), + // While we don't have a shared state between all page in infra, this makes it possible to restore a page state when returning to the previous route + ...(location.search || location.pathname + ? { + state: JSON.stringify({ + originAppId: appId, + originSearch: location.search, + originPathname: location.pathname, + }), + } + : undefined), + }, + }; + }, + [location.pathname, appId, location.search] + ); + + return { getNodeDetailUrl }; +}; diff --git a/x-pack/plugins/metrics_data_access/public/plugin.ts b/x-pack/plugins/metrics_data_access/public/plugin.ts new file mode 100644 index 0000000000000..e85dd77f9f3a9 --- /dev/null +++ b/x-pack/plugins/metrics_data_access/public/plugin.ts @@ -0,0 +1,41 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { CoreSetup, CoreStart, PluginInitializerContext } from '@kbn/core/public'; +import { Logger } from '@kbn/logging'; +import { MetricsDataPluginClass } from './types'; +import { MetricsDataClient } from './lib/metrics_client'; +import { createLazyContainerMetricsTable } from './components/infrastructure_node_metrics_tables/container/create_lazy_container_metrics_table'; +import { createLazyHostMetricsTable } from './components/infrastructure_node_metrics_tables/host/create_lazy_host_metrics_table'; +import { createLazyPodMetricsTable } from './components/infrastructure_node_metrics_tables/pod/create_lazy_pod_metrics_table'; + +export class Plugin implements MetricsDataPluginClass { + public logger: Logger; + + constructor(context: PluginInitializerContext<{}>) { + this.logger = context.logger.get(); + } + + setup(core: CoreSetup) { + const metricsClient = new MetricsDataClient(core.http); + return { + metricsClient, + }; + } + + start(core: CoreStart) { + const metricsClient = new MetricsDataClient(core.http); + return { + metricsClient, + ContainerMetricsTable: createLazyContainerMetricsTable(core, metricsClient), + HostMetricsTable: createLazyHostMetricsTable(core, metricsClient), + PodMetricsTable: createLazyPodMetricsTable(core, metricsClient), + }; + } + + stop() {} +} diff --git a/x-pack/plugins/metrics_data_access/public/test_utils/index.ts b/x-pack/plugins/metrics_data_access/public/test_utils/index.ts new file mode 100644 index 0000000000000..89ab12cf8f088 --- /dev/null +++ b/x-pack/plugins/metrics_data_access/public/test_utils/index.ts @@ -0,0 +1,314 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor 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 FAKE_SNAPSHOT_RESPONSE = { + nodes: [ + { + path: [{ value: 'host-01', label: 'host-01', ip: '192.168.1.10' }], + metrics: [ + { + name: 'memory', + value: 0.002, + max: 0.00134, + avg: 0.0009833333333333335, + timeseries: { + id: 'memory', + columns: [ + { name: 'timestamp', type: 'date' }, + { name: 'metric_0', type: 'number' }, + ], + rows: [ + { timestamp: 1593630455000, metric_0: 0 }, + { timestamp: 1593630755000, metric_0: 0.001 }, + { timestamp: 1593631055000, metric_0: 0.00099 }, + { timestamp: 1593631355000, metric_0: 0.00133 }, + { timestamp: 1593631655000, metric_0: 0.00099 }, + { timestamp: 1593631955000, metric_0: 0.001 }, + { timestamp: 1593632255000, metric_0: 0.00099 }, + { timestamp: 1593632555000, metric_0: 0.00067 }, + { timestamp: 1593632855000, metric_0: 0.001 }, + { timestamp: 1593633155000, metric_0: 0.00099 }, + { timestamp: 1593633455000, metric_0: 0.00099 }, + { timestamp: 1593633755000, metric_0: 0.00099 }, + { timestamp: 1593634055000, metric_0: 0.001 }, + { timestamp: 1593634355000, metric_0: 0.00067 }, + { timestamp: 1593634655000, metric_0: 0.00133 }, + { timestamp: 1593634955000, metric_0: 0.00101 }, + { timestamp: 1593635255000, metric_0: 0.00134 }, + { timestamp: 1593635555000, metric_0: 0.00133 }, + { timestamp: 1593635855000, metric_0: 0.00102 }, + { timestamp: 1593636155000, metric_0: 0.00101 }, + { timestamp: 1593636455000, metric_0: 0.001 }, + ], + }, + }, + { + name: 'cpu', + value: 0.002, + max: 0.00134, + avg: 0.0009833333333333335, + timeseries: { + id: 'cpu', + columns: [ + { name: 'timestamp', type: 'date' }, + { name: 'metric_0', type: 'number' }, + ], + rows: [ + { timestamp: 1593630455000, metric_0: 0 }, + { timestamp: 1593630755000, metric_0: 0.001 }, + { timestamp: 1593631055000, metric_0: 0.00099 }, + { timestamp: 1593631355000, metric_0: 0.00133 }, + { timestamp: 1593631655000, metric_0: 0.00099 }, + { timestamp: 1593631955000, metric_0: 0.001 }, + { timestamp: 1593632255000, metric_0: 0.00099 }, + { timestamp: 1593632555000, metric_0: 0.00067 }, + { timestamp: 1593632855000, metric_0: 0.001 }, + { timestamp: 1593633155000, metric_0: 0.00099 }, + { timestamp: 1593633455000, metric_0: 0.00099 }, + { timestamp: 1593633755000, metric_0: 0.00099 }, + { timestamp: 1593634055000, metric_0: 0.001 }, + { timestamp: 1593634355000, metric_0: 0.00067 }, + { timestamp: 1593634655000, metric_0: 0.00133 }, + { timestamp: 1593634955000, metric_0: 0.00101 }, + { timestamp: 1593635255000, metric_0: 0.00134 }, + { timestamp: 1593635555000, metric_0: 0.00133 }, + { timestamp: 1593635855000, metric_0: 0.00102 }, + { timestamp: 1593636155000, metric_0: 0.00101 }, + { timestamp: 1593636455000, metric_0: 0.001 }, + ], + }, + }, + { + name: 'rx', + value: 4, + max: 13, + avg: 3.761904761904762, + timeseries: { + id: 'rx', + columns: [ + { name: 'timestamp', type: 'date' }, + { name: 'metric_0', type: 'number' }, + ], + rows: [ + { timestamp: 1593630455000, metric_0: 0 }, + { timestamp: 1593630755000, metric_0: 4 }, + { timestamp: 1593631055000, metric_0: 4 }, + { timestamp: 1593631355000, metric_0: 9 }, + { timestamp: 1593631655000, metric_0: 4 }, + { timestamp: 1593631955000, metric_0: 3 }, + { timestamp: 1593632255000, metric_0: 2 }, + { timestamp: 1593632555000, metric_0: 2 }, + { timestamp: 1593632855000, metric_0: 4 }, + { timestamp: 1593633155000, metric_0: 3 }, + { timestamp: 1593633455000, metric_0: 2 }, + { timestamp: 1593633755000, metric_0: 2 }, + { timestamp: 1593634055000, metric_0: 3 }, + { timestamp: 1593634355000, metric_0: 0 }, + { timestamp: 1593634655000, metric_0: 11 }, + { timestamp: 1593634955000, metric_0: 6 }, + { timestamp: 1593635255000, metric_0: 14 }, + { timestamp: 1593635555000, metric_0: 10 }, + { timestamp: 1593635855000, metric_0: 8 }, + { timestamp: 1593636155000, metric_0: 4 }, + { timestamp: 1593636455000, metric_0: 4 }, + ], + }, + }, + { + name: 'tx', + value: 3, + max: 13, + avg: 3.761904761904762, + timeseries: { + id: 'tx', + columns: [ + { name: 'timestamp', type: 'date' }, + { name: 'metric_0', type: 'number' }, + ], + rows: [ + { timestamp: 1593630455000, metric_0: 0 }, + { timestamp: 1593630755000, metric_0: 5 }, + { timestamp: 1593631055000, metric_0: 5 }, + { timestamp: 1593631355000, metric_0: 10 }, + { timestamp: 1593631655000, metric_0: 5 }, + { timestamp: 1593631955000, metric_0: 3 }, + { timestamp: 1593632255000, metric_0: 3 }, + { timestamp: 1593632555000, metric_0: 3 }, + { timestamp: 1593632855000, metric_0: 5 }, + { timestamp: 1593633155000, metric_0: 4 }, + { timestamp: 1593633455000, metric_0: 3 }, + { timestamp: 1593633755000, metric_0: 3 }, + { timestamp: 1593634055000, metric_0: 3 }, + { timestamp: 1593634355000, metric_0: 2 }, + { timestamp: 1593634655000, metric_0: 12 }, + { timestamp: 1593634955000, metric_0: 7 }, + { timestamp: 1593635255000, metric_0: 15 }, + { timestamp: 1593635555000, metric_0: 11 }, + { timestamp: 1593635855000, metric_0: 9 }, + { timestamp: 1593636155000, metric_0: 4 }, + { timestamp: 1593636455000, metric_0: 5 }, + ], + }, + }, + ], + }, + { + path: [{ value: 'host-02', label: 'host-02', ip: '192.168.1.11' }], + metrics: [ + { + name: 'memory', + value: 0.001, + max: 0.00134, + avg: 0.0009833333333333335, + timeseries: { + id: 'memory', + columns: [ + { name: 'timestamp', type: 'date' }, + { name: 'metric_0', type: 'number' }, + ], + rows: [ + { timestamp: 1593630455000, metric_0: 0 }, + { timestamp: 1593630755000, metric_0: 0.001 }, + { timestamp: 1593631055000, metric_0: 0.00099 }, + { timestamp: 1593631355000, metric_0: 0.00133 }, + { timestamp: 1593631655000, metric_0: 0.00099 }, + { timestamp: 1593631955000, metric_0: 0.001 }, + { timestamp: 1593632255000, metric_0: 0.00099 }, + { timestamp: 1593632555000, metric_0: 0.00067 }, + { timestamp: 1593632855000, metric_0: 0.001 }, + { timestamp: 1593633155000, metric_0: 0.00099 }, + { timestamp: 1593633455000, metric_0: 0.00099 }, + { timestamp: 1593633755000, metric_0: 0.00099 }, + { timestamp: 1593634055000, metric_0: 0.001 }, + { timestamp: 1593634355000, metric_0: 0.00067 }, + { timestamp: 1593634655000, metric_0: 0.00133 }, + { timestamp: 1593634955000, metric_0: 0.00101 }, + { timestamp: 1593635255000, metric_0: 0.00134 }, + { timestamp: 1593635555000, metric_0: 0.00133 }, + { timestamp: 1593635855000, metric_0: 0.00102 }, + { timestamp: 1593636155000, metric_0: 0.00101 }, + { timestamp: 1593636455000, metric_0: 0.001 }, + ], + }, + }, + { + name: 'cpu', + value: 0.001, + max: 0.00134, + avg: 0.0009833333333333335, + timeseries: { + id: 'cpu', + columns: [ + { name: 'timestamp', type: 'date' }, + { name: 'metric_0', type: 'number' }, + ], + rows: [ + { timestamp: 1593630455000, metric_0: 0 }, + { timestamp: 1593630755000, metric_0: 0.001 }, + { timestamp: 1593631055000, metric_0: 0.00099 }, + { timestamp: 1593631355000, metric_0: 0.00133 }, + { timestamp: 1593631655000, metric_0: 0.00099 }, + { timestamp: 1593631955000, metric_0: 0.001 }, + { timestamp: 1593632255000, metric_0: 0.00099 }, + { timestamp: 1593632555000, metric_0: 0.00067 }, + { timestamp: 1593632855000, metric_0: 0.001 }, + { timestamp: 1593633155000, metric_0: 0.00099 }, + { timestamp: 1593633455000, metric_0: 0.00099 }, + { timestamp: 1593633755000, metric_0: 0.00099 }, + { timestamp: 1593634055000, metric_0: 0.001 }, + { timestamp: 1593634355000, metric_0: 0.00067 }, + { timestamp: 1593634655000, metric_0: 0.00133 }, + { timestamp: 1593634955000, metric_0: 0.00101 }, + { timestamp: 1593635255000, metric_0: 0.00134 }, + { timestamp: 1593635555000, metric_0: 0.00133 }, + { timestamp: 1593635855000, metric_0: 0.00102 }, + { timestamp: 1593636155000, metric_0: 0.00101 }, + { timestamp: 1593636455000, metric_0: 0.001 }, + ], + }, + }, + { + name: 'rx', + value: 3, + max: 13, + avg: 3.761904761904762, + timeseries: { + id: 'rx', + columns: [ + { name: 'timestamp', type: 'date' }, + { name: 'metric_0', type: 'number' }, + ], + rows: [ + { timestamp: 1593630455000, metric_0: 0 }, + { timestamp: 1593630755000, metric_0: 3 }, + { timestamp: 1593631055000, metric_0: 3 }, + { timestamp: 1593631355000, metric_0: 8 }, + { timestamp: 1593631655000, metric_0: 3 }, + { timestamp: 1593631955000, metric_0: 2 }, + { timestamp: 1593632255000, metric_0: 1 }, + { timestamp: 1593632555000, metric_0: 1 }, + { timestamp: 1593632855000, metric_0: 3 }, + { timestamp: 1593633155000, metric_0: 2 }, + { timestamp: 1593633455000, metric_0: 1 }, + { timestamp: 1593633755000, metric_0: 1 }, + { timestamp: 1593634055000, metric_0: 2 }, + { timestamp: 1593634355000, metric_0: 0 }, + { timestamp: 1593634655000, metric_0: 10 }, + { timestamp: 1593634955000, metric_0: 5 }, + { timestamp: 1593635255000, metric_0: 13 }, + { timestamp: 1593635555000, metric_0: 9 }, + { timestamp: 1593635855000, metric_0: 7 }, + { timestamp: 1593636155000, metric_0: 2 }, + { timestamp: 1593636455000, metric_0: 3 }, + ], + }, + }, + { + name: 'tx', + value: 3, + max: 13, + avg: 3.761904761904762, + timeseries: { + id: 'tx', + columns: [ + { name: 'timestamp', type: 'date' }, + { name: 'metric_0', type: 'number' }, + ], + rows: [ + { timestamp: 1593630455000, metric_0: 0 }, + { timestamp: 1593630755000, metric_0: 3 }, + { timestamp: 1593631055000, metric_0: 3 }, + { timestamp: 1593631355000, metric_0: 8 }, + { timestamp: 1593631655000, metric_0: 3 }, + { timestamp: 1593631955000, metric_0: 2 }, + { timestamp: 1593632255000, metric_0: 1 }, + { timestamp: 1593632555000, metric_0: 1 }, + { timestamp: 1593632855000, metric_0: 3 }, + { timestamp: 1593633155000, metric_0: 2 }, + { timestamp: 1593633455000, metric_0: 1 }, + { timestamp: 1593633755000, metric_0: 1 }, + { timestamp: 1593634055000, metric_0: 2 }, + { timestamp: 1593634355000, metric_0: 0 }, + { timestamp: 1593634655000, metric_0: 10 }, + { timestamp: 1593634955000, metric_0: 5 }, + { timestamp: 1593635255000, metric_0: 13 }, + { timestamp: 1593635555000, metric_0: 9 }, + { timestamp: 1593635855000, metric_0: 7 }, + { timestamp: 1593636155000, metric_0: 2 }, + { timestamp: 1593636455000, metric_0: 3 }, + ], + }, + }, + ], + }, + ], + interval: '300s', +}; + +export const FAKE_OVERVIEW_RESPONSE = { + series: [], +}; diff --git a/x-pack/plugins/metrics_data_access/public/test_utils/use_global_storybook_theme.tsx b/x-pack/plugins/metrics_data_access/public/test_utils/use_global_storybook_theme.tsx new file mode 100644 index 0000000000000..4d1feb4617dcf --- /dev/null +++ b/x-pack/plugins/metrics_data_access/public/test_utils/use_global_storybook_theme.tsx @@ -0,0 +1,59 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { DecoratorFn } from '@storybook/react'; +import React, { useEffect, useMemo, useState } from 'react'; +import { BehaviorSubject } from 'rxjs'; +import type { CoreTheme } from '@kbn/core/public'; +import { EuiThemeProvider } from '@kbn/kibana-react-plugin/common'; +import { KibanaThemeProvider } from '@kbn/kibana-react-plugin/public'; + +type StoryContext = Parameters[1]; + +export const useGlobalStorybookTheme = ({ globals: { euiTheme } }: StoryContext) => { + const theme = useMemo(() => euiThemeFromId(euiTheme), [euiTheme]); + const [theme$] = useState(() => new BehaviorSubject(theme)); + + useEffect(() => { + theme$.next(theme); + }, [theme$, theme]); + + return { + theme, + theme$, + }; +}; + +export const GlobalStorybookThemeProviders: React.FC<{ storyContext: StoryContext }> = ({ + children, + storyContext, +}) => { + const { theme, theme$ } = useGlobalStorybookTheme(storyContext); + return ( + + {children} + + ); +}; + +export const decorateWithGlobalStorybookThemeProviders: DecoratorFn = ( + wrappedStory, + storyContext +) => ( + + {wrappedStory()} + +); + +const euiThemeFromId = (themeId: string): CoreTheme => { + switch (themeId) { + case 'v8.dark': + return { darkMode: true }; + default: + return { darkMode: false }; + } +}; diff --git a/x-pack/plugins/metrics_data_access/public/types.ts b/x-pack/plugins/metrics_data_access/public/types.ts new file mode 100644 index 0000000000000..785f23fc55edf --- /dev/null +++ b/x-pack/plugins/metrics_data_access/public/types.ts @@ -0,0 +1,22 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import type { Plugin as PluginClass } from '@kbn/core/public'; +import type { MetricsDataClient } from './lib/metrics_client'; +import type { NodeMetricsTableProps } from './components/infrastructure_node_metrics_tables/shared'; + +export interface MetricsDataPluginSetup { + metricsClient: MetricsDataClient; +} + +export interface MetricsDataPluginStart { + metricsClient: MetricsDataClient; + HostMetricsTable: (props: NodeMetricsTableProps) => JSX.Element; + PodMetricsTable: (props: NodeMetricsTableProps) => JSX.Element; + ContainerMetricsTable: (props: NodeMetricsTableProps) => JSX.Element; +} + +export type MetricsDataPluginClass = PluginClass; diff --git a/x-pack/plugins/metrics_data_access/public/utils/use_tracked_promise.ts b/x-pack/plugins/metrics_data_access/public/utils/use_tracked_promise.ts new file mode 100644 index 0000000000000..d12749ea69fdc --- /dev/null +++ b/x-pack/plugins/metrics_data_access/public/utils/use_tracked_promise.ts @@ -0,0 +1,299 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor 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 max-classes-per-file */ + +import { DependencyList, useEffect, useMemo, useRef, useState, useCallback } from 'react'; +import useMountedState from 'react-use/lib/useMountedState'; + +interface UseTrackedPromiseArgs { + createPromise: (...args: Arguments) => Promise; + onResolve?: (result: Result) => void; + onReject?: (value: unknown) => void; + cancelPreviousOn?: 'creation' | 'settlement' | 'resolution' | 'rejection' | 'never'; + triggerOrThrow?: 'always' | 'whenMounted'; +} + +/** + * This hook manages a Promise factory and can create new Promises from it. The + * state of these Promises is tracked and they can be canceled when superseded + * to avoid race conditions. + * + * ``` + * const [requestState, performRequest] = useTrackedPromise( + * { + * cancelPreviousOn: 'resolution', + * createPromise: async (url: string) => { + * return await fetchSomething(url) + * }, + * onResolve: response => { + * setSomeState(response.data); + * }, + * onReject: response => { + * setSomeError(response); + * }, + * }, + * [fetchSomething] + * ); + * ``` + * + * The `onResolve` and `onReject` handlers are registered separately, because + * the hook will inject a rejection when in case of a canellation. The + * `cancelPreviousOn` attribute can be used to indicate when the preceding + * pending promises should be canceled: + * + * 'never': No preceding promises will be canceled. + * + * 'creation': Any preceding promises will be canceled as soon as a new one is + * created. + * + * 'settlement': Any preceding promise will be canceled when a newer promise is + * resolved or rejected. + * + * 'resolution': Any preceding promise will be canceled when a newer promise is + * resolved. + * + * 'rejection': Any preceding promise will be canceled when a newer promise is + * rejected. + * + * Any pending promises will be canceled when the component using the hook is + * unmounted, but their status will not be tracked to avoid React warnings + * about memory leaks. + * + * The last argument is a normal React hook dependency list that indicates + * under which conditions a new reference to the configuration object should be + * used. + * + * The `onResolve`, `onReject` and possible uncatched errors are only triggered + * if the underlying component is mounted. To ensure they always trigger (i.e. + * if the promise is called in a `useLayoutEffect`) use the `triggerOrThrow` + * attribute: + * + * 'whenMounted': (default) they are called only if the component is mounted. + * + * 'always': they always call. The consumer is then responsible of ensuring no + * side effects happen if the underlying component is not mounted. + */ +export const useTrackedPromise = ( + { + createPromise, + onResolve = noOp, + onReject = noOp, + cancelPreviousOn = 'never', + triggerOrThrow = 'whenMounted', + }: UseTrackedPromiseArgs, + dependencies: DependencyList +) => { + const isComponentMounted = useMountedState(); + const shouldTriggerOrThrow = useCallback(() => { + switch (triggerOrThrow) { + case 'always': + return true; + case 'whenMounted': + return isComponentMounted(); + } + }, [isComponentMounted, triggerOrThrow]); + + /** + * If a promise is currently pending, this holds a reference to it and its + * cancellation function. + */ + const pendingPromises = useRef>>([]); + + /** + * The state of the promise most recently created by the `createPromise` + * factory. It could be uninitialized, pending, resolved or rejected. + */ + const [promiseState, setPromiseState] = useState>({ + state: 'uninitialized', + }); + + const reset = useCallback(() => { + setPromiseState({ + state: 'uninitialized', + }); + }, []); + + const execute = useMemo( + () => + (...args: Arguments) => { + let rejectCancellationPromise!: (value: any) => void; + const cancellationPromise = new Promise((_, reject) => { + rejectCancellationPromise = reject; + }); + + // remember the list of prior pending promises for cancellation + const previousPendingPromises = pendingPromises.current; + + const cancelPreviousPendingPromises = () => { + previousPendingPromises.forEach((promise) => promise.cancel()); + }; + + const newPromise = createPromise(...args); + const newCancelablePromise = Promise.race([newPromise, cancellationPromise]); + + // track this new state + setPromiseState({ + state: 'pending', + promise: newCancelablePromise, + }); + + if (cancelPreviousOn === 'creation') { + cancelPreviousPendingPromises(); + } + + const newPendingPromise: CancelablePromise = { + cancel: () => { + rejectCancellationPromise(new CanceledPromiseError()); + }, + cancelSilently: () => { + rejectCancellationPromise(new SilentCanceledPromiseError()); + }, + promise: newCancelablePromise.then( + (value) => { + if (['settlement', 'resolution'].includes(cancelPreviousOn)) { + cancelPreviousPendingPromises(); + } + + // remove itself from the list of pending promises + pendingPromises.current = pendingPromises.current.filter( + (pendingPromise) => pendingPromise.promise !== newPendingPromise.promise + ); + + if (onResolve && shouldTriggerOrThrow()) { + onResolve(value); + } + + setPromiseState((previousPromiseState) => + previousPromiseState.state === 'pending' && + previousPromiseState.promise === newCancelablePromise + ? { + state: 'resolved', + promise: newPendingPromise.promise, + value, + } + : previousPromiseState + ); + + return value; + }, + (value) => { + if (!(value instanceof SilentCanceledPromiseError)) { + if (['settlement', 'rejection'].includes(cancelPreviousOn)) { + cancelPreviousPendingPromises(); + } + + // remove itself from the list of pending promises + pendingPromises.current = pendingPromises.current.filter( + (pendingPromise) => pendingPromise.promise !== newPendingPromise.promise + ); + + if (shouldTriggerOrThrow()) { + if (onReject) { + onReject(value); + } else { + throw value; + } + } + + setPromiseState((previousPromiseState) => + previousPromiseState.state === 'pending' && + previousPromiseState.promise === newCancelablePromise + ? { + state: 'rejected', + promise: newCancelablePromise, + value, + } + : previousPromiseState + ); + } + } + ), + }; + + // add the new promise to the list of pending promises + pendingPromises.current = [...pendingPromises.current, newPendingPromise]; + + // silence "unhandled rejection" warnings + newPendingPromise.promise.catch(noOp); + + return newPendingPromise.promise; + }, + // the dependencies are managed by the caller + // eslint-disable-next-line react-hooks/exhaustive-deps + dependencies + ); + + /** + * Cancel any pending promises silently to avoid memory leaks and race + * conditions. + */ + useEffect( + () => () => { + pendingPromises.current.forEach((promise) => promise.cancelSilently()); + }, + [] + ); + + return [promiseState, execute, reset] as [typeof promiseState, typeof execute, typeof reset]; +}; + +export interface UninitializedPromiseState { + state: 'uninitialized'; +} + +export interface PendingPromiseState { + state: 'pending'; + promise: Promise; +} + +export interface ResolvedPromiseState { + state: 'resolved'; + promise: Promise; + value: ResolvedValue; +} + +export interface RejectedPromiseState { + state: 'rejected'; + promise: Promise; + value: RejectedValue; +} + +export type SettledPromiseState = + | ResolvedPromiseState + | RejectedPromiseState; + +export type PromiseState = + | UninitializedPromiseState + | PendingPromiseState + | SettledPromiseState; + +export const isRejectedPromiseState = ( + promiseState: PromiseState +): promiseState is RejectedPromiseState => promiseState.state === 'rejected'; + +interface CancelablePromise { + // reject the promise prematurely with a CanceledPromiseError + cancel: () => void; + // reject the promise prematurely with a SilentCanceledPromiseError + cancelSilently: () => void; + // the tracked promise + promise: Promise; +} + +export class CanceledPromiseError extends Error { + public isCanceled = true; + + constructor(message?: string) { + super(message); + Object.setPrototypeOf(this, new.target.prototype); + } +} + +export class SilentCanceledPromiseError extends CanceledPromiseError {} + +const noOp = () => undefined; diff --git a/x-pack/plugins/metrics_data_access/server/lib/adapters/framework/adapter_types.ts b/x-pack/plugins/metrics_data_access/server/lib/adapters/framework/adapter_types.ts new file mode 100644 index 0000000000000..d55c1aad0408f --- /dev/null +++ b/x-pack/plugins/metrics_data_access/server/lib/adapters/framework/adapter_types.ts @@ -0,0 +1,182 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import { Lifecycle } from '@hapi/hapi'; +import { SharePluginSetup } from '@kbn/share-plugin/server'; +import { UsageCollectionSetup } from '@kbn/usage-collection-plugin/server'; +import { JsonArray, JsonValue } from '@kbn/utility-types'; +import { RouteConfig, RouteMethod } from '@kbn/core/server'; +import { + PluginSetup as DataPluginSetup, + PluginStart as DataPluginStart, +} from '@kbn/data-plugin/server'; +import { PluginStart as DataViewsPluginStart } from '@kbn/data-views-plugin/server'; +import { HomeServerPluginSetup } from '@kbn/home-plugin/server'; +import { VisTypeTimeseriesSetup } from '@kbn/vis-type-timeseries-plugin/server'; +import { PluginSetupContract as FeaturesPluginSetup } from '@kbn/features-plugin/server'; +import { SpacesPluginSetup } from '@kbn/spaces-plugin/server'; +import { PluginSetupContract as AlertingPluginContract } from '@kbn/alerting-plugin/server'; +import { MlPluginSetup } from '@kbn/ml-plugin/server'; +import { RuleRegistryPluginSetupContract } from '@kbn/rule-registry-plugin/server'; +import { ObservabilityPluginSetup } from '@kbn/observability-plugin/server'; +import { VersionedRouteConfig } from '@kbn/core-http-server'; +import { MetricsDataPluginSetup } from '../../../types'; + +export interface InfraServerPluginSetupDeps { + alerting: AlertingPluginContract; + data: DataPluginSetup; + home: HomeServerPluginSetup; + features: FeaturesPluginSetup; + ruleRegistry: RuleRegistryPluginSetupContract; + observability: ObservabilityPluginSetup; + share: SharePluginSetup; + spaces: SpacesPluginSetup; + usageCollection: UsageCollectionSetup; + visTypeTimeseries: VisTypeTimeseriesSetup; + ml?: MlPluginSetup; + metricsDataAccess: MetricsDataPluginSetup; +} + +export interface InfraServerPluginStartDeps { + data: DataPluginStart; + dataViews: DataViewsPluginStart; +} + +export interface CallWithRequestParams extends estypes.RequestBase { + max_concurrent_shard_requests?: number; + name?: string; + index?: string | string[]; + ignore_unavailable?: boolean; + allow_no_indices?: boolean; + size?: number; + terminate_after?: number; + fields?: estypes.Fields; + path?: string; + query?: string | object; + track_total_hits?: boolean | number; + body?: any; +} + +export type InfraResponse = Lifecycle.ReturnValue; + +export interface InfraFrameworkPluginOptions { + register: any; + options: any; +} + +export interface InfraDatabaseResponse { + took: number; + timeout: boolean; +} + +export interface InfraDatabaseSearchResponse + extends InfraDatabaseResponse { + _shards: { + total: number; + successful: number; + skipped: number; + failed: number; + }; + timed_out: boolean; + aggregations?: Aggregations; + hits: { + total: { + value: number; + relation: string; + }; + hits: Hit[]; + }; +} + +export interface InfraDatabaseMultiResponse extends InfraDatabaseResponse { + responses: Array>; +} + +export interface InfraDatabaseGetIndicesAliasResponse { + [indexName: string]: { + aliases: { + [aliasName: string]: any; + }; + }; +} + +export interface InfraDatabaseGetIndicesResponse { + [indexName: string]: { + aliases: { + [aliasName: string]: any; + }; + mappings: { + _meta: object; + dynamic_templates: any[]; + date_detection: boolean; + properties: { + [fieldName: string]: any; + }; + }; + settings: { index: object }; + }; +} + +export type SearchHit = estypes.SearchHit; + +export interface SortedSearchHit extends SearchHit { + sort: any[]; + _source: { + [field: string]: JsonValue; + }; + fields: { + [field: string]: JsonArray; + }; +} + +export type InfraDateRangeAggregationBucket = { + from?: number; + to?: number; + doc_count: number; + key: string; +} & NestedAggregation; + +export interface InfraDateRangeAggregationResponse { + buckets: Array>; +} + +export interface InfraTopHitsAggregationResponse { + hits: { + hits: []; + }; +} + +export interface InfraMetadataAggregationBucket { + key: string; +} + +export interface InfraMetadataAggregationResponse { + buckets: InfraMetadataAggregationBucket[]; +} + +export interface InfraFieldsResponse { + [name: string]: InfraFieldDef; +} + +export interface InfraFieldDetails { + searchable: boolean; + aggregatable: boolean; + type: string; +} + +export interface InfraFieldDef { + [type: string]: InfraFieldDetails; +} + +export type InfraRouteConfig = { + method: RouteMethod; +} & RouteConfig; + +export type InfraVersionedRouteConfig = { + method: RouteMethod; +} & VersionedRouteConfig; diff --git a/x-pack/plugins/metrics_data_access/server/lib/adapters/framework/index.ts b/x-pack/plugins/metrics_data_access/server/lib/adapters/framework/index.ts new file mode 100644 index 0000000000000..5d7c09c54b8c1 --- /dev/null +++ b/x-pack/plugins/metrics_data_access/server/lib/adapters/framework/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 './adapter_types'; diff --git a/x-pack/plugins/metrics_data_access/server/lib/adapters/framework/kibana_framework_adapter.ts b/x-pack/plugins/metrics_data_access/server/lib/adapters/framework/kibana_framework_adapter.ts new file mode 100644 index 0000000000000..b2d1e5f91ea81 --- /dev/null +++ b/x-pack/plugins/metrics_data_access/server/lib/adapters/framework/kibana_framework_adapter.ts @@ -0,0 +1,239 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import { TransportRequestParams } from '@elastic/elasticsearch'; +import { ElasticsearchClient, SavedObjectsClientContract } from '@kbn/core/server'; +import { + CoreSetup, + IRouter, + RequestHandler, + RouteMethod, + RequestHandlerContext, +} from '@kbn/core/server'; +import { UI_SETTINGS } from '@kbn/data-plugin/server'; +import type { MetricsDataPluginStartDeps } from '../../../types'; +import { + CallWithRequestParams, + InfraDatabaseGetIndicesAliasResponse, + InfraDatabaseGetIndicesResponse, + InfraDatabaseMultiResponse, + InfraDatabaseSearchResponse, + InfraRouteConfig, + InfraVersionedRouteConfig, +} from './adapter_types'; + +interface FrozenIndexParams { + ignore_throttled?: boolean; +} + +export class KibanaFramework { + public router: IRouter; + private core: CoreSetup; + + constructor(core: CoreSetup, router: IRouter) { + this.router = router; + this.core = core; + } + + public registerRoute( + config: InfraRouteConfig, + handler: RequestHandler + ) { + const defaultOptions = { + tags: ['access:infra'], + }; + const routeConfig = { + path: config.path, + validate: config.validate, + // Currently we have no use of custom options beyond tags, this can be extended + // beyond defaultOptions if it's needed. + options: defaultOptions, + }; + switch (config.method) { + case 'get': + this.router.get(routeConfig, handler); + break; + case 'post': + this.router.post(routeConfig, handler); + break; + case 'delete': + this.router.delete(routeConfig, handler); + break; + case 'put': + this.router.put(routeConfig, handler); + break; + case 'patch': + this.router.patch(routeConfig, handler); + break; + } + } + + public registerVersionedRoute( + config: InfraVersionedRouteConfig + ) { + const defaultOptions = { + tags: ['access:infra'], + }; + const routeConfig = { + access: config.access, + path: config.path, + // Currently we have no use of custom options beyond tags, this can be extended + // beyond defaultOptions if it's needed. + options: defaultOptions, + }; + switch (config.method) { + case 'get': + return this.router.versioned.get(routeConfig); + case 'post': + return this.router.versioned.post(routeConfig); + case 'delete': + return this.router.versioned.delete(routeConfig); + case 'put': + return this.router.versioned.put(routeConfig); + case 'patch': + return this.router.versioned.patch(routeConfig); + default: + throw new RangeError( + `#registerVersionedRoute: "${config.method}" is not an accepted method` + ); + } + } + + callWithRequest( + requestContext: RequestHandlerContext, + endpoint: 'search', + options?: CallWithRequestParams + ): Promise>; + callWithRequest( + requestContext: RequestHandlerContext, + endpoint: 'msearch', + options?: CallWithRequestParams + ): Promise>; + callWithRequest( + requestContext: RequestHandlerContext, + endpoint: 'indices.existsAlias', + options?: CallWithRequestParams + ): Promise; + callWithRequest( + requestContext: RequestHandlerContext, + method: 'indices.getAlias', + options?: object + ): Promise; + callWithRequest( + requestContext: RequestHandlerContext, + method: 'indices.get' | 'ml.getBuckets', + options?: object + ): Promise; + callWithRequest( + requestContext: RequestHandlerContext, + method: 'transport.request', + options?: CallWithRequestParams + ): Promise; + callWithRequest( + requestContext: RequestHandlerContext, + endpoint: string, + options?: CallWithRequestParams + ): Promise; + public async callWithRequest( + requestContext: RequestHandlerContext, + endpoint: string, + params: CallWithRequestParams + ) { + const { elasticsearch, uiSettings } = await requestContext.core; + + const includeFrozen = await uiSettings.client.get(UI_SETTINGS.SEARCH_INCLUDE_FROZEN); + if (endpoint === 'msearch') { + const maxConcurrentShardRequests = await uiSettings.client.get( + UI_SETTINGS.COURIER_MAX_CONCURRENT_SHARD_REQUESTS + ); + if (maxConcurrentShardRequests > 0) { + params = { ...params, max_concurrent_shard_requests: maxConcurrentShardRequests }; + } + } + + // Only set the "ignore_throttled" value (to false) if the Kibana setting + // for "search:includeFrozen" is true (i.e. don't ignore throttled indices, a triple negative!) + // More information: + // - https://github.com/elastic/kibana/issues/113197 + // - https://github.com/elastic/elasticsearch/pull/77479 + // + // NOTE: these params only need to be spread onto the search and msearch calls below + const frozenIndicesParams: FrozenIndexParams = {}; + if (includeFrozen) { + frozenIndicesParams.ignore_throttled = false; + } + + let apiResult; + switch (endpoint) { + case 'search': + apiResult = elasticsearch.client.asCurrentUser.search({ + ...params, + ...frozenIndicesParams, + }); + break; + case 'msearch': + apiResult = elasticsearch.client.asCurrentUser.msearch({ + ...params, + ...frozenIndicesParams, + } as estypes.MsearchRequest); + break; + case 'indices.existsAlias': + apiResult = elasticsearch.client.asCurrentUser.indices.existsAlias({ + ...params, + } as estypes.IndicesExistsAliasRequest); + break; + case 'indices.getAlias': + apiResult = elasticsearch.client.asCurrentUser.indices.getAlias({ + ...params, + }); + break; + case 'indices.get': + apiResult = elasticsearch.client.asCurrentUser.indices.get({ + ...params, + } as estypes.IndicesGetRequest); + break; + case 'transport.request': + apiResult = elasticsearch.client.asCurrentUser.transport.request({ + ...params, + } as TransportRequestParams); + break; + case 'ml.getBuckets': + apiResult = elasticsearch.client.asCurrentUser.ml.getBuckets({ + ...params, + } as estypes.MlGetBucketsRequest); + break; + } + return apiResult ? await apiResult : undefined; + } + + public async getIndexPatternsServiceWithRequestContext(requestContext: RequestHandlerContext) { + const { savedObjects, elasticsearch } = await requestContext.core; + return await this.createIndexPatternsService( + savedObjects.client, + elasticsearch.client.asCurrentUser + ); + } + + public async getIndexPatternsService( + savedObjectsClient: SavedObjectsClientContract, + elasticsearchClient: ElasticsearchClient + ) { + return await this.createIndexPatternsService(savedObjectsClient, elasticsearchClient); + } + + private async createIndexPatternsService( + savedObjectsClient: SavedObjectsClientContract, + elasticsearchClient: ElasticsearchClient + ) { + const [, startPlugins] = await this.core.getStartServices(); + return startPlugins.data.indexPatterns.dataViewsServiceFactory( + savedObjectsClient, + elasticsearchClient + ); + } +} diff --git a/x-pack/plugins/metrics_data_access/server/lib/adapters/metrics/adapter_types.ts b/x-pack/plugins/metrics_data_access/server/lib/adapters/metrics/adapter_types.ts new file mode 100644 index 0000000000000..778cc38586c2c --- /dev/null +++ b/x-pack/plugins/metrics_data_access/server/lib/adapters/metrics/adapter_types.ts @@ -0,0 +1,100 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { InventoryMetric } from '../../../../common/inventory_models/types'; + +export enum InfraMetricModelQueryType { + lucene = 'lucene', + kuery = 'kuery', +} + +export enum InfraMetricModelMetricType { + avg = 'avg', + max = 'max', + min = 'min', + calculation = 'calculation', + cardinality = 'cardinality', + series_agg = 'series_agg', + positive_only = 'positive_only', + derivative = 'derivative', + count = 'count', + sum = 'sum', + cumulative_sum = 'cumulative_sum', +} + +export interface InfraMetricModel { + id: InventoryMetric; + requires: string[]; + index_pattern: string | string[]; + interval: string; + time_field: string; + type: string; + series: InfraMetricModelSeries[]; + filter?: string; + map_field_to?: string; + id_type?: 'cloud' | 'node'; +} + +export interface InfraMetricModelSeries { + id: string; + metrics: InfraMetricModelMetric[]; + split_mode: string; + terms_field?: string; + terms_size?: number; + terms_order_by?: string; + filter?: { query: string; language: InfraMetricModelQueryType }; +} + +export interface InfraMetricModelBasicMetric { + id: string; + field?: string | null; + type: InfraMetricModelMetricType; +} + +export interface InfraMetricModelSeriesAgg { + id: string; + function: string; + type: InfraMetricModelMetricType.series_agg; +} + +export interface InfraMetricModelDerivative { + id: string; + field: string; + unit: string; + type: InfraMetricModelMetricType; +} + +export interface InfraMetricModelBucketScriptVariable { + field: string; + id: string; + name: string; +} + +export interface InfraMetricModelCount { + id: string; + type: InfraMetricModelMetricType.count; +} + +export interface InfraMetricModelBucketScript { + id: string; + script: string; + type: InfraMetricModelMetricType.calculation; + variables: InfraMetricModelBucketScriptVariable[]; +} + +export type InfraMetricModelMetric = + | InfraMetricModelCount + | InfraMetricModelBasicMetric + | InfraMetricModelBucketScript + | InfraMetricModelDerivative + | InfraMetricModelSeriesAgg; + +export type InfraMetricModelCreator = ( + timeField: string, + indexPattern: string | string[], + interval: string +) => InfraMetricModel; diff --git a/x-pack/plugins/metrics_data_access/server/lib/adapters/metrics/index.ts b/x-pack/plugins/metrics_data_access/server/lib/adapters/metrics/index.ts new file mode 100644 index 0000000000000..5d7c09c54b8c1 --- /dev/null +++ b/x-pack/plugins/metrics_data_access/server/lib/adapters/metrics/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 './adapter_types'; diff --git a/x-pack/plugins/metrics_data_access/server/lib/create_custom_metrics_aggregations.ts b/x-pack/plugins/metrics_data_access/server/lib/create_custom_metrics_aggregations.ts new file mode 100644 index 0000000000000..13017cc6666b6 --- /dev/null +++ b/x-pack/plugins/metrics_data_access/server/lib/create_custom_metrics_aggregations.ts @@ -0,0 +1,79 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { fromKueryExpression, toElasticsearchQuery } from '@kbn/es-query'; +import { isEmpty } from 'lodash'; +import { MetricExpressionCustomMetric } from '../../common/alerting/metrics'; +import { MetricsExplorerCustomMetric } from '../../common/http_api'; + +const isMetricExpressionCustomMetric = ( + subject: MetricsExplorerCustomMetric | MetricExpressionCustomMetric +): subject is MetricExpressionCustomMetric => { + return (subject as MetricExpressionCustomMetric).aggType != null; +}; + +export const createCustomMetricsAggregations = ( + id: string, + customMetrics: Array, + equation?: string +) => { + const bucketsPath: { [id: string]: string } = {}; + const metricAggregations = customMetrics.reduce((acc, metric) => { + const key = `${id}_${metric.name}`; + const aggregation = isMetricExpressionCustomMetric(metric) + ? metric.aggType + : metric.aggregation; + + if (aggregation === 'count') { + bucketsPath[metric.name] = `${key}>_count`; + return { + ...acc, + [key]: { + filter: metric.filter + ? toElasticsearchQuery(fromKueryExpression(metric.filter)) + : { match_all: {} }, + }, + }; + } + + if (aggregation && metric.field) { + bucketsPath[metric.name] = key; + return { + ...acc, + [key]: { + [aggregation]: { field: metric.field }, + }, + }; + } + + return acc; + }, {}); + + if (isEmpty(metricAggregations)) { + return {}; + } + + return { + ...metricAggregations, + [id]: { + bucket_script: { + buckets_path: bucketsPath, + script: { + source: convertEquationToPainless(bucketsPath, equation), + lang: 'painless', + }, + }, + }, + }; +}; + +const convertEquationToPainless = (bucketsPath: { [id: string]: string }, equation?: string) => { + const workingEquation = equation || Object.keys(bucketsPath).join(' + '); + return Object.keys(bucketsPath).reduce((acc, key) => { + return acc.replaceAll(key, `params.${key}`); + }, workingEquation); +}; diff --git a/x-pack/plugins/metrics_data_access/server/lib/create_search_client.ts b/x-pack/plugins/metrics_data_access/server/lib/create_search_client.ts new file mode 100644 index 0000000000000..6936da480be11 --- /dev/null +++ b/x-pack/plugins/metrics_data_access/server/lib/create_search_client.ts @@ -0,0 +1,17 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { RequestHandlerContext } from '@kbn/core/server'; +import { CallWithRequestParams, InfraDatabaseSearchResponse } from './adapters/framework'; +import { KibanaFramework } from './adapters/framework/kibana_framework_adapter'; + +export const createSearchClient = + (requestContext: RequestHandlerContext, framework: KibanaFramework) => + ( + opts: CallWithRequestParams + ): Promise> => + framework.callWithRequest(requestContext, 'search', opts); diff --git a/x-pack/plugins/metrics_data_access/server/lib/metrics/constants.ts b/x-pack/plugins/metrics_data_access/server/lib/metrics/constants.ts new file mode 100644 index 0000000000000..733f0b8d9376d --- /dev/null +++ b/x-pack/plugins/metrics_data_access/server/lib/metrics/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. + */ + +export const EMPTY_RESPONSE = { + series: [], + info: { total: 0, afterKey: null, interval: 0 }, +}; diff --git a/x-pack/plugins/metrics_data_access/server/lib/metrics/index.ts b/x-pack/plugins/metrics_data_access/server/lib/metrics/index.ts new file mode 100644 index 0000000000000..2f72fb09b7108 --- /dev/null +++ b/x-pack/plugins/metrics_data_access/server/lib/metrics/index.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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { decodeOrThrow } from '../../../common/runtime_types'; +const TIMESTAMP_FIELD = '@timestamp'; +import { MetricsAPIRequest, MetricsAPIResponse } from '../../../common/http_api/metrics_api'; +import { + ESSearchClient, + CompositeResponseRT, + MetricsESResponse, + AggregationResponseRT, + AggregationResponse, + CompositeResponse, + HistogramBucketRT, +} from './types'; +import { EMPTY_RESPONSE } from './constants'; +import { createAggregations, createCompositeAggregations } from './lib/create_aggregations'; +import { convertBucketsToMetricsApiSeries } from './lib/convert_buckets_to_metrics_series'; +import { calculateBucketSize } from './lib/calculate_bucket_size'; +import { calculatedInterval } from './lib/calculate_interval'; + +const DEFAULT_LIMIT = 9; + +export const query = async ( + search: ESSearchClient, + rawOptions: MetricsAPIRequest +): Promise => { + const interval = await calculatedInterval(search, rawOptions); + + const options = { + ...rawOptions, + timerange: { + ...rawOptions.timerange, + interval, + }, + }; + const hasGroupBy = Array.isArray(options.groupBy) && options.groupBy.length > 0; + const filter: Array> = [ + { + range: { + [options.timerange.timeFieldName || TIMESTAMP_FIELD]: { + gte: options.timerange.from, + lte: options.timerange.to, + format: 'epoch_millis', + }, + }, + }, + ...(options.groupBy?.map((field) => ({ exists: { field } })) ?? []), + ]; + + const params = { + allow_no_indices: true, + ignore_unavailable: true, + index: options.indexPattern, + body: { + size: 0, + query: { bool: { filter: [...filter, ...(options.filters ?? [])] } }, + aggs: hasGroupBy ? createCompositeAggregations(options) : createAggregations(options), + }, + }; + + try { + const response = await search<{}, MetricsESResponse>(params); + + if (response.hits.total.value === 0) { + return EMPTY_RESPONSE; + } + + if (!response.aggregations) { + throw new Error('Aggregations should be present.'); + } + + const { bucketSize } = calculateBucketSize({ ...options.timerange, interval }); + + if (hasGroupBy) { + const aggregations = decodeOrThrow(CompositeResponseRT)(response.aggregations); + const { groupings } = aggregations; + const limit = options.limit ?? DEFAULT_LIMIT; + const returnAfterKey = !!groupings.after_key && groupings.buckets.length === limit; + const afterKey = returnAfterKey ? groupings.after_key : null; + + return { + series: getSeriesFromCompositeAggregations(groupings, options, bucketSize * 1000), + info: { + afterKey, + interval: rawOptions.includeTimeseries ? bucketSize : undefined, + }, + }; + } + + const aggregations = decodeOrThrow(AggregationResponseRT)(response.aggregations); + return { + series: getSeriesFromHistogram(aggregations, options, bucketSize * 1000), + info: { + afterKey: null, + interval: bucketSize, + }, + }; + } catch (e) { + throw e; + } +}; + +const getSeriesFromHistogram = ( + aggregations: AggregationResponse, + options: MetricsAPIRequest, + bucketSize: number +): MetricsAPIResponse['series'] => { + return [ + convertBucketsToMetricsApiSeries(['*'], options, aggregations.histogram.buckets, bucketSize), + ]; +}; + +const getSeriesFromCompositeAggregations = ( + groupings: CompositeResponse['groupings'], + options: MetricsAPIRequest, + bucketSize: number +): MetricsAPIResponse['series'] => { + return groupings.buckets.map((bucket) => { + const keys = Object.values(bucket.key); + const metricsetNames = bucket.metricsets.buckets.map((m) => m.key); + const metrics = convertBucketsToMetricsApiSeries( + keys, + options, + HistogramBucketRT.is(bucket) ? bucket.histogram.buckets : [bucket], + bucketSize + ); + return { ...metrics, metricsets: metricsetNames }; + }); +}; diff --git a/x-pack/plugins/metrics_data_access/server/lib/metrics/lib/__snapshots__/convert_buckets_to_metrics_series.test.ts.snap b/x-pack/plugins/metrics_data_access/server/lib/metrics/lib/__snapshots__/convert_buckets_to_metrics_series.test.ts.snap new file mode 100644 index 0000000000000..b49483481693f --- /dev/null +++ b/x-pack/plugins/metrics_data_access/server/lib/metrics/lib/__snapshots__/convert_buckets_to_metrics_series.test.ts.snap @@ -0,0 +1,273 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`convertBucketsToMetricsApiSeries should drop the last bucket 1`] = ` +Object { + "columns": Array [ + Object { + "name": "timestamp", + "type": "date", + }, + Object { + "name": "metric_0", + "type": "number", + }, + ], + "id": "example-0", + "keys": Array [ + "example-0", + ], + "rows": Array [ + Object { + "metric_0": 1, + "timestamp": 1577836800000, + }, + Object { + "metric_0": 1, + "timestamp": 1577836860000, + }, + Object { + "metric_0": 1, + "timestamp": 1577836920000, + }, + Object { + "metric_0": 1, + "timestamp": 1577836980000, + }, + Object { + "metric_0": 1, + "timestamp": 1577837040000, + }, + ], +} +`; + +exports[`convertBucketsToMetricsApiSeries should just work 1`] = ` +Object { + "columns": Array [ + Object { + "name": "timestamp", + "type": "date", + }, + Object { + "name": "metric_0", + "type": "number", + }, + ], + "id": "example-0", + "keys": Array [ + "example-0", + ], + "rows": Array [ + Object { + "metric_0": 1, + "timestamp": 1577836800000, + }, + Object { + "metric_0": 1, + "timestamp": 1577836860000, + }, + Object { + "metric_0": 1, + "timestamp": 1577836920000, + }, + Object { + "metric_0": 1, + "timestamp": 1577836980000, + }, + Object { + "metric_0": 1, + "timestamp": 1577837040000, + }, + Object { + "metric_0": null, + "timestamp": 1577837100000, + }, + ], +} +`; + +exports[`convertBucketsToMetricsApiSeries should return empty timeseries for empty metrics 1`] = ` +Object { + "columns": Array [], + "id": "example-0", + "keys": Array [ + "example-0", + ], + "rows": Array [], +} +`; + +exports[`convertBucketsToMetricsApiSeries should transform top_metric aggregations 1`] = ` +Object { + "columns": Array [ + Object { + "name": "timestamp", + "type": "date", + }, + Object { + "name": "metric_0", + "type": "number", + }, + Object { + "name": "__metadata__", + "type": "number", + }, + ], + "id": "example-0", + "keys": Array [ + "example-0", + ], + "rows": Array [ + Object { + "__metadata__": Array [ + Object { + "host.ip": "testHostIp", + "host.name": "testHostName", + }, + ], + "metric_0": 1, + "timestamp": 1577836800000, + }, + Object { + "__metadata__": Array [], + "metric_0": null, + "timestamp": 1577836860000, + }, + ], +} +`; + +exports[`convertBucketsToMetricsApiSeries should work with keyed percentiles 1`] = ` +Object { + "columns": Array [ + Object { + "name": "timestamp", + "type": "date", + }, + Object { + "name": "metric_0", + "type": "number", + }, + ], + "id": "example-0", + "keys": Array [ + "example-0", + ], + "rows": Array [ + Object { + "metric_0": 4, + "timestamp": 1577836800000, + }, + Object { + "metric_0": 4, + "timestamp": 1577836860000, + }, + Object { + "metric_0": 4, + "timestamp": 1577836920000, + }, + Object { + "metric_0": 4, + "timestamp": 1577836980000, + }, + Object { + "metric_0": 4, + "timestamp": 1577837040000, + }, + Object { + "metric_0": 4, + "timestamp": 1577837100000, + }, + ], +} +`; + +exports[`convertBucketsToMetricsApiSeries should work with normalized_values 1`] = ` +Object { + "columns": Array [ + Object { + "name": "timestamp", + "type": "date", + }, + Object { + "name": "metric_0", + "type": "number", + }, + ], + "id": "example-0", + "keys": Array [ + "example-0", + ], + "rows": Array [ + Object { + "metric_0": 2, + "timestamp": 1577836800000, + }, + Object { + "metric_0": 2, + "timestamp": 1577836860000, + }, + Object { + "metric_0": 2, + "timestamp": 1577836920000, + }, + Object { + "metric_0": 2, + "timestamp": 1577836980000, + }, + Object { + "metric_0": 2, + "timestamp": 1577837040000, + }, + Object { + "metric_0": null, + "timestamp": 1577837100000, + }, + ], +} +`; + +exports[`convertBucketsToMetricsApiSeries should work with percentiles 1`] = ` +Object { + "columns": Array [ + Object { + "name": "timestamp", + "type": "date", + }, + Object { + "name": "metric_0", + "type": "number", + }, + ], + "id": "example-0", + "keys": Array [ + "example-0", + ], + "rows": Array [ + Object { + "metric_0": 3, + "timestamp": 1577836800000, + }, + Object { + "metric_0": 3, + "timestamp": 1577836860000, + }, + Object { + "metric_0": 3, + "timestamp": 1577836920000, + }, + Object { + "metric_0": 3, + "timestamp": 1577836980000, + }, + Object { + "metric_0": 3, + "timestamp": 1577837040000, + }, + Object { + "metric_0": 3, + "timestamp": 1577837100000, + }, + ], +} +`; diff --git a/x-pack/plugins/metrics_data_access/server/lib/metrics/lib/__snapshots__/create_aggregations.test.ts.snap b/x-pack/plugins/metrics_data_access/server/lib/metrics/lib/__snapshots__/create_aggregations.test.ts.snap new file mode 100644 index 0000000000000..d35d7ce1a4b81 --- /dev/null +++ b/x-pack/plugins/metrics_data_access/server/lib/metrics/lib/__snapshots__/create_aggregations.test.ts.snap @@ -0,0 +1,101 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`createAggregations(options) should return add offset to histogram 1`] = ` +Object { + "histogram": Object { + "aggregations": Object { + "metric_0": Object { + "avg": Object { + "field": "system.cpu.user.pct", + }, + }, + }, + "date_histogram": Object { + "extended_bounds": Object { + "max": 1577838720000, + "min": 1577835120000, + }, + "field": "@timestamp", + "fixed_interval": "1m", + "offset": "-60000ms", + }, + }, + "metricsets": Object { + "terms": Object { + "field": "metricset.name", + }, + }, +} +`; + +exports[`createAggregations(options) should return groupings aggregation with groupBy 1`] = ` +Object { + "groupings": Object { + "aggs": Object { + "histogram": Object { + "aggregations": Object { + "metric_0": Object { + "avg": Object { + "field": "system.cpu.user.pct", + }, + }, + }, + "date_histogram": Object { + "extended_bounds": Object { + "max": 1577840400000, + "min": 1577836800000, + }, + "field": "@timestamp", + "fixed_interval": "1m", + "offset": "0s", + }, + }, + "metricsets": Object { + "terms": Object { + "field": "metricset.name", + }, + }, + }, + "composite": Object { + "size": 20, + "sources": Array [ + Object { + "groupBy0": Object { + "terms": Object { + "field": "host.name", + }, + }, + }, + ], + }, + }, +} +`; + +exports[`createAggregations(options) should return just histogram aggregation without groupBy 1`] = ` +Object { + "histogram": Object { + "aggregations": Object { + "metric_0": Object { + "avg": Object { + "field": "system.cpu.user.pct", + }, + }, + }, + "date_histogram": Object { + "extended_bounds": Object { + "max": 1577840400000, + "min": 1577836800000, + }, + "field": "@timestamp", + "fixed_interval": "1m", + "offset": "0s", + }, + }, + "metricsets": Object { + "terms": Object { + "field": "metricset.name", + }, + }, +} +`; diff --git a/x-pack/plugins/metrics_data_access/server/lib/metrics/lib/__snapshots__/create_metrics_aggregations.test.ts.snap b/x-pack/plugins/metrics_data_access/server/lib/metrics/lib/__snapshots__/create_metrics_aggregations.test.ts.snap new file mode 100644 index 0000000000000..36e456c507f24 --- /dev/null +++ b/x-pack/plugins/metrics_data_access/server/lib/metrics/lib/__snapshots__/create_metrics_aggregations.test.ts.snap @@ -0,0 +1,23 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`createMetricsAggregations(options) should just work 1`] = ` +Object { + "metric_0": Object { + "avg": Object { + "field": "system.cpu.user.pct", + }, + }, + "metric_1": Object { + "derivative": Object { + "buckets_path": "metric_1_max", + "gap_policy": "skip", + "unit": "1s", + }, + }, + "metric_1_max": Object { + "max": Object { + "field": "test.field.that.is.a.counter", + }, + }, +} +`; diff --git a/x-pack/plugins/metrics_data_access/server/lib/metrics/lib/calculate_bucket_size/calculate_auto.test.ts b/x-pack/plugins/metrics_data_access/server/lib/metrics/lib/calculate_bucket_size/calculate_auto.test.ts new file mode 100644 index 0000000000000..78211d2940e69 --- /dev/null +++ b/x-pack/plugins/metrics_data_access/server/lib/metrics/lib/calculate_bucket_size/calculate_auto.test.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 { calculateAuto } from './calculate_auto'; +import moment, { isDuration } from 'moment'; + +describe('calculateAuto.near(bucket, duration)', () => { + it('should calculate the bucket size for 15 minutes', () => { + const bucketSizeDuration = calculateAuto.near(100, moment.duration(15, 'minutes')); + expect(bucketSizeDuration).not.toBeUndefined(); + expect(isDuration(bucketSizeDuration)).toBeTruthy(); + expect(bucketSizeDuration!.asSeconds()).toBe(10); + }); + it('should calculate the bucket size for an hour', () => { + const bucketSizeDuration = calculateAuto.near(100, moment.duration(1, 'hour')); + expect(bucketSizeDuration).not.toBeUndefined(); + expect(isDuration(bucketSizeDuration)).toBeTruthy(); + expect(bucketSizeDuration!.asSeconds()).toBe(30); + }); + it('should calculate the bucket size for a day', () => { + const bucketSizeDuration = calculateAuto.near(100, moment.duration(1, 'day')); + expect(bucketSizeDuration).not.toBeUndefined(); + expect(isDuration(bucketSizeDuration)).toBeTruthy(); + expect(bucketSizeDuration!.asMinutes()).toBe(10); + }); +}); diff --git a/x-pack/plugins/metrics_data_access/server/lib/metrics/lib/calculate_bucket_size/calculate_auto.ts b/x-pack/plugins/metrics_data_access/server/lib/metrics/lib/calculate_bucket_size/calculate_auto.ts new file mode 100644 index 0000000000000..99447271ce5f1 --- /dev/null +++ b/x-pack/plugins/metrics_data_access/server/lib/metrics/lib/calculate_bucket_size/calculate_auto.ts @@ -0,0 +1,82 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import moment, { isDuration, Duration } from 'moment'; +const d = moment.duration; + +const roundingRules = [ + [d(500, 'ms'), d(100, 'ms')], + [d(5, 'second'), d(1, 'second')], + [d(7.5, 'second'), d(5, 'second')], + [d(15, 'second'), d(10, 'second')], + [d(45, 'second'), d(30, 'second')], + [d(3, 'minute'), d(1, 'minute')], + [d(9, 'minute'), d(5, 'minute')], + [d(20, 'minute'), d(10, 'minute')], + [d(45, 'minute'), d(30, 'minute')], + [d(2, 'hour'), d(1, 'hour')], + [d(6, 'hour'), d(3, 'hour')], + [d(24, 'hour'), d(12, 'hour')], + [d(1, 'week'), d(1, 'd')], + [d(3, 'week'), d(1, 'week')], + [d(1, 'year'), d(1, 'month')], + [d(Infinity, 'year'), d(1, 'year')], +]; + +const reverseRoundingRules = [...roundingRules].reverse(); +type CheckFunction = (bound: Duration, interval: Duration, target: number) => Duration | undefined; + +function findRule(rules: Duration[][], check: CheckFunction, last?: boolean) { + function pickInterval(buckets: number, duration: Duration) { + const target = duration.asMilliseconds() / buckets; + let lastResult = null; + + for (const [end, start] of rules) { + const result = check(end, start, target); + + if (result == null) { + if (!last) continue; + if (lastResult) return lastResult; + break; + } + + if (!last) return result; + lastResult = result; + } + + // fallback to just a number of milliseconds, ensure ms is >= 1 + const ms = Math.max(Math.floor(target), 1); + return moment.duration(ms, 'ms'); + } + + return (buckets: number, duration: Duration) => { + const interval = pickInterval(buckets, duration); + if (isDuration(interval)) return interval; + }; +} + +export const calculateAuto = { + near: findRule( + reverseRoundingRules, + function near(bound, interval, target) { + if (isDuration(bound) && bound.asMilliseconds() > target) return interval; + }, + true + ), + lessThan: findRule( + reverseRoundingRules, + function lessThan(_bound: Duration, interval: Duration, target: number) { + if (interval.asMilliseconds() < target) return interval; + } + ), + atLeast: findRule( + reverseRoundingRules, + function atLeast(_bound: Duration, interval: Duration, target: number) { + if (interval.asMilliseconds() <= target) return interval; + } + ), +}; diff --git a/x-pack/plugins/metrics_data_access/server/lib/metrics/lib/calculate_bucket_size/calculate_bucket_size.test.ts b/x-pack/plugins/metrics_data_access/server/lib/metrics/lib/calculate_bucket_size/calculate_bucket_size.test.ts new file mode 100644 index 0000000000000..65a87e1662c40 --- /dev/null +++ b/x-pack/plugins/metrics_data_access/server/lib/metrics/lib/calculate_bucket_size/calculate_bucket_size.test.ts @@ -0,0 +1,54 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { calculateBucketSize } from '.'; +import moment from 'moment'; + +const timerange = { + from: moment('2017-01-01T00:00:00.000Z').valueOf(), + to: moment('2017-01-01T01:00:00.000Z').valueOf(), + interval: '1m', + field: '@timetsamp', +}; + +describe('calculateBucketSize(timerange, intervalString)', () => { + test('returns auto calculated buckets', () => { + const result = calculateBucketSize({ ...timerange, interval: 'auto' }); + expect(result).toHaveProperty('bucketSize', 30); + expect(result).toHaveProperty('intervalString', '30s'); + }); + + test('returns overridden buckets (1s)', () => { + const result = calculateBucketSize({ ...timerange, interval: '1s' }); + expect(result).toHaveProperty('bucketSize', 1); + expect(result).toHaveProperty('intervalString', '1s'); + }); + + test('returns overridden buckets (10m)', () => { + const result = calculateBucketSize({ ...timerange, interval: '10m' }); + expect(result).toHaveProperty('bucketSize', 600); + expect(result).toHaveProperty('intervalString', '10m'); + }); + + test('returns overridden buckets (1d)', () => { + const result = calculateBucketSize({ ...timerange, interval: '1d' }); + expect(result).toHaveProperty('bucketSize', 86400); + expect(result).toHaveProperty('intervalString', '1d'); + }); + + test('returns overridden buckets (>=2d)', () => { + const result = calculateBucketSize({ ...timerange, interval: '>=2d' }); + expect(result).toHaveProperty('bucketSize', 86400 * 2); + expect(result).toHaveProperty('intervalString', '2d'); + }); + + test('returns overridden buckets (>=10s)', () => { + const result = calculateBucketSize({ ...timerange, interval: '>=10s' }); + expect(result).toHaveProperty('bucketSize', 30); + expect(result).toHaveProperty('intervalString', '30s'); + }); +}); diff --git a/x-pack/plugins/metrics_data_access/server/lib/metrics/lib/calculate_bucket_size/index.ts b/x-pack/plugins/metrics_data_access/server/lib/metrics/lib/calculate_bucket_size/index.ts new file mode 100644 index 0000000000000..81a399a997bc2 --- /dev/null +++ b/x-pack/plugins/metrics_data_access/server/lib/metrics/lib/calculate_bucket_size/index.ts @@ -0,0 +1,93 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import moment from 'moment'; +import { MetricsAPITimerange } from '../../../../../common/http_api'; +import { calculateAuto } from './calculate_auto'; +import { + getUnitValue, + parseInterval, + convertIntervalToUnit, + ASCENDING_UNIT_ORDER, +} from './unit_to_seconds'; +import { INTERVAL_STRING_RE, GTE_INTERVAL_RE } from './interval_regex'; + +const BUCKET_SIZE = 100; + +const calculateBucketData = (intervalString: string) => { + const intervalStringMatch = intervalString.match(INTERVAL_STRING_RE); + + if (!intervalStringMatch) { + throw new Error('Unable to parse interval string'); + } + + const parsedInterval = parseInterval(intervalString); + + if (!parsedInterval) { + throw new Error('Unable to parse interval string'); + } + + let bucketSize = Number(intervalStringMatch[1]) * getUnitValue(intervalStringMatch[2]); + + // don't go too small + if (bucketSize < 1) { + bucketSize = 1; + } + + // Check decimal + if (parsedInterval.value && parsedInterval.value % 1 !== 0) { + if (parsedInterval.unit && parsedInterval.unit !== 'ms') { + const { value, unit } = convertIntervalToUnit( + intervalString, + ASCENDING_UNIT_ORDER[ASCENDING_UNIT_ORDER.indexOf(parsedInterval.unit) - 1] + ); + + if (value && unit) { + intervalString = value + unit; + } else { + intervalString = '1ms'; + } + } else { + intervalString = '1ms'; + } + } + + return { + bucketSize, + intervalString, + }; +}; + +const calculateBucketSizeForAutoInterval = (timerange: MetricsAPITimerange): number | undefined => { + const duration = moment.duration(timerange.to - timerange.from, 'ms'); + const bucketSizeDuration = calculateAuto.near(BUCKET_SIZE, duration); + + if (bucketSizeDuration) { + return bucketSizeDuration.asSeconds(); + } +}; + +export const calculateBucketSize = (timerange: MetricsAPITimerange) => { + const bucketSize = calculateBucketSizeForAutoInterval(timerange); + let intervalString = `${bucketSize}s`; + + const gteAutoMatch = timerange.interval.match(GTE_INTERVAL_RE); + + if (gteAutoMatch) { + const bucketData = calculateBucketData(gteAutoMatch[1]); + if (bucketSize && bucketData.bucketSize >= bucketSize) { + return bucketData; + } + } + + const matches = timerange.interval.match(INTERVAL_STRING_RE); + if (matches) { + intervalString = timerange.interval; + } + + return calculateBucketData(intervalString); +}; diff --git a/x-pack/plugins/metrics_data_access/server/lib/metrics/lib/calculate_bucket_size/interval_regex.test.ts b/x-pack/plugins/metrics_data_access/server/lib/metrics/lib/calculate_bucket_size/interval_regex.test.ts new file mode 100644 index 0000000000000..5ad3d56707d03 --- /dev/null +++ b/x-pack/plugins/metrics_data_access/server/lib/metrics/lib/calculate_bucket_size/interval_regex.test.ts @@ -0,0 +1,82 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { GTE_INTERVAL_RE, INTERVAL_STRING_RE } from './interval_regex'; + +describe('REGEX for Intervals', () => { + describe('GTE_INTERVAL_RE', () => { + test('returns true for">=12h"', () => { + const value = GTE_INTERVAL_RE.test('>=12h'); + + expect(value).toBeTruthy(); + }); + test('returns true for ">=1y"', () => { + const value = GTE_INTERVAL_RE.test('>=12h'); + + expect(value).toBeTruthy(); + }); + test('returns true for ">=25m"', () => { + const value = GTE_INTERVAL_RE.test('>=12h'); + + expect(value).toBeTruthy(); + }); + test('returns false "auto"', () => { + const value = GTE_INTERVAL_RE.test('auto'); + + expect(value).toBeFalsy(); + }); + test('returns false "wrongInput"', () => { + const value = GTE_INTERVAL_RE.test('wrongInput'); + + expect(value).toBeFalsy(); + }); + test('returns false "d"', () => { + const value = GTE_INTERVAL_RE.test('d'); + + expect(value).toBeFalsy(); + }); + + test('returns false "y"', () => { + const value = GTE_INTERVAL_RE.test('y'); + + expect(value).toBeFalsy(); + }); + }); + + describe('INTERVAL_STRING_RE', () => { + test('returns true for "8d"', () => { + const value = INTERVAL_STRING_RE.test('8d'); + + expect(value).toBeTruthy(); + }); + test('returns true for "1y"', () => { + const value = INTERVAL_STRING_RE.test('1y'); + + expect(value).toBeTruthy(); + }); + test('returns true for "6M"', () => { + const value = INTERVAL_STRING_RE.test('6M'); + + expect(value).toBeTruthy(); + }); + test('returns false "auto"', () => { + const value = INTERVAL_STRING_RE.test('auto'); + + expect(value).toBeFalsy(); + }); + test('returns false "wrongInput"', () => { + const value = INTERVAL_STRING_RE.test('wrongInput'); + + expect(value).toBeFalsy(); + }); + test('returns false for">=21h"', () => { + const value = INTERVAL_STRING_RE.test('>=21h'); + + expect(value).toBeFalsy(); + }); + }); +}); diff --git a/x-pack/plugins/metrics_data_access/server/lib/metrics/lib/calculate_bucket_size/interval_regex.ts b/x-pack/plugins/metrics_data_access/server/lib/metrics/lib/calculate_bucket_size/interval_regex.ts new file mode 100644 index 0000000000000..c53119cb14299 --- /dev/null +++ b/x-pack/plugins/metrics_data_access/server/lib/metrics/lib/calculate_bucket_size/interval_regex.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 dateMath from '@kbn/datemath'; + +export const GTE_INTERVAL_RE = new RegExp(`^>=([\\d\\.]+\\s*(${dateMath.units.join('|')}))$`); +export const INTERVAL_STRING_RE = new RegExp(`^([\\d\\.]+)\\s*(${dateMath.units.join('|')})$`); diff --git a/x-pack/plugins/metrics_data_access/server/lib/metrics/lib/calculate_bucket_size/unit_to_seconds.test.ts b/x-pack/plugins/metrics_data_access/server/lib/metrics/lib/calculate_bucket_size/unit_to_seconds.test.ts new file mode 100644 index 0000000000000..79eb1cda1c858 --- /dev/null +++ b/x-pack/plugins/metrics_data_access/server/lib/metrics/lib/calculate_bucket_size/unit_to_seconds.test.ts @@ -0,0 +1,133 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { + getUnitValue, + parseInterval, + convertIntervalToUnit, + getSuitableUnit, +} from './unit_to_seconds'; + +describe('parseInterval()', () => { + test('should parse "1m" interval (positive)', () => + expect(parseInterval('1m')).toEqual({ + value: 1, + unit: 'm', + })); + + test('should parse "134d" interval (positive)', () => + expect(parseInterval('134d')).toEqual({ + value: 134, + unit: 'd', + })); + + test('should parse "0.5d" interval (positive)', () => + expect(parseInterval('0.5d')).toEqual({ + value: 0.5, + unit: 'd', + })); + + test('should parse "30M" interval (positive)', () => + expect(parseInterval('30M')).toEqual({ + value: 30, + unit: 'M', + })); + + test('should not parse "gm" interval (negative)', () => + expect(parseInterval('gm')).toEqual({ + value: undefined, + unit: undefined, + })); + + test('should not parse "-1d" interval (negative)', () => + expect(parseInterval('-1d')).toEqual({ + value: undefined, + unit: undefined, + })); + + test('should not parse "M" interval (negative)', () => + expect(parseInterval('M')).toEqual({ + value: undefined, + unit: undefined, + })); +}); + +describe('convertIntervalToUnit()', () => { + test('should convert "30m" interval to "h" unit (positive)', () => + expect(convertIntervalToUnit('30m', 'h')).toEqual({ + value: 0.5, + unit: 'h', + })); + + test('should convert "0.5h" interval to "m" unit (positive)', () => + expect(convertIntervalToUnit('0.5h', 'm')).toEqual({ + value: 30, + unit: 'm', + })); + + test('should convert "1h" interval to "m" unit (positive)', () => + expect(convertIntervalToUnit('1h', 'm')).toEqual({ + value: 60, + unit: 'm', + })); + + test('should convert "1h" interval to "ms" unit (positive)', () => + expect(convertIntervalToUnit('1h', 'ms')).toEqual({ + value: 3600000, + unit: 'ms', + })); + + test('should not convert "30m" interval to "0" unit (positive)', () => + expect(convertIntervalToUnit('30m', 'o')).toEqual({ + value: undefined, + unit: undefined, + })); + + test('should not convert "m" interval to "s" unit (positive)', () => + expect(convertIntervalToUnit('m', 's')).toEqual({ + value: undefined, + unit: undefined, + })); +}); + +describe('getSuitableUnit()', () => { + test('should return "d" unit for oneDayInSeconds (positive)', () => { + const oneDayInSeconds = getUnitValue('d') * 1; + + expect(getSuitableUnit(oneDayInSeconds)).toBe('d'); + }); + + test('should return "d" unit for twoDaysInSeconds (positive)', () => { + const twoDaysInSeconds = getUnitValue('d') * 2; + + expect(getSuitableUnit(twoDaysInSeconds)).toBe('d'); + }); + + test('should return "w" unit for threeWeeksInSeconds (positive)', () => { + const threeWeeksInSeconds = getUnitValue('w') * 3; + + expect(getSuitableUnit(threeWeeksInSeconds)).toBe('w'); + }); + + test('should return "y" unit for aroundOneYearInSeconds (positive)', () => { + const aroundOneYearInSeconds = getUnitValue('d') * 370; + + expect(getSuitableUnit(aroundOneYearInSeconds)).toBe('y'); + }); + + test('should return "y" unit for twoYearsInSeconds (positive)', () => { + const twoYearsInSeconds = getUnitValue('y') * 2; + + expect(getSuitableUnit(twoYearsInSeconds)).toBe('y'); + }); + + test('should return "undefined" unit for negativeNumber (negative)', () => { + const negativeNumber = -12; + + expect(getSuitableUnit(negativeNumber)).toBeUndefined(); + }); +}); diff --git a/x-pack/plugins/metrics_data_access/server/lib/metrics/lib/calculate_bucket_size/unit_to_seconds.ts b/x-pack/plugins/metrics_data_access/server/lib/metrics/lib/calculate_bucket_size/unit_to_seconds.ts new file mode 100644 index 0000000000000..742edf9972812 --- /dev/null +++ b/x-pack/plugins/metrics_data_access/server/lib/metrics/lib/calculate_bucket_size/unit_to_seconds.ts @@ -0,0 +1,69 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { sortBy, isNumber } from 'lodash'; +import { INTERVAL_STRING_RE } from './interval_regex'; + +export const ASCENDING_UNIT_ORDER = ['ms', 's', 'm', 'h', 'd', 'w', 'M', 'y']; + +const units: Record = { + ms: 0.001, + s: 1, + m: 60, + h: 3600, + d: 86400, + w: 86400 * 7, + M: 86400 * 30, + y: 86400 * 365, +}; + +const sortedUnits = sortBy(Object.keys(units), (key) => units[key]); + +export const parseInterval = (intervalString: string) => { + let value; + let unit; + + if (intervalString) { + const matches = intervalString.match(INTERVAL_STRING_RE); + + if (matches) { + value = Number(matches[1]); + unit = matches[2]; + } + } + + return { value, unit }; +}; + +export const convertIntervalToUnit = (intervalString: string, newUnit: string) => { + const parsedInterval = parseInterval(intervalString); + let value; + let unit; + + if (parsedInterval.unit && parsedInterval.value && units[newUnit]) { + value = Number( + ((parsedInterval.value * units[parsedInterval.unit]) / units[newUnit]).toFixed(2) + ); + unit = newUnit; + } + + return { value, unit }; +}; + +export const getSuitableUnit = (intervalInSeconds: number) => + sortedUnits.find((key, index, array) => { + const nextUnit = array[index + 1]; + const isValidInput = isNumber(intervalInSeconds) && intervalInSeconds > 0; + const isLastItem = index + 1 === array.length; + + return ( + isValidInput && + ((intervalInSeconds >= units[key] && intervalInSeconds < units[nextUnit]) || isLastItem) + ); + }); + +export const getUnitValue = (unit: string) => units[unit]; diff --git a/x-pack/plugins/metrics_data_access/server/lib/metrics/lib/calculate_date_histogram_offset.test.ts b/x-pack/plugins/metrics_data_access/server/lib/metrics/lib/calculate_date_histogram_offset.test.ts new file mode 100644 index 0000000000000..ef0f64855acd8 --- /dev/null +++ b/x-pack/plugins/metrics_data_access/server/lib/metrics/lib/calculate_date_histogram_offset.test.ts @@ -0,0 +1,52 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { calculateDateHistogramOffset } from './calculate_date_histogram_offset'; +import moment from 'moment'; + +describe('calculateDateHistogramOffset(timerange)', () => { + it('should just work', () => { + const timerange = { + from: moment('2020-01-01T00:03:32').valueOf(), + to: moment('2020-01-01T01:03:32').valueOf(), + interval: '1m', + field: '@timestamp', + }; + const offset = calculateDateHistogramOffset(timerange); + expect(offset).toBe('-28000ms'); + }); + it('should work with un-even timeranges (60s buckets)', () => { + const timerange = { + from: 1625057349373, + to: 1625057649373, + interval: '60s', + field: '@timestamp', + }; + const offset = calculateDateHistogramOffset(timerange); + expect(offset).toBe('-51373ms'); + }); + it('should work with un-even timeranges (5m buckets)', () => { + const timerange = { + from: 1625516185059, + to: 1625602885059, + interval: '5m', + field: '@timestamp', + }; + const offset = calculateDateHistogramOffset(timerange); + expect(offset).toBe('-215059ms'); + }); + it('should work with un-even timeranges (>=10s buckets)', () => { + const timerange = { + from: 1625516185059, + to: 1625602885059, + interval: '>=10s', + field: '@timestamp', + }; + const offset = calculateDateHistogramOffset(timerange); + expect(offset).toBe('-215059ms'); + }); +}); diff --git a/x-pack/plugins/metrics_data_access/server/lib/metrics/lib/calculate_date_histogram_offset.ts b/x-pack/plugins/metrics_data_access/server/lib/metrics/lib/calculate_date_histogram_offset.ts new file mode 100644 index 0000000000000..6f35a624a11da --- /dev/null +++ b/x-pack/plugins/metrics_data_access/server/lib/metrics/lib/calculate_date_histogram_offset.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 { MetricsAPITimerange } from '../../../../common/http_api'; +import { calculateBucketSize } from './calculate_bucket_size'; + +export const calculateDateHistogramOffset = (timerange: MetricsAPITimerange): string => { + const fromInSeconds = Math.floor(timerange.from / 1000); + const { bucketSize } = calculateBucketSize(timerange); + + // negative offset to align buckets with full intervals (e.g. minutes) + const offset = (fromInSeconds % bucketSize) - bucketSize; + + // Because everything is being rounded to the nearest second, except the timerange, + // we need to adjust the buckets to account for the millisecond offset otherwise + // the last bucket will be only contain the difference. + const millisOffset = timerange.to % 1000; + return `${offset * 1000 - millisOffset}ms`; +}; diff --git a/x-pack/plugins/metrics_data_access/server/lib/metrics/lib/calculate_interval.ts b/x-pack/plugins/metrics_data_access/server/lib/metrics/lib/calculate_interval.ts new file mode 100644 index 0000000000000..ee309ad449b2d --- /dev/null +++ b/x-pack/plugins/metrics_data_access/server/lib/metrics/lib/calculate_interval.ts @@ -0,0 +1,34 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { isArray, isNumber } from 'lodash'; +import { MetricsAPIRequest } from '../../../../common/http_api'; +import { ESSearchClient } from '../types'; +import { calculateMetricInterval } from '../../../utils/calculate_metric_interval'; + +export const calculatedInterval = async (search: ESSearchClient, options: MetricsAPIRequest) => { + const useModuleInterval = + options.timerange.interval === 'modules' && + isArray(options.modules) && + options.modules.length > 0; + + const calcualatedInterval = useModuleInterval + ? await calculateMetricInterval( + search, + { + indexPattern: options.indexPattern, + timerange: { from: options.timerange.from, to: options.timerange.to }, + }, + options.modules + ) + : false; + + const defaultInterval = + options.timerange.interval === 'modules' ? 'auto' : options.timerange.interval; + + return isNumber(calcualatedInterval) ? `>=${calcualatedInterval}s` : defaultInterval; +}; diff --git a/x-pack/plugins/metrics_data_access/server/lib/metrics/lib/convert_buckets_to_metrics_series.test.ts b/x-pack/plugins/metrics_data_access/server/lib/metrics/lib/convert_buckets_to_metrics_series.test.ts new file mode 100644 index 0000000000000..bba4e338fc106 --- /dev/null +++ b/x-pack/plugins/metrics_data_access/server/lib/metrics/lib/convert_buckets_to_metrics_series.test.ts @@ -0,0 +1,195 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { MetricsAPIRequest } from '../../../../common/http_api'; +import moment from 'moment'; +import { convertBucketsToMetricsApiSeries } from './convert_buckets_to_metrics_series'; + +const keys = ['example-0']; + +const options: MetricsAPIRequest = { + timerange: { + from: moment('2020-01-01T00:00:00Z').valueOf(), + to: moment('2020-01-01T00:00:00Z').add(5, 'minute').valueOf(), + interval: '1m', + }, + limit: 9, + indexPattern: 'metrics-*', + metrics: [ + { id: 'metric_0', aggregations: { metric_0: { avg: { field: 'system.cpu.user.pct' } } } }, + ], + includeTimeseries: true, +}; + +const buckets = [ + { + key: moment('2020-01-01T00:00:00Z').valueOf(), + key_as_string: moment('2020-01-01T00:00:00Z').toISOString(), + doc_count: 1, + metric_0: { value: 1 }, + }, + { + key: moment('2020-01-01T00:00:00Z').add(1, 'minute').valueOf(), + key_as_string: moment('2020-01-01T00:00:00Z').add(1, 'minute').toISOString(), + doc_count: 1, + metric_0: { value: 1 }, + }, + { + key: moment('2020-01-01T00:00:00Z').add(2, 'minute').valueOf(), + key_as_string: moment('2020-01-01T00:00:00Z').add(2, 'minute').toISOString(), + doc_count: 1, + metric_0: { value: 1 }, + }, + { + key: moment('2020-01-01T00:00:00Z').add(3, 'minute').valueOf(), + key_as_string: moment('2020-01-01T00:00:00Z').add(3, 'minute').toISOString(), + doc_count: 1, + metric_0: { value: 1 }, + }, + { + key: moment('2020-01-01T00:00:00Z').add(4, 'minute').valueOf(), + key_as_string: moment('2020-01-01T00:00:00Z').add(4, 'minute').toISOString(), + doc_count: 1, + metric_0: { value: 1 }, + }, + { + key: moment('2020-01-01T00:00:00Z').add(5, 'minute').valueOf(), + key_as_string: moment('2020-01-01T00:00:00Z').add(5, 'minute').toISOString(), + doc_count: 1, + metric_0: { value: null }, + }, +]; + +describe('convertBucketsToMetricsApiSeries', () => { + it('should just work', () => { + expect(convertBucketsToMetricsApiSeries(keys, options, buckets, 60000)).toMatchSnapshot(); + }); + it('should drop the last bucket', () => { + expect( + convertBucketsToMetricsApiSeries( + keys, + { ...options, dropPartialBuckets: true }, + buckets, + 60000 + ) + ).toMatchSnapshot(); + }); + it('should return empty timeseries for empty metrics', () => { + expect( + convertBucketsToMetricsApiSeries(keys, { ...options, metrics: [] }, buckets, 60000) + ).toMatchSnapshot(); + }); + it('should work with normalized_values', () => { + const bucketsWithNormalizedValue = buckets.map((bucket) => { + const value = bucket.metric_0.value; + if (value) { + return { ...bucket, metric_0: { value, normalized_value: value + 1 } }; + } + return bucket; + }); + expect( + convertBucketsToMetricsApiSeries(keys, { ...options }, bucketsWithNormalizedValue, 60000) + ).toMatchSnapshot(); + }); + it('should work with percentiles', () => { + const bucketsWithPercentiles = buckets.map((bucket) => { + return { ...bucket, metric_0: { values: { '95.0': 3 } } }; + }); + expect( + convertBucketsToMetricsApiSeries(keys, { ...options }, bucketsWithPercentiles, 60000) + ).toMatchSnapshot(); + }); + it('should throw error with multiple percentiles', () => { + const bucketsWithMultiplePercentiles = buckets.map((bucket) => { + return { ...bucket, metric_0: { values: { '95.0': 3, '99.0': 4 } } }; + }); + expect(() => + convertBucketsToMetricsApiSeries(keys, { ...options }, bucketsWithMultiplePercentiles, 60000) + ).toThrow(); + }); + it('should work with keyed percentiles', () => { + const bucketsWithKeyedPercentiles = buckets.map((bucket) => { + return { ...bucket, metric_0: { values: [{ key: '99.0', value: 4 }] } }; + }); + expect( + convertBucketsToMetricsApiSeries(keys, { ...options }, bucketsWithKeyedPercentiles, 60000) + ).toMatchSnapshot(); + }); + it('should throw error with multiple keyed percentiles', () => { + const bucketsWithMultipleKeyedPercentiles = buckets.map((bucket) => { + return { + ...bucket, + metric_0: { + values: [ + { key: '95.0', value: 3 }, + { key: '99.0', value: 4 }, + ], + }, + }; + }); + expect(() => + convertBucketsToMetricsApiSeries( + keys, + { ...options }, + bucketsWithMultipleKeyedPercentiles, + 60000 + ) + ).toThrow(); + }); + + it('should transform top_metric aggregations', () => { + const topMetricOptions: MetricsAPIRequest = { + ...options, + metrics: [ + { id: 'metric_0', aggregations: { metric_0: { avg: { field: 'system.cpu.user.pct' } } } }, + { + id: '__metadata__', + aggregations: { + __metadata__: { + top_metrics: { + metrics: [{ field: 'host.name' }, { field: 'host.ip' }], + }, + }, + }, + }, + ], + }; + + const bucketsWithTopAggregation = [ + { + key: 1577836800000, + key_as_string: '2020-01-01T00:00:00.000Z', + doc_count: 1, + metric_0: { value: 1 }, + __metadata__: { + top: [ + { + sort: ['2021-03-30T13:46:27.684Z'], + metrics: { + 'host.name': 'testHostName', + 'host.ip': 'testHostIp', + }, + }, + ], + }, + }, + { + key: 1577836860000, + key_as_string: '2020-01-01T00:01:00.000Z', + doc_count: 1, + metric_0: { value: null }, + __metadata__: { + top: [], + }, + }, + ]; + + expect( + convertBucketsToMetricsApiSeries(keys, topMetricOptions, bucketsWithTopAggregation, 60000) + ).toMatchSnapshot(); + }); +}); diff --git a/x-pack/plugins/metrics_data_access/server/lib/metrics/lib/convert_buckets_to_metrics_series.ts b/x-pack/plugins/metrics_data_access/server/lib/metrics/lib/convert_buckets_to_metrics_series.ts new file mode 100644 index 0000000000000..56ee719c931ec --- /dev/null +++ b/x-pack/plugins/metrics_data_access/server/lib/metrics/lib/convert_buckets_to_metrics_series.ts @@ -0,0 +1,118 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { get, values, first } from 'lodash'; +import * as rt from 'io-ts'; +import { + MetricsAPIRequest, + MetricsAPISeries, + MetricsAPIColumn, + MetricsAPIRow, +} from '../../../../common/http_api/metrics_api'; +import { + Bucket, + BasicMetricValueRT, + NormalizedMetricValueRT, + PercentilesTypeRT, + PercentilesKeyedTypeRT, + TopMetricsTypeRT, + MetricValueTypeRT, +} from '../types'; + +const BASE_COLUMNS = [{ name: 'timestamp', type: 'date' }] as MetricsAPIColumn[]; + +const ValueObjectTypeRT = rt.union([rt.string, rt.number, MetricValueTypeRT]); +type ValueObjectType = rt.TypeOf; + +const getValue = (valueObject: ValueObjectType) => { + if (NormalizedMetricValueRT.is(valueObject)) { + return valueObject.normalized_value || valueObject.value; + } + + if (PercentilesTypeRT.is(valueObject)) { + const percentileValues = values(valueObject.values); + if (percentileValues.length > 1) { + throw new Error( + 'Metrics API only supports a single percentile, multiple percentiles should be sent separately' + ); + } + return first(percentileValues) || null; + } + + if (PercentilesKeyedTypeRT.is(valueObject)) { + if (valueObject.values.length > 1) { + throw new Error( + 'Metrics API only supports a single percentile, multiple percentiles should be sent separately' + ); + } + const percentileValue = first(valueObject.values); + return (percentileValue && percentileValue.value) || null; + } + + if (BasicMetricValueRT.is(valueObject)) { + return valueObject.value; + } + + if (TopMetricsTypeRT.is(valueObject)) { + return valueObject.top.map((res) => res.metrics); + } + + return null; +}; + +const dropOutOfBoundsBuckets = + (from: number, to: number, bucketSizeInMillis: number) => (row: MetricsAPIRow) => + row.timestamp >= from && row.timestamp + bucketSizeInMillis <= to; + +export const convertBucketsToRows = ( + options: MetricsAPIRequest, + buckets: Bucket[] +): MetricsAPIRow[] => { + return buckets.map((bucket) => { + const ids = options.metrics.map((metric) => metric.id); + const metrics = ids.reduce((acc, id) => { + const valueObject = get(bucket, [id]); + acc[id] = ValueObjectTypeRT.is(valueObject) ? getValue(valueObject) : null; + return acc; + }, {} as Record); + + return { timestamp: bucket.key as number, ...metrics }; + }); +}; + +export const convertBucketsToMetricsApiSeries = ( + keys: string[], + options: MetricsAPIRequest, + buckets: Bucket[], + bucketSizeInMillis: number +): MetricsAPISeries => { + const id = keys.join(':'); + // If there are no metrics then we just return the empty series + // but still maintain the groupings. + if (options.metrics.length === 0) { + return { id, keys, columns: [], rows: [] }; + } + const columns = options.metrics.map((metric) => ({ + name: metric.id, + type: 'number', + })) as MetricsAPIColumn[]; + const allRows = convertBucketsToRows(options, buckets); + + const rows = + options.dropPartialBuckets && options.includeTimeseries + ? allRows.filter( + dropOutOfBoundsBuckets(options.timerange.from, options.timerange.to, bucketSizeInMillis) + ) + : allRows; + + return { + id, + keys, + rows, + columns: [...BASE_COLUMNS, ...columns], + }; +}; diff --git a/x-pack/plugins/metrics_data_access/server/lib/metrics/lib/create_aggregations.test.ts b/x-pack/plugins/metrics_data_access/server/lib/metrics/lib/create_aggregations.test.ts new file mode 100644 index 0000000000000..120faa40ccd00 --- /dev/null +++ b/x-pack/plugins/metrics_data_access/server/lib/metrics/lib/create_aggregations.test.ts @@ -0,0 +1,86 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { createAggregations, createCompositeAggregations } from './create_aggregations'; +import moment from 'moment'; +import { MetricsAPIRequest } from '../../../../common/http_api'; + +const options: MetricsAPIRequest = { + timerange: { + from: moment('2020-01-01T00:00:00Z').valueOf(), + to: moment('2020-01-01T01:00:00Z').valueOf(), + interval: '>=1m', + }, + limit: 20, + indexPattern: 'metrics-*', + metrics: [ + { id: 'metric_0', aggregations: { metric_0: { avg: { field: 'system.cpu.user.pct' } } } }, + ], + includeTimeseries: true, +}; + +describe('createAggregations(options)', () => { + it('should return groupings aggregation with groupBy', () => { + const optionsWithGroupBy: MetricsAPIRequest = { ...options, groupBy: ['host.name'] }; + expect(createCompositeAggregations(optionsWithGroupBy)).toMatchSnapshot(); + }); + it('should return groupings aggregation with afterKey', () => { + const optionsWithGroupBy: MetricsAPIRequest = { + ...options, + groupBy: ['host.name'], + afterKey: { group0: 'host-0' }, + }; + expect(createCompositeAggregations(optionsWithGroupBy)).toEqual({ + groupings: expect.objectContaining({ + composite: expect.objectContaining({ + after: { group0: 'host-0' }, + }), + }), + }); + }); + + it('should return groupings aggregation without date histogram', () => { + const optionsWithGroupBy: MetricsAPIRequest = { + ...options, + groupBy: ['host.name'], + includeTimeseries: false, + }; + expect(createCompositeAggregations(optionsWithGroupBy)).toEqual({ + groupings: expect.objectContaining({ + aggs: { + metric_0: { + avg: { + field: 'system.cpu.user.pct', + }, + }, + metricsets: { + terms: { + field: 'metricset.name', + }, + }, + }, + }), + }); + }); + + it('should return just histogram aggregation without groupBy', () => { + expect(createAggregations(options)).toMatchSnapshot(); + }); + + it('should return add offset to histogram', () => { + const optionsWithAlignDataToEnd = { + ...options, + timerange: { + ...options.timerange, + from: moment('2020-01-01T00:00:00Z').subtract(28, 'minutes').valueOf(), + to: moment('2020-01-01T01:00:00Z').subtract(28, 'minutes').valueOf(), + }, + alignDataToEnd: true, + }; + expect(createAggregations(optionsWithAlignDataToEnd)).toMatchSnapshot(); + }); +}); diff --git a/x-pack/plugins/metrics_data_access/server/lib/metrics/lib/create_aggregations.ts b/x-pack/plugins/metrics_data_access/server/lib/metrics/lib/create_aggregations.ts new file mode 100644 index 0000000000000..b017129401c1b --- /dev/null +++ b/x-pack/plugins/metrics_data_access/server/lib/metrics/lib/create_aggregations.ts @@ -0,0 +1,98 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { AggregationOptionsByType } from '@kbn/es-types'; + +import Boom from '@hapi/boom'; +import { afterKeyObjectRT } from '../../../../common/http_api'; +import { TIMESTAMP_FIELD } from '../../../../common/constants'; +import { MetricsAPIRequest } from '../../../../common/http_api/metrics_api'; +import { calculateDateHistogramOffset } from './calculate_date_histogram_offset'; +import { createMetricsAggregations } from './create_metrics_aggregations'; +import { calculateBucketSize } from './calculate_bucket_size'; + +const DEFAULT_LIMIT = 9; +const METRICSET_AGGS = { + metricsets: { + terms: { + field: 'metricset.name', + }, + }, +}; + +type MetricsAggregation = ReturnType; +interface HistogramAggregation { + histogram: { + date_histogram: AggregationOptionsByType['date_histogram']; + aggregations: MetricsAggregation; + }; +} + +const createMetricHistogramAggs = (options: MetricsAPIRequest): HistogramAggregation => { + const { intervalString } = calculateBucketSize(options.timerange); + return { + histogram: { + date_histogram: { + field: options.timerange.timeFieldName || TIMESTAMP_FIELD, + fixed_interval: intervalString, + offset: options.alignDataToEnd ? calculateDateHistogramOffset(options.timerange) : '0s', + extended_bounds: { + min: options.timerange.from, + max: options.timerange.to, + }, + }, + aggregations: createMetricsAggregations(options), + }, + }; +}; + +const getAfterKey = (options: MetricsAPIRequest) => { + if (!options.afterKey) { + return null; + } + if (afterKeyObjectRT.is(options.afterKey)) { + return options.afterKey; + } else { + return { groupBy0: options.afterKey }; + } +}; +export const createCompositeAggregations = (options: MetricsAPIRequest) => { + if (!Array.isArray(options.groupBy) || !options.groupBy.length) { + throw Boom.badRequest('groupBy must be informed.'); + } + + if (!options.includeTimeseries && !!options.metrics.find((p) => p.id === 'logRate')) { + throw Boom.badRequest('logRate metric is not supported without time series'); + } + + const after = getAfterKey(options); + + return { + groupings: { + composite: { + size: options.limit ?? DEFAULT_LIMIT, + sources: options.groupBy.map((field, index) => ({ + [`groupBy${index}`]: { terms: { field } }, + })), + ...(after ? { after } : {}), + }, + aggs: { + ...(options.includeTimeseries + ? createMetricHistogramAggs(options) + : createMetricsAggregations(options)), + ...METRICSET_AGGS, + }, + }, + }; +}; + +export const createAggregations = (options: MetricsAPIRequest) => { + return { + ...createMetricHistogramAggs(options), + ...METRICSET_AGGS, + }; +}; diff --git a/x-pack/plugins/metrics_data_access/server/lib/metrics/lib/create_metrics_aggregations.test.ts b/x-pack/plugins/metrics_data_access/server/lib/metrics/lib/create_metrics_aggregations.test.ts new file mode 100644 index 0000000000000..ef57aa05085a3 --- /dev/null +++ b/x-pack/plugins/metrics_data_access/server/lib/metrics/lib/create_metrics_aggregations.test.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 { MetricsAPIRequest } from '../../../../common/http_api'; +import moment from 'moment'; +import { createMetricsAggregations } from './create_metrics_aggregations'; + +const options: MetricsAPIRequest = { + timerange: { + from: moment('2020-01-01T00:00:00Z').valueOf(), + to: moment('2020-01-01T01:00:00Z').valueOf(), + interval: '>=1m', + }, + limit: 20, + indexPattern: 'metrics-*', + metrics: [ + { id: 'metric_0', aggregations: { metric_0: { avg: { field: 'system.cpu.user.pct' } } } }, + { + id: 'metric_1', + aggregations: { + metric_1_max: { max: { field: 'test.field.that.is.a.counter' } }, + metric_1: { derivative: { buckets_path: 'metric_1_max', gap_policy: 'skip', unit: '1s' } }, + }, + }, + ], + includeTimeseries: true, +}; + +describe('createMetricsAggregations(options)', () => { + it('should just work', () => { + expect(createMetricsAggregations(options)).toMatchSnapshot(); + }); +}); diff --git a/x-pack/plugins/metrics_data_access/server/lib/metrics/lib/create_metrics_aggregations.ts b/x-pack/plugins/metrics_data_access/server/lib/metrics/lib/create_metrics_aggregations.ts new file mode 100644 index 0000000000000..7ab96a870cd1e --- /dev/null +++ b/x-pack/plugins/metrics_data_access/server/lib/metrics/lib/create_metrics_aggregations.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 { MetricsUIAggregation } from '../../../../common/inventory_models/types'; +import { MetricsAPIRequest } from '../../../../common/http_api/metrics_api'; + +export const createMetricsAggregations = (options: MetricsAPIRequest): MetricsUIAggregation => { + const { metrics } = options; + return metrics.reduce((aggs, metric) => { + return Object.assign(aggs, metric.aggregations); + }, {}); +}; diff --git a/x-pack/plugins/metrics_data_access/server/lib/metrics/types.ts b/x-pack/plugins/metrics_data_access/server/lib/metrics/types.ts new file mode 100644 index 0000000000000..0c87e8eca47d9 --- /dev/null +++ b/x-pack/plugins/metrics_data_access/server/lib/metrics/types.ts @@ -0,0 +1,121 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import * as rt from 'io-ts'; +import { InfraDatabaseSearchResponse, CallWithRequestParams } from '../adapters/framework'; + +export type ESSearchClient = ( + options: CallWithRequestParams +) => Promise>; + +const NumberOrNullRT = rt.union([rt.number, rt.null]); + +export const BasicMetricValueRT = rt.type({ value: NumberOrNullRT }); + +export const NormalizedMetricValueRT = rt.intersection([ + BasicMetricValueRT, + rt.type({ normalized_value: NumberOrNullRT }), +]); +export const PercentilesTypeRT = rt.type({ values: rt.record(rt.string, NumberOrNullRT) }); + +export const PercentilesKeyedTypeRT = rt.type({ + values: rt.array(rt.type({ key: rt.string, value: NumberOrNullRT })), +}); + +export const TopMetricsTypeRT = rt.type({ + top: rt.array( + rt.type({ + sort: rt.union([rt.array(rt.number), rt.array(rt.string)]), + metrics: rt.record(rt.string, rt.union([rt.number, rt.string, rt.null])), + }) + ), +}); + +export const MaxPeriodFilterExistsTypeRT = rt.type({ + doc_count: rt.number, + period: BasicMetricValueRT, +}); + +export const MetricValueTypeRT = rt.union([ + BasicMetricValueRT, + NormalizedMetricValueRT, + PercentilesTypeRT, + PercentilesKeyedTypeRT, + TopMetricsTypeRT, + MaxPeriodFilterExistsTypeRT, +]); +export type MetricValueType = rt.TypeOf; + +export const TermsWithMetrics = rt.intersection([ + rt.type({ + buckets: rt.array(rt.record(rt.string, rt.union([rt.number, rt.string, MetricValueTypeRT]))), + }), + rt.partial({ + sum_other_doc_count: rt.number, + doc_count_error_upper_bound: rt.number, + }), +]); + +export const BucketRT = rt.record( + rt.string, + rt.union([ + rt.number, + rt.string, + MetricValueTypeRT, + TermsWithMetrics, + rt.record(rt.string, rt.string), + rt.type({ doc_count: rt.number }), + ]) +); + +export const MetricsetRT = rt.type({ + buckets: rt.array( + rt.type({ + key: rt.string, + doc_count: rt.number, + }) + ), +}); + +export const HistogramRT = rt.type({ + histogram: rt.type({ + buckets: rt.array(BucketRT), + }), + metricsets: MetricsetRT, +}); + +export const MetricsBucketRT = rt.intersection([BucketRT, rt.type({ metricsets: MetricsetRT })]); +export const HistogramBucketRT = rt.intersection([ + rt.type({ + key: rt.record(rt.string, rt.string), + doc_count: rt.number, + }), + HistogramRT, +]); + +export const AggregationResponseRT = HistogramRT; + +export const CompositeResponseRT = rt.type({ + groupings: rt.intersection([ + rt.type({ + buckets: rt.array(rt.union([HistogramBucketRT, MetricsBucketRT])), + }), + rt.partial({ + after_key: rt.record(rt.string, rt.string), + }), + ]), +}); + +export type Bucket = rt.TypeOf; +export type HistogramBucket = rt.TypeOf; +export type CompositeResponse = rt.TypeOf; +export type AggregationResponse = rt.TypeOf; +export type MetricsESResponse = AggregationResponse | CompositeResponse; + +export interface LogQueryFields { + indexPattern: string; +} diff --git a/x-pack/plugins/metrics_data_access/server/plugin.ts b/x-pack/plugins/metrics_data_access/server/plugin.ts index 0f51a7a33f888..597c63c2d8ebb 100644 --- a/x-pack/plugins/metrics_data_access/server/plugin.ts +++ b/x-pack/plugins/metrics_data_access/server/plugin.ts @@ -5,17 +5,34 @@ * 2.0. */ -import { CoreSetup, PluginInitializerContext, Plugin } from '@kbn/core/server'; -import { MetricsDataPluginSetup } from './types'; +import { + CoreSetup, + PluginInitializerContext, + Plugin, + RequestHandlerContext, +} from '@kbn/core/server'; +import { MetricsDataPluginSetup, MetricsDataPluginStartDeps } from './types'; import { MetricsDataClient } from './client'; import { metricsDataSourceSavedObjectType } from './saved_objects/metrics_data_source'; +import { KibanaFramework } from './lib/adapters/framework/kibana_framework_adapter'; +import { initMetricExplorerRoute } from './routes/metrics_explorer'; +import { initMetricIndicesRoute } from './routes/metric_indices'; export class MetricsDataPlugin implements Plugin { private metricsClient: MetricsDataClient | null = null; constructor(context: PluginInitializerContext) {} - public setup(core: CoreSetup) { + public setup(core: CoreSetup) { + const router = core.http.createRouter(); + const framework = new KibanaFramework(core, router); + + initMetricExplorerRoute(framework); + initMetricIndicesRoute({ + router, + metricsClient: new MetricsDataClient(), + }); + core.savedObjects.registerType(metricsDataSourceSavedObjectType); this.metricsClient = new MetricsDataClient(); diff --git a/x-pack/plugins/metrics_data_access/server/routes/metric_indices/index.ts b/x-pack/plugins/metrics_data_access/server/routes/metric_indices/index.ts new file mode 100644 index 0000000000000..ebd4ed1943f20 --- /dev/null +++ b/x-pack/plugins/metrics_data_access/server/routes/metric_indices/index.ts @@ -0,0 +1,65 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { ElasticsearchClient } from '@kbn/core/server'; +import { RequestHandlerContext } from '@kbn/core-http-request-handler-context-server'; +import { SearchTotalHits } from '@elastic/elasticsearch/lib/api/types'; +import { SetupRouteOptions } from '../types'; +import { MetricIndicesAPIResponse } from '../../../common/http_api/metric_indices'; + +function getIndexStatus(client: ElasticsearchClient, index: string) { + return client + .search({ + ignore_unavailable: true, + allow_no_indices: true, + index, + size: 0, + terminate_after: 1, + track_total_hits: 1, + }) + .then( + (response) => { + if (response._shards.total <= 0) { + return 'missing'; + } + + if ((response.hits.total as SearchTotalHits).value > 0) { + return 'available'; + } + + return 'empty'; + }, + (err) => { + if (err.status === 404) { + return 'missing'; + } + + throw err; + } + ); +} + +export function initMetricIndicesRoute({ + router, + metricsClient, +}: SetupRouteOptions) { + router.get( + { + path: `/api/metrics/indices`, + validate: false, + }, + async (context, _req, res) => { + const savedObjectsClient = (await context.core).savedObjects.client; + const esClient = (await context.core).elasticsearch.client.asCurrentUser; + const metricIndices = await metricsClient.getMetricIndices({ savedObjectsClient }); + const metricIndicesStatus = await getIndexStatus(esClient, metricIndices); + return res.ok({ + body: { metricIndices, metricIndicesExist: metricIndicesStatus !== 'missing' }, + }); + } + ); +} diff --git a/x-pack/plugins/metrics_data_access/server/routes/metrics_explorer/index.ts b/x-pack/plugins/metrics_data_access/server/routes/metrics_explorer/index.ts new file mode 100644 index 0000000000000..2dc36c89c7dde --- /dev/null +++ b/x-pack/plugins/metrics_data_access/server/routes/metrics_explorer/index.ts @@ -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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import Boom from '@hapi/boom'; +import { pipe } from 'fp-ts/lib/pipeable'; +import { fold } from 'fp-ts/lib/Either'; +import { identity } from 'fp-ts/lib/function'; +import { schema } from '@kbn/config-schema'; +import { + metricsExplorerRequestBodyRT, + metricsExplorerResponseRT, + MetricsExplorerPageInfo, +} from '../../../common/http_api/metrics_explorer'; +import { throwErrors } from '../../../common/runtime_types'; +import { convertRequestToMetricsAPIOptions } from './lib/convert_request_to_metrics_api_options'; +import { createSearchClient } from '../../lib/create_search_client'; +import { findIntervalForMetrics } from './lib/find_interval_for_metrics'; +import { query } from '../../lib/metrics'; +import { queryTotalGroupings } from './lib/query_total_groupings'; +import { transformSeries } from './lib/transform_series'; +import { KibanaFramework } from '../../lib/adapters/framework/kibana_framework_adapter'; + +const escapeHatch = schema.object({}, { unknowns: 'allow' }); + +export const initMetricExplorerRoute = (framework: KibanaFramework) => { + framework.registerRoute( + { + method: 'post', + path: '/api/infra/metrics_explorer', + validate: { + body: escapeHatch, + }, + }, + async (requestContext, request, response) => { + const options = pipe( + metricsExplorerRequestBodyRT.decode(request.body), + fold(throwErrors(Boom.badRequest), identity) + ); + + const client = createSearchClient(requestContext, framework); + const interval = await findIntervalForMetrics(client, options); + + const optionsWithInterval = options.forceInterval + ? options + : { + ...options, + timerange: { + ...options.timerange, + interval: interval ? `>=${interval}s` : options.timerange.interval, + }, + }; + + const metricsApiOptions = convertRequestToMetricsAPIOptions(optionsWithInterval); + const metricsApiResponse = await query(client, metricsApiOptions); + const totalGroupings = await queryTotalGroupings(client, metricsApiOptions); + const hasGroupBy = + Array.isArray(metricsApiOptions.groupBy) && metricsApiOptions.groupBy.length > 0; + + const pageInfo: MetricsExplorerPageInfo = { + total: totalGroupings, + afterKey: null, + }; + + if (metricsApiResponse.info.afterKey) { + pageInfo.afterKey = metricsApiResponse.info.afterKey; + } + + // If we have a groupBy but there are ZERO groupings returned then we need to + // return an empty array. Otherwise we transform the series to match the current schema. + const series = + hasGroupBy && totalGroupings === 0 + ? [] + : metricsApiResponse.series.map(transformSeries(hasGroupBy)); + + return response.ok({ + body: metricsExplorerResponseRT.encode({ series, pageInfo }), + }); + } + ); +}; diff --git a/x-pack/plugins/metrics_data_access/server/routes/metrics_explorer/lib/convert_metric_to_metrics_api_metric.test.ts b/x-pack/plugins/metrics_data_access/server/routes/metrics_explorer/lib/convert_metric_to_metrics_api_metric.test.ts new file mode 100644 index 0000000000000..6e391aeb45246 --- /dev/null +++ b/x-pack/plugins/metrics_data_access/server/routes/metrics_explorer/lib/convert_metric_to_metrics_api_metric.test.ts @@ -0,0 +1,89 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { convertMetricToMetricsAPIMetric } from './convert_metric_to_metrics_api_metric'; +import { + MetricsExplorerMetric, + MetricsAPIMetric, + MetricsExplorerAggregation, +} from '../../../../common/http_api'; + +describe('convertMetricToMetricsAPIMetric(metric, index)', () => { + const runTest = (metric: MetricsExplorerMetric, aggregation: MetricsAPIMetric) => + it(`should convert ${metric.aggregation}`, () => { + expect(convertMetricToMetricsAPIMetric(metric, 1)).toEqual(aggregation); + }); + + const runTestForBasic = (aggregation: MetricsExplorerAggregation) => + runTest( + { aggregation, field: 'system.cpu.user.pct' }, + { + id: 'metric_1', + aggregations: { metric_1: { [aggregation]: { field: 'system.cpu.user.pct' } } }, + } + ); + + runTestForBasic('avg'); + runTestForBasic('sum'); + runTestForBasic('max'); + runTestForBasic('min'); + runTestForBasic('cardinality'); + + runTest( + { aggregation: 'rate', field: 'test.field.that.is.a.counter' }, + { + id: 'metric_1', + aggregations: { + metric_1_max: { + max: { + field: 'test.field.that.is.a.counter', + }, + }, + metric_1_deriv: { + derivative: { + buckets_path: 'metric_1_max', + gap_policy: 'skip', + unit: '1s', + }, + }, + metric_1: { + bucket_script: { + buckets_path: { + value: 'metric_1_deriv[normalized_value]', + }, + gap_policy: 'skip', + script: { + lang: 'painless', + source: 'params.value > 0.0 ? params.value : 0.0', + }, + }, + }, + }, + } + ); + + runTest( + { aggregation: 'count' }, + { + id: 'metric_1', + aggregations: { + metric_1: { + bucket_script: { + buckets_path: { + count: '_count', + }, + gap_policy: 'skip', + script: { + lang: 'expression', + source: 'count * 1', + }, + }, + }, + }, + } + ); +}); diff --git a/x-pack/plugins/metrics_data_access/server/routes/metrics_explorer/lib/convert_metric_to_metrics_api_metric.ts b/x-pack/plugins/metrics_data_access/server/routes/metrics_explorer/lib/convert_metric_to_metrics_api_metric.ts new file mode 100644 index 0000000000000..299bc75f03114 --- /dev/null +++ b/x-pack/plugins/metrics_data_access/server/routes/metrics_explorer/lib/convert_metric_to_metrics_api_metric.ts @@ -0,0 +1,82 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { isEmpty } from 'lodash'; +import { networkTraffic } from '../../../../common/inventory_models/shared/metrics/snapshot/network_traffic'; +import { MetricsAPIMetric, MetricsExplorerMetric } from '../../../../common/http_api'; +import { createCustomMetricsAggregations } from '../../../lib/create_custom_metrics_aggregations'; + +export const convertMetricToMetricsAPIMetric = ( + metric: MetricsExplorerMetric, + index: number +): MetricsAPIMetric | undefined => { + const id = `metric_${index}`; + if (metric.aggregation === 'rate' && metric.field) { + return { + id, + aggregations: networkTraffic(id, metric.field), + }; + } + + if (['p95', 'p99'].includes(metric.aggregation) && metric.field) { + const percent = metric.aggregation === 'p95' ? 95 : 99; + return { + id, + aggregations: { + [id]: { + percentiles: { + field: metric.field, + percents: [percent], + }, + }, + }, + }; + } + + if (['max', 'min', 'avg', 'cardinality', 'sum'].includes(metric.aggregation) && metric.field) { + return { + id, + aggregations: { + [id]: { + [metric.aggregation]: { field: metric.field }, + }, + }, + }; + } + + if (metric.aggregation === 'count') { + return { + id, + aggregations: { + [id]: { + bucket_script: { + buckets_path: { count: '_count' }, + script: { + source: 'count * 1', + lang: 'expression', + }, + gap_policy: 'skip', + }, + }, + }, + }; + } + + if (metric.aggregation === 'custom' && metric.custom_metrics) { + const customMetricAggregations = createCustomMetricsAggregations( + id, + metric.custom_metrics, + metric.equation + ); + if (!isEmpty(customMetricAggregations)) { + return { + id, + aggregations: customMetricAggregations, + }; + } + } +}; diff --git a/x-pack/plugins/metrics_data_access/server/routes/metrics_explorer/lib/convert_request_to_metrics_api_options.test.ts b/x-pack/plugins/metrics_data_access/server/routes/metrics_explorer/lib/convert_request_to_metrics_api_options.test.ts new file mode 100644 index 0000000000000..fdf58fa848f8f --- /dev/null +++ b/x-pack/plugins/metrics_data_access/server/routes/metrics_explorer/lib/convert_request_to_metrics_api_options.test.ts @@ -0,0 +1,135 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { MetricsExplorerRequestBody, MetricsAPIRequest } from '../../../../common/http_api'; +import { convertRequestToMetricsAPIOptions } from './convert_request_to_metrics_api_options'; + +const BASE_REQUEST: MetricsExplorerRequestBody = { + timerange: { + from: new Date('2020-01-01T00:00:00Z').getTime(), + to: new Date('2020-01-01T01:00:00Z').getTime(), + interval: '1m', + }, + limit: 9, + indexPattern: 'metrics-*', + metrics: [{ aggregation: 'avg', field: 'system.cpu.user.pct' }], +}; + +const BASE_METRICS_UI_OPTIONS: MetricsAPIRequest = { + timerange: { + from: new Date('2020-01-01T00:00:00Z').getTime(), + to: new Date('2020-01-01T01:00:00Z').getTime(), + interval: '1m', + }, + limit: 9, + dropPartialBuckets: true, + indexPattern: 'metrics-*', + metrics: [ + { id: 'metric_0', aggregations: { metric_0: { avg: { field: 'system.cpu.user.pct' } } } }, + ], + includeTimeseries: true, +}; + +describe('convertRequestToMetricsAPIOptions', () => { + it('should just work', () => { + expect(convertRequestToMetricsAPIOptions(BASE_REQUEST)).toEqual(BASE_METRICS_UI_OPTIONS); + }); + + it('should work with string afterKeys', () => { + expect(convertRequestToMetricsAPIOptions({ ...BASE_REQUEST, afterKey: 'host.name' })).toEqual({ + ...BASE_METRICS_UI_OPTIONS, + afterKey: { groupBy0: 'host.name' }, + }); + }); + + it('should work with afterKey objects', () => { + const afterKey = { groupBy0: 'host.name', groupBy1: 'cloud.availability_zone' }; + expect( + convertRequestToMetricsAPIOptions({ + ...BASE_REQUEST, + afterKey, + }) + ).toEqual({ + ...BASE_METRICS_UI_OPTIONS, + afterKey, + }); + }); + + it('should work with string group bys', () => { + expect( + convertRequestToMetricsAPIOptions({ + ...BASE_REQUEST, + groupBy: 'host.name', + }) + ).toEqual({ + ...BASE_METRICS_UI_OPTIONS, + groupBy: ['host.name'], + }); + }); + + it('should work with group by arrays', () => { + expect( + convertRequestToMetricsAPIOptions({ + ...BASE_REQUEST, + groupBy: ['host.name', 'cloud.availability_zone'], + }) + ).toEqual({ + ...BASE_METRICS_UI_OPTIONS, + groupBy: ['host.name', 'cloud.availability_zone'], + }); + }); + + it('should work with filterQuery json string', () => { + const filter = { bool: { filter: [{ match: { 'host.name': 'example-01' } }] } }; + expect( + convertRequestToMetricsAPIOptions({ + ...BASE_REQUEST, + filterQuery: JSON.stringify(filter), + }) + ).toEqual({ + ...BASE_METRICS_UI_OPTIONS, + filters: [filter], + }); + }); + + it('should work with filterQuery as Lucene expressions', () => { + const filter = `host.name: 'example-01'`; + expect( + convertRequestToMetricsAPIOptions({ + ...BASE_REQUEST, + filterQuery: filter, + }) + ).toEqual({ + ...BASE_METRICS_UI_OPTIONS, + filters: [{ query_string: { query: filter, analyze_wildcard: true } }], + }); + }); + + it('should work with empty metrics', () => { + expect( + convertRequestToMetricsAPIOptions({ + ...BASE_REQUEST, + metrics: [], + }) + ).toEqual({ + ...BASE_METRICS_UI_OPTIONS, + metrics: [], + }); + }); + + it('should work with empty field', () => { + expect( + convertRequestToMetricsAPIOptions({ + ...BASE_REQUEST, + metrics: [{ aggregation: 'avg' }], + }) + ).toEqual({ + ...BASE_METRICS_UI_OPTIONS, + metrics: [], + }); + }); +}); diff --git a/x-pack/plugins/metrics_data_access/server/routes/metrics_explorer/lib/convert_request_to_metrics_api_options.ts b/x-pack/plugins/metrics_data_access/server/routes/metrics_explorer/lib/convert_request_to_metrics_api_options.ts new file mode 100644 index 0000000000000..144be0565e298 --- /dev/null +++ b/x-pack/plugins/metrics_data_access/server/routes/metrics_explorer/lib/convert_request_to_metrics_api_options.ts @@ -0,0 +1,62 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { isObject, isArray } from 'lodash'; +import { + MetricsAPIRequest, + MetricsExplorerRequestBody, + afterKeyObjectRT, +} from '../../../../common/http_api'; +import { convertMetricToMetricsAPIMetric } from './convert_metric_to_metrics_api_metric'; + +export const convertRequestToMetricsAPIOptions = ( + options: MetricsExplorerRequestBody +): MetricsAPIRequest => { + const metrics = options.metrics + .map(convertMetricToMetricsAPIMetric) + .filter((m: M): m is NonNullable => !!m); + const { limit, timerange, indexPattern } = options; + + const metricsApiOptions: MetricsAPIRequest = { + timerange, + indexPattern, + limit, + metrics, + dropPartialBuckets: true, + includeTimeseries: true, + }; + + if (options.afterKey) { + metricsApiOptions.afterKey = afterKeyObjectRT.is(options.afterKey) + ? options.afterKey + : { groupBy0: options.afterKey }; + } + + if (options.groupBy) { + metricsApiOptions.groupBy = isArray(options.groupBy) ? options.groupBy : [options.groupBy]; + } + + if (options.filterQuery) { + try { + const filterObject = JSON.parse(options.filterQuery); + if (isObject(filterObject)) { + metricsApiOptions.filters = [filterObject as any]; + } + } catch (err) { + metricsApiOptions.filters = [ + { + query_string: { + query: options.filterQuery, + analyze_wildcard: true, + }, + }, + ]; + } + } + + return metricsApiOptions; +}; diff --git a/x-pack/plugins/metrics_data_access/server/routes/metrics_explorer/lib/find_interval_for_metrics.ts b/x-pack/plugins/metrics_data_access/server/routes/metrics_explorer/lib/find_interval_for_metrics.ts new file mode 100644 index 0000000000000..da00bcc3783d5 --- /dev/null +++ b/x-pack/plugins/metrics_data_access/server/routes/metrics_explorer/lib/find_interval_for_metrics.ts @@ -0,0 +1,53 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { uniq } from 'lodash'; +import LRU from 'lru-cache'; +import { MetricsExplorerRequestBody } from '../../../../common/http_api/metrics_explorer'; +import { getDatasetForField } from './get_dataset_for_field'; +import { calculateMetricInterval } from '../../../utils/calculate_metric_interval'; +import { ESSearchClient } from '../../../lib/metrics/types'; + +const cache = new LRU({ + max: 100, + maxAge: 15 * 60 * 1000, +}); + +export const findIntervalForMetrics = async ( + client: ESSearchClient, + options: MetricsExplorerRequestBody +) => { + const fields = uniq( + options.metrics.map((metric) => (metric.field ? metric.field : null)).filter((f) => f) + ) as string[]; + + const cacheKey = fields.sort().join(':'); + + if (cache.has(cacheKey)) return cache.get(cacheKey); + + if (fields.length === 0) { + return 60; + } + + const modules = await Promise.all( + fields.map( + async (field) => + await getDatasetForField(client, field as string, options.indexPattern, options.timerange) + ) + ); + + const interval = calculateMetricInterval( + client, + { + indexPattern: options.indexPattern, + timerange: options.timerange, + }, + modules.filter(Boolean) as string[] + ); + cache.set(cacheKey, interval); + return interval; +}; diff --git a/x-pack/plugins/metrics_data_access/server/routes/metrics_explorer/lib/get_dataset_for_field.ts b/x-pack/plugins/metrics_data_access/server/routes/metrics_explorer/lib/get_dataset_for_field.ts new file mode 100644 index 0000000000000..a249f7123b766 --- /dev/null +++ b/x-pack/plugins/metrics_data_access/server/routes/metrics_explorer/lib/get_dataset_for_field.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. + */ + +const TIMESTAMP_FIELD = '@timestamp'; +import { ESSearchClient } from '../../../lib/metrics/types'; + +interface EventDatasetHit { + _source: { + event?: { + dataset?: string; + }; + }; +} + +export const getDatasetForField = async ( + client: ESSearchClient, + field: string, + indexPattern: string, + timerange: { to: number; from: number } +) => { + const params = { + allow_no_indices: true, + ignore_unavailable: true, + terminate_after: 1, + index: indexPattern, + body: { + query: { + bool: { + filter: [ + { exists: { field } }, + { + range: { + [TIMESTAMP_FIELD]: { + gte: timerange.from, + lte: timerange.to, + format: 'epoch_millis', + }, + }, + }, + ], + }, + }, + size: 1, + _source: ['event.dataset'], + sort: [{ [TIMESTAMP_FIELD]: { order: 'desc' } }], + }, + }; + + const response = await client(params); + + if (response.hits.total.value === 0) { + return null; + } + + return response.hits.hits?.[0]._source.event?.dataset; +}; diff --git a/x-pack/plugins/metrics_data_access/server/routes/metrics_explorer/lib/query_total_grouping.test.ts b/x-pack/plugins/metrics_data_access/server/routes/metrics_explorer/lib/query_total_grouping.test.ts new file mode 100644 index 0000000000000..1844a994a9375 --- /dev/null +++ b/x-pack/plugins/metrics_data_access/server/routes/metrics_explorer/lib/query_total_grouping.test.ts @@ -0,0 +1,128 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { MetricsAPIRequest } from '../../../../common/http_api'; +import { queryTotalGroupings } from './query_total_groupings'; + +describe('queryTotalGroupings', () => { + const ESSearchClientMock = jest.fn().mockReturnValue({}); + const defaultOptions: MetricsAPIRequest = { + timerange: { + from: 1615972672011, + interval: '>=10s', + to: 1615976272012, + }, + indexPattern: 'testIndexPattern', + metrics: [], + dropPartialBuckets: true, + groupBy: ['testField'], + includeTimeseries: true, + }; + + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('should return 0 when there is no groupBy', async () => { + const { groupBy, ...options } = defaultOptions; + + const response = await queryTotalGroupings(ESSearchClientMock, options); + expect(response).toBe(0); + }); + + it('should return 0 when there is groupBy is empty', async () => { + const options = { + ...defaultOptions, + groupBy: [], + }; + + const response = await queryTotalGroupings(ESSearchClientMock, options); + expect(response).toBe(0); + }); + + it('should query ES with a timerange', async () => { + await queryTotalGroupings(ESSearchClientMock, defaultOptions); + + expect(ESSearchClientMock.mock.calls[0][0].body.query.bool.filter).toContainEqual({ + range: { + '@timestamp': { + gte: 1615972672011, + lte: 1615976272012, + format: 'epoch_millis', + }, + }, + }); + }); + + it('should query ES with a exist fields', async () => { + const options = { + ...defaultOptions, + groupBy: ['testField1', 'testField2'], + }; + + await queryTotalGroupings(ESSearchClientMock, options); + + expect(ESSearchClientMock.mock.calls[0][0].body.query.bool.filter).toContainEqual({ + exists: { field: 'testField1' }, + }); + + expect(ESSearchClientMock.mock.calls[0][0].body.query.bool.filter).toContainEqual({ + exists: { field: 'testField2' }, + }); + }); + + it('should query ES with a query filter', async () => { + const options = { + ...defaultOptions, + filters: [ + { + bool: { + should: [{ match_phrase: { field1: 'value1' } }], + minimum_should_match: 1, + }, + }, + ], + }; + + await queryTotalGroupings(ESSearchClientMock, options); + + expect(ESSearchClientMock.mock.calls[0][0].body.query.bool.filter).toContainEqual({ + bool: { + should: [ + { + match_phrase: { + field1: 'value1', + }, + }, + ], + minimum_should_match: 1, + }, + }); + }); + + it('should return 0 when there are no aggregations in the response', async () => { + const clientMock = jest.fn().mockReturnValue({}); + + const response = await queryTotalGroupings(clientMock, defaultOptions); + + expect(response).toBe(0); + }); + + it('should return the value of the aggregation in the response', async () => { + const clientMock = jest.fn().mockReturnValue({ + aggregations: { + count: { + value: 10, + }, + }, + }); + + const response = await queryTotalGroupings(clientMock, defaultOptions); + + expect(response).toBe(10); + }); +}); diff --git a/x-pack/plugins/metrics_data_access/server/routes/metrics_explorer/lib/query_total_groupings.ts b/x-pack/plugins/metrics_data_access/server/routes/metrics_explorer/lib/query_total_groupings.ts new file mode 100644 index 0000000000000..f7d91f7e24dda --- /dev/null +++ b/x-pack/plugins/metrics_data_access/server/routes/metrics_explorer/lib/query_total_groupings.ts @@ -0,0 +1,67 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +const TIMESTAMP_FIELD = '@timestamp'; +import { isArray } from 'lodash'; +import { MetricsAPIRequest } from '../../../../common/http_api'; +import { ESSearchClient } from '../../../lib/metrics/types'; + +interface GroupingResponse { + count: { + value: number; + }; +} + +export const queryTotalGroupings = async ( + client: ESSearchClient, + options: MetricsAPIRequest +): Promise => { + if (!options.groupBy || (isArray(options.groupBy) && options.groupBy.length === 0)) { + return Promise.resolve(0); + } + + let filters: Array> = [ + { + range: { + [TIMESTAMP_FIELD]: { + gte: options.timerange.from, + lte: options.timerange.to, + format: 'epoch_millis', + }, + }, + }, + ...options.groupBy.map((field) => ({ exists: { field } })), + ]; + + if (options.filters) { + filters = [...filters, ...options.filters]; + } + + const params = { + allow_no_indices: true, + ignore_unavailable: true, + index: options.indexPattern, + body: { + size: 0, + query: { + bool: { + filter: filters, + }, + }, + aggs: { + count: { + cardinality: { + script: options.groupBy.map((field) => `doc['${field}'].value`).join('+'), + }, + }, + }, + }, + }; + + const response = await client<{}, GroupingResponse>(params); + return response.aggregations?.count.value ?? 0; +}; diff --git a/x-pack/plugins/metrics_data_access/server/routes/metrics_explorer/lib/transform_series.ts b/x-pack/plugins/metrics_data_access/server/routes/metrics_explorer/lib/transform_series.ts new file mode 100644 index 0000000000000..6b876887bd568 --- /dev/null +++ b/x-pack/plugins/metrics_data_access/server/routes/metrics_explorer/lib/transform_series.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 { MetricsAPISeries, MetricsExplorerSeries } from '../../../../common/http_api'; + +export const transformSeries = + (hasGroupBy: boolean) => + (series: MetricsAPISeries): MetricsExplorerSeries => { + const id = series.keys?.join(' / ') ?? series.id; + return { + ...series, + id, + rows: series.rows.map((row) => { + if (hasGroupBy) { + return { ...row, groupBy: id }; + } + return row; + }), + columns: hasGroupBy + ? [...series.columns, { name: 'groupBy', type: 'string' }] + : series.columns, + }; + }; diff --git a/x-pack/plugins/metrics_data_access/server/routes/types.ts b/x-pack/plugins/metrics_data_access/server/routes/types.ts new file mode 100644 index 0000000000000..cce4dcb5cc1e2 --- /dev/null +++ b/x-pack/plugins/metrics_data_access/server/routes/types.ts @@ -0,0 +1,14 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { IRouter, RequestHandlerContextBase } from '@kbn/core-http-server'; +import { MetricsDataClient } from '../client'; + +export interface SetupRouteOptions { + router: IRouter; + metricsClient: MetricsDataClient; +} diff --git a/x-pack/plugins/metrics_data_access/server/types.ts b/x-pack/plugins/metrics_data_access/server/types.ts index 3d13926899495..fe82768acb4ff 100644 --- a/x-pack/plugins/metrics_data_access/server/types.ts +++ b/x-pack/plugins/metrics_data_access/server/types.ts @@ -6,6 +6,7 @@ */ import { SavedObjectsClientContract } from '@kbn/core-saved-objects-api-server'; +import type { PluginStart as DataPluginStart } from '@kbn/data-plugin/server'; import { MetricsDataClient } from './client'; @@ -13,6 +14,10 @@ export interface MetricsDataPluginSetup { client: MetricsDataClient; } +export interface MetricsDataPluginStartDeps { + data: DataPluginStart; +} + export interface GetMetricIndicesOptions { savedObjectsClient: SavedObjectsClientContract; } diff --git a/x-pack/plugins/metrics_data_access/server/utils/calculate_metric_interval.ts b/x-pack/plugins/metrics_data_access/server/utils/calculate_metric_interval.ts new file mode 100644 index 0000000000000..beac55521bcef --- /dev/null +++ b/x-pack/plugins/metrics_data_access/server/utils/calculate_metric_interval.ts @@ -0,0 +1,100 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +const TIMESTAMP_FIELD = '@timestamp'; +import { findInventoryModel } from '../../common/inventory_models'; +import { InventoryItemType } from '../../common/inventory_models/types'; +import { ESSearchClient } from '../lib/metrics/types'; + +interface Options { + indexPattern: string; + timerange: { + from: number; + to: number; + }; +} + +/** + * Look at the data from metricbeat and get the max period for a given timerange. + * This is useful for visualizing metric modules like s3 that only send metrics once per day. + */ +export const calculateMetricInterval = async ( + client: ESSearchClient, + options: Options, + modules?: string[], + nodeType?: InventoryItemType // TODO: check that this type still makes sense +) => { + let from = options.timerange.from; + if (nodeType) { + const inventoryModel = findInventoryModel(nodeType); + from = options.timerange.to - inventoryModel.metrics.defaultTimeRangeInSeconds * 1000; + } + const query = { + allow_no_indices: true, + index: options.indexPattern, + ignore_unavailable: true, + body: { + query: { + bool: { + filter: [ + { + range: { + [TIMESTAMP_FIELD]: { + gte: from, + lte: options.timerange.to, + format: 'epoch_millis', + }, + }, + }, + ], + }, + }, + size: 0, + aggs: { + modules: { + terms: { + field: 'event.dataset', + include: modules, + }, + aggs: { + period: { + max: { + field: 'metricset.period', + }, + }, + }, + }, + }, + }, + }; + + const resp = await client<{}, PeriodAggregationData>(query); + + // if ES doesn't return an aggregations key, something went seriously wrong. + if (!resp.aggregations) { + return; + } + + const intervals = resp.aggregations.modules.buckets.map((a) => a.period.value).filter((v) => !!v); + if (!intervals.length) { + return; + } + + return Math.max(...intervals) / 1000; +}; + +interface PeriodAggregationData { + modules: { + buckets: Array<{ + key: string; + doc_count: number; + period: { + value: number; + }; + }>; + }; +} diff --git a/x-pack/plugins/metrics_data_access/tsconfig.json b/x-pack/plugins/metrics_data_access/tsconfig.json index b1dd132f12097..5eecf2fc31735 100644 --- a/x-pack/plugins/metrics_data_access/tsconfig.json +++ b/x-pack/plugins/metrics_data_access/tsconfig.json @@ -3,10 +3,36 @@ "compilerOptions": { "outDir": "target/types" }, - "include": ["../../../typings/**/*", "server/**/*"], + "include": ["../../../typings/**/*", "server/**/*", "common/**/*", "public/**/*"], "exclude": ["target/**/*"], "kbn_references": [ "@kbn/core", "@kbn/core-saved-objects-api-server", + "@kbn/io-ts-utils", + "@kbn/i18n", + "@kbn/share-plugin", + "@kbn/usage-collection-plugin", + "@kbn/utility-types", + "@kbn/data-plugin", + "@kbn/data-views-plugin", + "@kbn/home-plugin", + "@kbn/vis-type-timeseries-plugin", + "@kbn/features-plugin", + "@kbn/spaces-plugin", + "@kbn/alerting-plugin", + "@kbn/ml-plugin", + "@kbn/rule-registry-plugin", + "@kbn/observability-plugin", + "@kbn/core-http-server", + "@kbn/datemath", + "@kbn/es-types", + "@kbn/config-schema", + "@kbn/es-query", + "@kbn/kibana-react-plugin", + "@kbn/shared-ux-page-kibana-template", + "@kbn/observability-shared-plugin", + "@kbn/i18n-react", + "@kbn/logging", + "@kbn/core-http-request-handler-context-server" ] } diff --git a/x-pack/plugins/ml/public/application/components/technical_preview_badge/technical_preview_badge.tsx b/x-pack/plugins/ml/public/application/components/technical_preview_badge/technical_preview_badge.tsx index 95f1a0d54b10a..f23ef9e8b6b5a 100644 --- a/x-pack/plugins/ml/public/application/components/technical_preview_badge/technical_preview_badge.tsx +++ b/x-pack/plugins/ml/public/application/components/technical_preview_badge/technical_preview_badge.tsx @@ -21,7 +21,7 @@ export const TechnicalPreviewBadge: FC<{ compressed?: boolean }> = ({ compressed color="hollow" tooltipContent={i18n.translate('xpack.ml.navMenu.trainedModelsTabBetaTooltipContent', { defaultMessage: - 'This functionality is in technical preview and may be changed or removed completely in a future release. Elastic will take a best effort approach to fix any issues, but features in technical preview are not subject to the support SLA of official GA features.', + 'This functionality is in technical preview and may be changed or removed completely in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features.', })} tooltipPosition={'right'} /> diff --git a/x-pack/plugins/observability/common/constants.ts b/x-pack/plugins/observability/common/constants.ts index 11f23808d8fa3..b10eafd3e608f 100644 --- a/x-pack/plugins/observability/common/constants.ts +++ b/x-pack/plugins/observability/common/constants.ts @@ -60,4 +60,5 @@ export const observabilityAlertFeatureIds: ValidFeatureId[] = [ export const observabilityRuleCreationValidConsumers: RuleCreationValidConsumer[] = [ AlertConsumers.INFRASTRUCTURE, AlertConsumers.LOGS, + AlertConsumers.OBSERVABILITY, ]; diff --git a/x-pack/plugins/observability/kibana.jsonc b/x-pack/plugins/observability/kibana.jsonc index 467c31969c28a..94b61bc05b60a 100644 --- a/x-pack/plugins/observability/kibana.jsonc +++ b/x-pack/plugins/observability/kibana.jsonc @@ -43,7 +43,8 @@ "licensing", "usageCollection", "cloud", - "spaces" + "spaces", + "serverless" ], "requiredBundles": [ "data", diff --git a/x-pack/plugins/observability/public/application/index.tsx b/x-pack/plugins/observability/public/application/index.tsx index 40724d6db5b9f..8eb2bfe7df7bb 100644 --- a/x-pack/plugins/observability/public/application/index.tsx +++ b/x-pack/plugins/observability/public/application/index.tsx @@ -54,6 +54,7 @@ export const renderApp = ({ usageCollection, isDev, kibanaVersion, + isServerless, }: { core: CoreStart; config: ConfigSchema; @@ -64,6 +65,7 @@ export const renderApp = ({ usageCollection: UsageCollectionSetup; isDev?: boolean; kibanaVersion: string; + isServerless?: boolean; }) => { const { element, history, theme$ } = appMountParameters; const i18nCore = core.i18n; @@ -97,6 +99,7 @@ export const renderApp = ({ storage: new Storage(localStorage), isDev, kibanaVersion, + isServerless, }} > diff --git a/x-pack/plugins/observability/public/components/custom_threshold/components/alert_flyout.tsx b/x-pack/plugins/observability/public/components/custom_threshold/components/alert_flyout.tsx index ba39bcd7c4861..dc4ef4407c82c 100644 --- a/x-pack/plugins/observability/public/components/custom_threshold/components/alert_flyout.tsx +++ b/x-pack/plugins/observability/public/components/custom_threshold/components/alert_flyout.tsx @@ -39,6 +39,7 @@ export function AlertFlyout(props: Props) { series: props.series, }, validConsumers: observabilityRuleCreationValidConsumers, + useRuleProducer: true, }), // eslint-disable-next-line react-hooks/exhaustive-deps [triggersActionsUI, onCloseFlyout] diff --git a/x-pack/plugins/observability/public/components/experimental_badge.tsx b/x-pack/plugins/observability/public/components/experimental_badge.tsx index eb755200949c3..807886cbf5119 100644 --- a/x-pack/plugins/observability/public/components/experimental_badge.tsx +++ b/x-pack/plugins/observability/public/components/experimental_badge.tsx @@ -17,7 +17,7 @@ export function ExperimentalBadge() { })} tooltipContent={i18n.translate('xpack.observability.experimentalBadgeDescription', { defaultMessage: - 'This functionality is in technical preview and may be changed or removed completely in a future release. Elastic will take a best effort approach to fix any issues, but features in technical preview are not subject to the support SLA of official GA features.', + 'This functionality is in technical preview and may be changed or removed completely in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features.', })} /> ); diff --git a/x-pack/plugins/observability/public/data/slo/slo.ts b/x-pack/plugins/observability/public/data/slo/slo.ts index b60b9422e78b7..5e210526884fd 100644 --- a/x-pack/plugins/observability/public/data/slo/slo.ts +++ b/x-pack/plugins/observability/public/data/slo/slo.ts @@ -6,7 +6,7 @@ */ import { cloneDeep } from 'lodash'; -import { v1 as uuidv1 } from 'uuid'; +import { v4 as uuidv4 } from 'uuid'; import { ALL_VALUE, FindSLOResponse, SLOWithSummaryResponse } from '@kbn/slo-schema'; import { buildDegradingSummary, @@ -151,5 +151,5 @@ export function buildForecastedSlo( } export function buildSlo(params: Partial = {}): SLOWithSummaryResponse { - return cloneDeep({ ...baseSlo, id: uuidv1(), ...params }); + return cloneDeep({ ...baseSlo, id: uuidv4(), ...params }); } diff --git a/x-pack/plugins/observability/public/embeddable/slo/overview/handle_explicit_input.tsx b/x-pack/plugins/observability/public/embeddable/slo/overview/handle_explicit_input.tsx index 0c36b4e915c6c..72e460e6f1890 100644 --- a/x-pack/plugins/observability/public/embeddable/slo/overview/handle_explicit_input.tsx +++ b/x-pack/plugins/observability/public/embeddable/slo/overview/handle_explicit_input.tsx @@ -11,7 +11,7 @@ import { toMountPoint } from '@kbn/react-kibana-mount'; import type { CoreStart } from '@kbn/core/public'; import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; -import type { EmbeddableSloProps, SloEmbeddableInput } from './types'; +import type { SloEmbeddableInput, EmbeddableSloProps } from './types'; import { ObservabilityPublicPluginsStart } from '../../..'; import { SloConfiguration } from './slo_configuration'; diff --git a/x-pack/plugins/observability/public/embeddable/slo/overview/slo_configuration.tsx b/x-pack/plugins/observability/public/embeddable/slo/overview/slo_configuration.tsx index cf83690800318..c7fcb63be7a3a 100644 --- a/x-pack/plugins/observability/public/embeddable/slo/overview/slo_configuration.tsx +++ b/x-pack/plugins/observability/public/embeddable/slo/overview/slo_configuration.tsx @@ -20,7 +20,6 @@ import { import { FormattedMessage } from '@kbn/i18n-react'; import { i18n } from '@kbn/i18n'; import { SloSelector } from './slo_selector'; - import type { EmbeddableSloProps } from './types'; interface SloConfigurationProps { diff --git a/x-pack/plugins/observability/public/embeddable/slo/overview/slo_embeddable.tsx b/x-pack/plugins/observability/public/embeddable/slo/overview/slo_embeddable.tsx index faadbcb637646..ec5709ce45f98 100644 --- a/x-pack/plugins/observability/public/embeddable/slo/overview/slo_embeddable.tsx +++ b/x-pack/plugins/observability/public/embeddable/slo/overview/slo_embeddable.tsx @@ -50,8 +50,19 @@ export class SLOEmbeddable extends AbstractEmbeddable this.onRenderComplete()} sloId={sloId} sloInstanceId={sloInstanceId} lastReloadRequestTime={this.input.lastReloadRequestTime} diff --git a/x-pack/plugins/observability/public/embeddable/slo/overview/slo_overview.tsx b/x-pack/plugins/observability/public/embeddable/slo/overview/slo_overview.tsx index 9ee756c0235b8..873c37f89eca2 100644 --- a/x-pack/plugins/observability/public/embeddable/slo/overview/slo_overview.tsx +++ b/x-pack/plugins/observability/public/embeddable/slo/overview/slo_overview.tsx @@ -20,7 +20,12 @@ import { paths } from '../../../../common/locators/paths'; import { EmbeddableSloProps } from './types'; -export function SloOverview({ sloId, sloInstanceId, lastReloadRequestTime }: EmbeddableSloProps) { +export function SloOverview({ + sloId, + sloInstanceId, + lastReloadRequestTime, + onRenderComplete, +}: EmbeddableSloProps) { const { uiSettings, application: { navigateToUrl }, @@ -39,6 +44,13 @@ export function SloOverview({ sloId, sloInstanceId, lastReloadRequestTime }: Emb useEffect(() => { refetch(); }, [lastReloadRequestTime, refetch]); + useEffect(() => { + if (!onRenderComplete) return; + + if (!isLoading) { + onRenderComplete(); + } + }, [isLoading, onRenderComplete]); const percentFormat = uiSettings.get('format:percent:defaultPattern'); const isSloNotFound = !isLoading && slo === undefined; @@ -97,6 +109,7 @@ export function SloOverview({ sloId, sloInstanceId, lastReloadRequestTime }: Emb ); } + const TargetCopy = i18n.translate('xpack.observability.sloEmbeddable.overview.sloTargetLabel', { defaultMessage: 'Target', }); diff --git a/x-pack/plugins/observability/public/embeddable/slo/overview/types.ts b/x-pack/plugins/observability/public/embeddable/slo/overview/types.ts index ea125ffa8a9d5..a6f55069dc47e 100644 --- a/x-pack/plugins/observability/public/embeddable/slo/overview/types.ts +++ b/x-pack/plugins/observability/public/embeddable/slo/overview/types.ts @@ -10,6 +10,7 @@ export interface EmbeddableSloProps { sloId: string | undefined; sloInstanceId: string | undefined; lastReloadRequestTime?: number | undefined; + onRenderComplete?: () => void; } export type SloEmbeddableInput = EmbeddableInput & EmbeddableSloProps; diff --git a/x-pack/plugins/observability/public/hooks/slo/__storybook_mocks__/use_fetch_slo_list.ts b/x-pack/plugins/observability/public/hooks/slo/__storybook_mocks__/use_fetch_slo_list.ts index 4e7d1889e5bb0..78d0c0b8c2488 100644 --- a/x-pack/plugins/observability/public/hooks/slo/__storybook_mocks__/use_fetch_slo_list.ts +++ b/x-pack/plugins/observability/public/hooks/slo/__storybook_mocks__/use_fetch_slo_list.ts @@ -16,6 +16,5 @@ export const useFetchSloList = (): UseFetchSloListResponse => { isError: false, isSuccess: true, data: sloList, - refetch: function () {} as UseFetchSloListResponse['refetch'], }; }; diff --git a/x-pack/plugins/observability/public/hooks/slo/use_clone_slo.ts b/x-pack/plugins/observability/public/hooks/slo/use_clone_slo.ts index ac7f1ce0659f5..16c907f341270 100644 --- a/x-pack/plugins/observability/public/hooks/slo/use_clone_slo.ts +++ b/x-pack/plugins/observability/public/hooks/slo/use_clone_slo.ts @@ -9,7 +9,7 @@ import { IHttpFetchError, ResponseErrorBody } from '@kbn/core/public'; import { i18n } from '@kbn/i18n'; import type { CreateSLOInput, CreateSLOResponse, FindSLOResponse } from '@kbn/slo-schema'; import { QueryKey, useMutation, useQueryClient } from '@tanstack/react-query'; -import { v1 as uuidv1 } from 'uuid'; +import { v4 as uuidv4 } from 'uuid'; import { useKibana } from '../../utils/kibana_react'; import { sloKeys } from './query_key_factory'; @@ -50,7 +50,7 @@ export function useCloneSlo() { total: previousData?.total ? previousData.total + 1 : 1, results: [ ...(previousData?.results ?? []), - { ...originalSlo, name: slo.name, id: uuidv1(), summary: undefined }, + { ...originalSlo, name: slo.name, id: uuidv4(), summary: undefined }, ], }; diff --git a/x-pack/plugins/observability/public/hooks/slo/use_create_slo.ts b/x-pack/plugins/observability/public/hooks/slo/use_create_slo.ts index 15ba63d780913..6921c1f68cb15 100644 --- a/x-pack/plugins/observability/public/hooks/slo/use_create_slo.ts +++ b/x-pack/plugins/observability/public/hooks/slo/use_create_slo.ts @@ -10,7 +10,7 @@ import { i18n } from '@kbn/i18n'; import { encode } from '@kbn/rison'; import type { CreateSLOInput, CreateSLOResponse, FindSLOResponse } from '@kbn/slo-schema'; import { QueryKey, useMutation, useQueryClient } from '@tanstack/react-query'; -import { v1 as uuidv1 } from 'uuid'; +import { v4 as uuidv4 } from 'uuid'; import { paths } from '../../../common/locators/paths'; import { useKibana } from '../../utils/kibana_react'; import { sloKeys } from './query_key_factory'; @@ -47,7 +47,7 @@ export function useCreateSlo() { const [queryKey, previousData] = queriesData?.at(0) ?? []; - const newItem = { ...slo, id: uuidv1(), summary: undefined }; + const newItem = { ...slo, id: uuidv4(), summary: undefined }; const optimisticUpdate = { page: previousData?.page ?? 1, diff --git a/x-pack/plugins/observability/public/hooks/slo/use_fetch_active_alerts.ts b/x-pack/plugins/observability/public/hooks/slo/use_fetch_active_alerts.ts index 7f4e6fdce5b2b..31cf30ca03a1d 100644 --- a/x-pack/plugins/observability/public/hooks/slo/use_fetch_active_alerts.ts +++ b/x-pack/plugins/observability/public/hooks/slo/use_fetch_active_alerts.ts @@ -9,6 +9,7 @@ import { useQuery } from '@tanstack/react-query'; import { BASE_RAC_ALERTS_API_PATH } from '@kbn/rule-registry-plugin/common'; import { ALL_VALUE, SLOResponse } from '@kbn/slo-schema'; +import { AlertConsumers } from '@kbn/rule-registry-plugin/common/technical_rule_data_field_names'; import { useKibana } from '../../utils/kibana_react'; import { sloKeys } from './query_key_factory'; @@ -80,7 +81,7 @@ export function useFetchActiveAlerts({ sloIdsAndInstanceIds = [] }: Params): Use try { const response = await http.post(`${BASE_RAC_ALERTS_API_PATH}/find`, { body: JSON.stringify({ - feature_ids: ['slo'], + feature_ids: [AlertConsumers.SLO, AlertConsumers.OBSERVABILITY], size: 0, query: { bool: { diff --git a/x-pack/plugins/observability/public/hooks/slo/use_fetch_slo_list.ts b/x-pack/plugins/observability/public/hooks/slo/use_fetch_slo_list.ts index f97c2398b8efc..8f7a9e21b20cc 100644 --- a/x-pack/plugins/observability/public/hooks/slo/use_fetch_slo_list.ts +++ b/x-pack/plugins/observability/public/hooks/slo/use_fetch_slo_list.ts @@ -5,16 +5,10 @@ * 2.0. */ -import { useState } from 'react'; -import { - QueryObserverResult, - RefetchOptions, - RefetchQueryFilters, - useQuery, - useQueryClient, -} from '@tanstack/react-query'; import { i18n } from '@kbn/i18n'; import { FindSLOResponse } from '@kbn/slo-schema'; +import { useQuery, useQueryClient } from '@tanstack/react-query'; +import { useState } from 'react'; import { useKibana } from '../../utils/kibana_react'; import { sloKeys } from './query_key_factory'; @@ -34,9 +28,6 @@ export interface UseFetchSloListResponse { isSuccess: boolean; isError: boolean; data: FindSLOResponse | undefined; - refetch: ( - options?: (RefetchOptions & RefetchQueryFilters) | undefined - ) => Promise>; } const SHORT_REFETCH_INTERVAL = 1000 * 5; // 5 seconds @@ -56,56 +47,53 @@ export function useFetchSloList({ const queryClient = useQueryClient(); const [stateRefetchInterval, setStateRefetchInterval] = useState(SHORT_REFETCH_INTERVAL); - const { isInitialLoading, isLoading, isError, isSuccess, isRefetching, data, refetch } = useQuery( - { - queryKey: sloKeys.list({ kqlQuery, page, sortBy, sortDirection }), - queryFn: async ({ signal }) => { - const response = await http.get(`/api/observability/slos`, { - query: { - ...(kqlQuery && { kqlQuery }), - ...(sortBy && { sortBy }), - ...(sortDirection && { sortDirection }), - ...(page && { page }), - }, - signal, - }); + const { isInitialLoading, isLoading, isError, isSuccess, isRefetching, data } = useQuery({ + queryKey: sloKeys.list({ kqlQuery, page, sortBy, sortDirection }), + queryFn: async ({ signal }) => { + const response = await http.get(`/api/observability/slos`, { + query: { + ...(kqlQuery && { kqlQuery }), + ...(sortBy && { sortBy }), + ...(sortDirection && { sortDirection }), + ...(page && { page }), + }, + signal, + }); - return response; - }, - keepPreviousData: true, - refetchOnWindowFocus: false, - refetchInterval: shouldRefetch ? stateRefetchInterval : undefined, - staleTime: 1000, - retry: (failureCount, error) => { - if (String(error) === 'Error: Forbidden') { - return false; - } - return failureCount < 4; - }, - onSuccess: ({ results }: FindSLOResponse) => { - queryClient.invalidateQueries({ queryKey: sloKeys.historicalSummaries(), exact: false }); - queryClient.invalidateQueries({ queryKey: sloKeys.activeAlerts(), exact: false }); - queryClient.invalidateQueries({ queryKey: sloKeys.rules(), exact: false }); + return response; + }, + cacheTime: 0, + refetchOnWindowFocus: false, + refetchInterval: shouldRefetch ? stateRefetchInterval : undefined, + retry: (failureCount, error) => { + if (String(error) === 'Error: Forbidden') { + return false; + } + return failureCount < 4; + }, + onSuccess: ({ results }: FindSLOResponse) => { + queryClient.invalidateQueries({ queryKey: sloKeys.historicalSummaries(), exact: false }); + queryClient.invalidateQueries({ queryKey: sloKeys.activeAlerts(), exact: false }); + queryClient.invalidateQueries({ queryKey: sloKeys.rules(), exact: false }); - if (!shouldRefetch) { - return; - } + if (!shouldRefetch) { + return; + } - if (results.find((slo) => slo.summary.status === 'NO_DATA' || !slo.summary)) { - setStateRefetchInterval(SHORT_REFETCH_INTERVAL); - } else { - setStateRefetchInterval(LONG_REFETCH_INTERVAL); - } - }, - onError: (error: Error) => { - toasts.addError(error, { - title: i18n.translate('xpack.observability.slo.list.errorNotification', { - defaultMessage: 'Something went wrong while fetching SLOs', - }), - }); - }, - } - ); + if (results.find((slo) => slo.summary.status === 'NO_DATA' || !slo.summary)) { + setStateRefetchInterval(SHORT_REFETCH_INTERVAL); + } else { + setStateRefetchInterval(LONG_REFETCH_INTERVAL); + } + }, + onError: (error: Error) => { + toasts.addError(error, { + title: i18n.translate('xpack.observability.slo.list.errorNotification', { + defaultMessage: 'Something went wrong while fetching SLOs', + }), + }); + }, + }); return { data, @@ -114,6 +102,5 @@ export function useFetchSloList({ isRefetching, isSuccess, isError, - refetch, }; } diff --git a/x-pack/plugins/observability/public/pages/slo_details/components/header_control.tsx b/x-pack/plugins/observability/public/pages/slo_details/components/header_control.tsx index 02556efaf396a..b8c18aa457b48 100644 --- a/x-pack/plugins/observability/public/pages/slo_details/components/header_control.tsx +++ b/x-pack/plugins/observability/public/pages/slo_details/components/header_control.tsx @@ -250,6 +250,7 @@ export function HeaderControl({ isLoading, slo }: Props) { canChangeTrigger={false} onClose={onCloseRuleFlyout} initialValues={{ name: `${slo.name} burn rate`, params: { sloId: slo.id } }} + useRuleProducer /> ) : null} diff --git a/x-pack/plugins/observability/public/pages/slo_details/components/slo_detail_alerts.tsx b/x-pack/plugins/observability/public/pages/slo_details/components/slo_detail_alerts.tsx index 74d59bf74081e..f5d84d19b5c4e 100644 --- a/x-pack/plugins/observability/public/pages/slo_details/components/slo_detail_alerts.tsx +++ b/x-pack/plugins/observability/public/pages/slo_details/components/slo_detail_alerts.tsx @@ -32,7 +32,7 @@ export function SloDetailsAlerts({ slo }: Props) { configurationId={AlertConsumers.OBSERVABILITY} id={ALERTS_TABLE_ID} data-test-subj="alertTable" - featureIds={[AlertConsumers.SLO]} + featureIds={[AlertConsumers.SLO, AlertConsumers.OBSERVABILITY]} query={{ bool: { filter: [ diff --git a/x-pack/plugins/observability/public/pages/slo_edit/components/slo_edit_form.tsx b/x-pack/plugins/observability/public/pages/slo_edit/components/slo_edit_form.tsx index b8fc9bdaa0a02..6627f910a7c27 100644 --- a/x-pack/plugins/observability/public/pages/slo_edit/components/slo_edit_form.tsx +++ b/x-pack/plugins/observability/public/pages/slo_edit/components/slo_edit_form.tsx @@ -264,6 +264,7 @@ export function SloEditForm({ slo }: Props) { ruleTypeId={SLO_BURN_RATE_RULE_TYPE_ID} onClose={handleCloseRuleFlyout} onSave={handleCloseRuleFlyout} + useRuleProducer /> ) : null} diff --git a/x-pack/plugins/observability/public/pages/slo_edit/components/timeslice_metric/metric_input.tsx b/x-pack/plugins/observability/public/pages/slo_edit/components/timeslice_metric/metric_input.tsx index 0db4c1d585782..fbb7884ee63ac 100644 --- a/x-pack/plugins/observability/public/pages/slo_edit/components/timeslice_metric/metric_input.tsx +++ b/x-pack/plugins/observability/public/pages/slo_edit/components/timeslice_metric/metric_input.tsx @@ -4,7 +4,6 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import React from 'react'; import { EuiComboBox, EuiComboBoxOptionOption, @@ -14,12 +13,13 @@ import { EuiIconTip, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; +import React, { useEffect, useState } from 'react'; import { Controller, useFormContext } from 'react-hook-form'; -import { createOptionsFromFields } from '../../helpers/create_options'; -import { QueryBuilder } from '../common/query_builder'; -import { CreateSLOForm } from '../../types'; -import { AGGREGATION_OPTIONS, aggValueToLabel } from '../../helpers/aggregation_options'; import { Field } from '../../../../hooks/slo/use_fetch_index_pattern_fields'; +import { AGGREGATION_OPTIONS, aggValueToLabel } from '../../helpers/aggregation_options'; +import { createOptionsFromFields, Option } from '../../helpers/create_options'; +import { CreateSLOForm } from '../../types'; +import { QueryBuilder } from '../common/query_builder'; const fieldLabel = i18n.translate( 'xpack.observability.slo.sloEdit.sliType.timesliceMetric.fieldLabel', @@ -66,11 +66,28 @@ export function MetricInput({ }: MetricInputProps) { const { control, watch } = useFormContext(); const metric = watch(`indicator.params.metric.metrics.${index}`); - const metricFields = indexFields.filter((field) => - metric.aggregation === 'cardinality' - ? CARDINALITY_FIELD_TYPES.includes(field.type) - : NUMERIC_FIELD_TYPES.includes(field.type) + const metricAggregation = watch(`indicator.params.metric.metrics.${index}.aggregation`); + + const [metricFields, setMetricFields] = useState( + indexFields.filter((field) => NUMERIC_FIELD_TYPES.includes(field.type)) ); + const [aggregationOptions, setAggregationOptions] = useState(AGGREGATION_OPTIONS); + const [fieldOptions, setFieldOptions] = useState(createOptionsFromFields(metricFields)); + + useEffect(() => { + setMetricFields( + indexFields.filter((field) => + metricAggregation === 'cardinality' + ? CARDINALITY_FIELD_TYPES.includes(field.type) + : NUMERIC_FIELD_TYPES.includes(field.type) + ) + ); + }, [metricAggregation, setMetricFields, indexFields]); + + useEffect(() => { + setFieldOptions(createOptionsFromFields(metricFields)); + }, [metricFields, setFieldOptions]); + return ( <> @@ -124,13 +141,18 @@ export function MetricInput({ ] : [] } - options={AGGREGATION_OPTIONS} + onSearchChange={(searchValue: string) => { + setAggregationOptions( + AGGREGATION_OPTIONS.filter(({ value }) => value.includes(searchValue)) + ); + }} + options={aggregationOptions} /> )} /> - {metric.aggregation === 'percentile' && ( + {metricAggregation === 'percentile' && ( )} - {metric.aggregation !== 'doc_count' && ( + {metricAggregation !== 'doc_count' && ( { + setFieldOptions( + createOptionsFromFields(metricFields, ({ value }) => + value.includes(searchValue) + ) + ); + }} + options={fieldOptions} /> )} diff --git a/x-pack/plugins/observability/public/pages/slos/components/slo_list_item.tsx b/x-pack/plugins/observability/public/pages/slos/components/slo_list_item.tsx index cd4b6e760ea09..ae843977a0ee7 100644 --- a/x-pack/plugins/observability/public/pages/slos/components/slo_list_item.tsx +++ b/x-pack/plugins/observability/public/pages/slos/components/slo_list_item.tsx @@ -276,6 +276,7 @@ export function SloListItem({ onClose={() => { setIsAddRuleFlyoutOpen(false); }} + useRuleProducer /> ) : null} diff --git a/x-pack/plugins/observability/public/plugin.ts b/x-pack/plugins/observability/public/plugin.ts index 87fc2a2a94365..37d294f0fabe0 100644 --- a/x-pack/plugins/observability/public/plugin.ts +++ b/x-pack/plugins/observability/public/plugin.ts @@ -58,6 +58,7 @@ import { } from '@kbn/triggers-actions-ui-plugin/public'; import { UnifiedSearchPublicPluginStart } from '@kbn/unified-search-plugin/public'; import { UsageCollectionSetup } from '@kbn/usage-collection-plugin/public'; +import { ServerlessPluginStart } from '@kbn/serverless/public'; import { observabilityAppId, observabilityFeatureId } from '../common'; import { ALERTS_PATH, @@ -141,6 +142,7 @@ export interface ObservabilityPublicPluginsStart { home?: HomePublicPluginStart; cloud?: CloudStart; aiops: AiopsPluginStart; + serverless?: ServerlessPluginStart; } export type ObservabilityPublicStart = ReturnType; @@ -253,6 +255,7 @@ export class Plugin ObservabilityPageTemplate: pluginsStart.observabilityShared.navigation.PageTemplate, plugins: { ...pluginsStart, ruleTypeRegistry, actionTypeRegistry }, usageCollection: pluginsSetup.usageCollection, + isServerless: !!pluginsStart.serverless, }); }; diff --git a/x-pack/plugins/observability/server/index.ts b/x-pack/plugins/observability/server/index.ts index e05740ea9785c..96231115e3fa2 100644 --- a/x-pack/plugins/observability/server/index.ts +++ b/x-pack/plugins/observability/server/index.ts @@ -57,6 +57,7 @@ const configSchema = schema.object({ groupByPageSize: schema.number({ defaultValue: 10_000 }), }), enabled: schema.boolean({ defaultValue: true }), + createO11yGenericFeatureId: schema.boolean({ defaultValue: false }), }); export const config: PluginConfigDescriptor = { diff --git a/x-pack/plugins/observability/server/lib/rules/custom_threshold/custom_threshold_executor.test.ts b/x-pack/plugins/observability/server/lib/rules/custom_threshold/custom_threshold_executor.test.ts index bbe534e2071e3..73fead1a6f12b 100644 --- a/x-pack/plugins/observability/server/lib/rules/custom_threshold/custom_threshold_executor.test.ts +++ b/x-pack/plugins/observability/server/lib/rules/custom_threshold/custom_threshold_executor.test.ts @@ -235,7 +235,7 @@ describe('The metric threshold alert type', () => { const { action } = mostRecentAction(instanceID); expect(action.group).toBeUndefined(); expect(action.reason).toBe( - 'test.metric.1 is 1, above the threshold of 0.75. (duration: 1 min, data view: mockedIndexPattern)' + 'test.metric.1 is 1, above the threshold of 0.75. (duration: 1 min, data view: mockedDataViewName)' ); }); }); @@ -995,7 +995,7 @@ describe('The metric threshold alert type', () => { const { action } = mostRecentAction(instanceID); const reasons = action.reason; expect(reasons).toBe( - 'test.metric.1 is 1, above the threshold of 1; test.metric.2 is 3, above the threshold of 3. (duration: 1 min, data view: mockedIndexPattern)' + 'test.metric.1 is 1, above the threshold of 1; test.metric.2 is 3, above the threshold of 3. (duration: 1 min, data view: mockedDataViewName)' ); }); }); @@ -1746,6 +1746,7 @@ const alertsServices = alertsMock.createRuleExecutorServices(); const mockedIndex = { id: 'c34a7c79-a88b-4b4a-ad19-72f6d24104e4', title: 'metrics-fake_hosts', + name: 'mockedDataViewName', fieldFormatMap: {}, typeMeta: {}, timeFieldName: '@timestamp', diff --git a/x-pack/plugins/observability/server/lib/rules/custom_threshold/custom_threshold_executor.ts b/x-pack/plugins/observability/server/lib/rules/custom_threshold/custom_threshold_executor.ts index 0e0a4a9a3e7eb..c832ecc9144bf 100644 --- a/x-pack/plugins/observability/server/lib/rules/custom_threshold/custom_threshold_executor.ts +++ b/x-pack/plugins/observability/server/lib/rules/custom_threshold/custom_threshold_executor.ts @@ -134,6 +134,7 @@ export const createCustomThresholdExecutor = ({ const initialSearchSource = await searchSourceClient.create(params.searchConfiguration!); const dataView = initialSearchSource.getField('index')!.getIndexPattern(); + const dataViewName = initialSearchSource.getField('index')!.name; const timeFieldName = initialSearchSource.getField('index')?.timeFieldName; if (!dataView) { throw new Error('No matched data view'); @@ -189,7 +190,7 @@ export const createCustomThresholdExecutor = ({ let reason; if (nextState === AlertStates.ALERT) { - reason = buildFiredAlertReason(alertResults, group, dataView); + reason = buildFiredAlertReason(alertResults, group, dataViewName); } /* NO DATA STATE HANDLING diff --git a/x-pack/plugins/observability/server/plugin.ts b/x-pack/plugins/observability/server/plugin.ts index b4a81fb11e850..c034a41fbf2d5 100644 --- a/x-pack/plugins/observability/server/plugin.ts +++ b/x-pack/plugins/observability/server/plugin.ts @@ -26,6 +26,11 @@ import { RuleRegistryPluginSetupContract } from '@kbn/rule-registry-plugin/serve import { SharePluginSetup } from '@kbn/share-plugin/server'; import { SpacesPluginSetup } from '@kbn/spaces-plugin/server'; import { UsageCollectionSetup } from '@kbn/usage-collection-plugin/server'; +import { + ApmRuleType, + ES_QUERY_ID, + OBSERVABILITY_THRESHOLD_RULE_TYPE_ID, +} from '@kbn/rule-data-utils'; import { ObservabilityConfig } from '.'; import { casesFeatureId, observabilityFeatureId, sloFeatureId } from '../common'; import { SLO_BURN_RATE_RULE_TYPE_ID } from '../common/constants'; @@ -72,6 +77,13 @@ interface PluginStart { const sloRuleTypes = [SLO_BURN_RATE_RULE_TYPE_ID]; +const o11yRuleTypes = [ + SLO_BURN_RATE_RULE_TYPE_ID, + OBSERVABILITY_THRESHOLD_RULE_TYPE_ID, + ES_QUERY_ID, + ...Object.values(ApmRuleType), +]; + export class ObservabilityPlugin implements Plugin { private logger: Logger; @@ -180,6 +192,58 @@ export class ObservabilityPlugin implements Plugin { }); } + if (config.createO11yGenericFeatureId) { + plugins.features.registerKibanaFeature({ + id: observabilityFeatureId, + name: i18n.translate('xpack.observability.nameFeatureTitle', { + defaultMessage: 'Observability', + }), + order: 1000, + category: DEFAULT_APP_CATEGORIES.observability, + app: [observabilityFeatureId], + catalogue: [observabilityFeatureId], + alerting: o11yRuleTypes, + privileges: { + all: { + app: [observabilityFeatureId], + catalogue: [observabilityFeatureId], + api: ['rac'], + savedObject: { + all: [], + read: [], + }, + alerting: { + rule: { + all: o11yRuleTypes, + }, + alert: { + all: o11yRuleTypes, + }, + }, + ui: ['read', 'write'], + }, + read: { + app: [observabilityFeatureId], + catalogue: [observabilityFeatureId], + api: ['rac'], + savedObject: { + all: [], + read: [], + }, + alerting: { + rule: { + read: o11yRuleTypes, + }, + alert: { + read: o11yRuleTypes, + }, + }, + ui: ['read'], + }, + }, + }); + } + const { ruleDataService } = plugins.ruleRegistry; const savedObjectTypes = [SO_SLO_TYPE]; diff --git a/x-pack/plugins/observability/server/services/slo/create_slo.ts b/x-pack/plugins/observability/server/services/slo/create_slo.ts index cf524fdd0c40e..51c3fbec71dc8 100644 --- a/x-pack/plugins/observability/server/services/slo/create_slo.ts +++ b/x-pack/plugins/observability/server/services/slo/create_slo.ts @@ -7,7 +7,7 @@ import { ElasticsearchClient } from '@kbn/core/server'; import { ALL_VALUE, CreateSLOParams, CreateSLOResponse } from '@kbn/slo-schema'; -import { v1 as uuidv1 } from 'uuid'; +import { v4 as uuidv4 } from 'uuid'; import { SLO_SUMMARY_TEMP_INDEX_NAME } from '../../assets/constants'; import { Duration, DurationUnit, SLO } from '../../domain/models'; import { validateSLO } from '../../domain/services'; @@ -61,7 +61,7 @@ export class CreateSLO { const now = new Date(); return { ...params, - id: params.id ?? uuidv1(), + id: params.id ?? uuidv4(), settings: { syncDelay: params.settings?.syncDelay ?? new Duration(1, DurationUnit.Minute), frequency: params.settings?.frequency ?? new Duration(1, DurationUnit.Minute), diff --git a/x-pack/plugins/observability/server/services/slo/fixtures/slo.ts b/x-pack/plugins/observability/server/services/slo/fixtures/slo.ts index e423a0441f9d5..2bd320cbb8d65 100644 --- a/x-pack/plugins/observability/server/services/slo/fixtures/slo.ts +++ b/x-pack/plugins/observability/server/services/slo/fixtures/slo.ts @@ -14,7 +14,7 @@ import { TimesliceMetricIndicator, } from '@kbn/slo-schema'; import { cloneDeep } from 'lodash'; -import { v1 as uuidv1 } from 'uuid'; +import { v4 as uuidv4 } from 'uuid'; import { APMTransactionDurationIndicator, APMTransactionErrorRateIndicator, @@ -186,7 +186,7 @@ export const createSLO = (params: Partial = {}): SLO => { const now = new Date(); return cloneDeep({ ...defaultSLO, - id: uuidv1(), + id: uuidv4(), revision: 1, createdAt: now, updatedAt: now, diff --git a/x-pack/plugins/observability/server/services/slo/fixtures/summary_search_document.ts b/x-pack/plugins/observability/server/services/slo/fixtures/summary_search_document.ts index 43ec096e52bf4..17b45656aa525 100644 --- a/x-pack/plugins/observability/server/services/slo/fixtures/summary_search_document.ts +++ b/x-pack/plugins/observability/server/services/slo/fixtures/summary_search_document.ts @@ -6,10 +6,10 @@ */ import { ALL_VALUE } from '@kbn/slo-schema'; -import { v1 as uuidv1 } from 'uuid'; +import { v4 as uuidv4 } from 'uuid'; export const aSummaryDocument = ({ - id = uuidv1(), + id = uuidv4(), sliValue = 0.9, consumed = 0.4, isTempDoc = false, @@ -56,7 +56,7 @@ export const aSummaryDocument = ({ export const aHitFromSummaryIndex = (_source: any) => { return { _index: '.slo-observability.summary-v2', - _id: uuidv1(), + _id: uuidv4(), _score: 1, _source, }; @@ -65,7 +65,7 @@ export const aHitFromSummaryIndex = (_source: any) => { export const aHitFromTempSummaryIndex = (_source: any) => { return { _index: '.slo-observability.summary-v2.temp', - _id: uuidv1(), + _id: uuidv4(), _score: 1, _source, }; diff --git a/x-pack/plugins/observability/tsconfig.json b/x-pack/plugins/observability/tsconfig.json index 4c85d57f77926..d0d4114fe4612 100644 --- a/x-pack/plugins/observability/tsconfig.json +++ b/x-pack/plugins/observability/tsconfig.json @@ -92,7 +92,8 @@ "@kbn/react-kibana-mount", "@kbn/react-kibana-context-theme", "@kbn/shared-ux-link-redirect-app", - "@kbn/core-chrome-browser" + "@kbn/core-chrome-browser", + "@kbn/serverless" ], "exclude": [ "target/**/*" diff --git a/x-pack/plugins/observability_ai_assistant/public/components/technical_preview_badge.tsx b/x-pack/plugins/observability_ai_assistant/public/components/technical_preview_badge.tsx index 6e75047ef849a..e1ddd86c2017c 100644 --- a/x-pack/plugins/observability_ai_assistant/public/components/technical_preview_badge.tsx +++ b/x-pack/plugins/observability_ai_assistant/public/components/technical_preview_badge.tsx @@ -20,7 +20,7 @@ export function TechnicalPreviewBadge() { })} tooltipContent={i18n.translate('xpack.observabilityAiAssistant.experimentalTooltip', { defaultMessage: - 'This functionality is in technical preview and may be changed or removed completely in a future release. Elastic will take a best effort approach to fix any issues, but features in technical preview are not subject to the support SLA of official GA features.', + 'This functionality is in technical preview and may be changed or removed completely in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features.', })} /> ); diff --git a/x-pack/plugins/observability_onboarding/common/es_fields.ts b/x-pack/plugins/observability_onboarding/common/es_fields.ts new file mode 100644 index 0000000000000..268337b59bec1 --- /dev/null +++ b/x-pack/plugins/observability_onboarding/common/es_fields.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 const AGENT_ID = 'agent.id'; diff --git a/x-pack/plugins/observability_onboarding/public/assets/standalone_agent_setup.sh b/x-pack/plugins/observability_onboarding/public/assets/standalone_agent_setup.sh index f4c7a31e76b6c..35af09790aa2b 100755 --- a/x-pack/plugins/observability_onboarding/public/assets/standalone_agent_setup.sh +++ b/x-pack/plugins/observability_onboarding/public/assets/standalone_agent_setup.sh @@ -56,13 +56,20 @@ updateStepProgress() { local STEPNAME="$1" local STATUS="$2" # "incomplete" | "complete" | "disabled" | "loading" | "warning" | "danger" | "current" local MESSAGE=${3:-} + local PAYLOAD=${4:-} + local data="" + if [ -z "$PAYLOAD" ]; then + data="{\"status\":\"${STATUS}\", \"message\":\"${MESSAGE}\"}" + else + data="{\"status\":\"${STATUS}\", \"message\":\"${MESSAGE}\", \"payload\":${PAYLOAD}}" + fi curl --request POST \ --url "${API_ENDPOINT}/flow/${ONBOARDING_ID}/step/${STEPNAME}" \ --header "Authorization: ApiKey ${API_KEY_ENCODED}" \ --header "Content-Type: application/json" \ --header "kbn-xsrf: true" \ --header "x-elastic-internal-origin: Kibana" \ - --data "{\"status\":\"${STATUS}\", \"message\":\"${MESSAGE}\"}" \ + --data "$data" \ --output /dev/null \ --no-progress-meter } @@ -133,10 +140,12 @@ ELASTIC_AGENT_STATES=(STARTING CONFIGURING HEALTHY DEGRADED FAILED STOPPING UPGR ELASTIC_AGENT_STATE="$(elastic-agent status --output json | sed -n '/components/q;p' | grep state | sed 's/\(.*\),/\1 /' | sed 's/"state": //' | sed 's/\s//g')" # Get elastic-agent status in json format | removing extra states in the json | finding "message":value | removing , | removing "message": | trimming the result | removing "" ELASTIC_AGENT_MESSAGE="$(elastic-agent status --output json | sed -n '/components/q;p' | grep message | sed 's/\(.*\),/\1 /' | sed 's/"message": //' | sed 's/\s//g' | sed 's/\"//g')" +# Get elastic-agent status in json format | removing extra ids in the json | finding "id":value | removing , | removing "id": | trimming the result | removing "" +ELASTIC_AGENT_ID="$(elastic-agent status --output json | sed -n '/components/q;p' | grep id | sed 's/\(.*\),/\1 /' | sed 's/"id": //' | sed 's/\s//g' | sed 's/\"//g')" if [ "${ELASTIC_AGENT_STATE}" = "2" ] && [ "${ELASTIC_AGENT_MESSAGE}" = "Running" ]; then - echo "Elastic Agent running" + echo "Elastic Agent running (id: ${ELASTIC_AGENT_ID})" echo "Download and save configuration to ${cfg}" - updateStepProgress "ea-status" "complete" + updateStepProgress "ea-status" "complete" "" "{\"agentId\": \"${ELASTIC_AGENT_ID}\"}" else updateStepProgress "ea-status" "warning" "Expected agent status HEALTHY / Running but got ${ELASTIC_AGENT_STATES[ELASTIC_AGENT_STATE]} / ${ELASTIC_AGENT_MESSAGE}" fi diff --git a/x-pack/plugins/observability_onboarding/server/routes/flow/get_has_logs.ts b/x-pack/plugins/observability_onboarding/server/routes/flow/get_has_logs.ts index 1fb2baad1e4bb..2b384d198f0c4 100644 --- a/x-pack/plugins/observability_onboarding/server/routes/flow/get_has_logs.ts +++ b/x-pack/plugins/observability_onboarding/server/routes/flow/get_has_logs.ts @@ -6,7 +6,10 @@ */ import { ElasticsearchClient } from '@kbn/core/server'; +import { termQuery } from '@kbn/observability-plugin/server'; +import { AGENT_ID } from '../../../common/es_fields'; import { + ElasticAgentStepPayload, LogFilesState, ObservabilityOnboardingType, SystemLogsState, @@ -16,10 +19,12 @@ export async function getHasLogs({ type, state, esClient, + payload, }: { type: ObservabilityOnboardingType; state?: LogFilesState | SystemLogsState; esClient: ElasticsearchClient; + payload?: ElasticAgentStepPayload; }) { if (!state) { return false; @@ -30,11 +35,21 @@ export async function getHasLogs({ const index = type === 'logFiles' ? `logs-${(state as LogFilesState).datasetName}-${namespace}` - : `logs-system.syslog-${namespace}`; + : [`logs-system.syslog-${namespace}`, `logs-system.auth-${namespace}`]; + + const agentId = payload?.agentId; const { hits } = await esClient.search({ index, + ignore_unavailable: true, terminate_after: 1, + body: { + query: { + bool: { + filter: [...termQuery(AGENT_ID, agentId)], + }, + }, + }, }); const total = hits.total as { value: number }; return total.value > 0; diff --git a/x-pack/plugins/observability_onboarding/server/routes/flow/route.ts b/x-pack/plugins/observability_onboarding/server/routes/flow/route.ts index 7689167945966..c7b95fd31924c 100644 --- a/x-pack/plugins/observability_onboarding/server/routes/flow/route.ts +++ b/x-pack/plugins/observability_onboarding/server/routes/flow/route.ts @@ -11,7 +11,10 @@ import { getObservabilityOnboardingFlow, saveObservabilityOnboardingFlow, } from '../../lib/state'; -import { ObservabilityOnboardingFlow } from '../../saved_objects/observability_onboarding_status'; +import { + ElasticAgentStepPayload, + ObservabilityOnboardingFlow, +} from '../../saved_objects/observability_onboarding_status'; import { createObservabilityOnboardingServerRoute } from '../create_observability_onboarding_server_route'; import { getHasLogs } from './get_has_logs'; @@ -63,16 +66,18 @@ const stepProgressUpdateRoute = createObservabilityOnboardingServerRoute({ status: t.string, }), t.partial({ message: t.string }), + t.partial({ payload: t.record(t.string, t.unknown) }), ]), }), async handler(resources) { const { params: { path: { id, name }, - body: { status, message }, + body: { status, message, payload }, }, core, } = resources; + const coreStart = await core.start(); const savedObjectsClient = coreStart.savedObjects.createInternalRepository(); @@ -102,11 +107,15 @@ const stepProgressUpdateRoute = createObservabilityOnboardingServerRoute({ ...observabilityOnboardingState, progress: { ...observabilityOnboardingState.progress, - [name]: { status, message }, + [name]: { + status, + message, + payload: payload as unknown as ElasticAgentStepPayload, + }, }, }, }); - return { name, status, message }; + return { name, status, message, payload }; }, }); @@ -156,6 +165,7 @@ const getProgressRoute = createObservabilityOnboardingServerRoute({ type, state: savedObservabilityOnboardingState.state, esClient, + payload: progress['ea-status']?.payload, }); if (hasLogs) { progress['logs-ingest'] = { status: 'complete' }; diff --git a/x-pack/plugins/observability_onboarding/server/saved_objects/observability_onboarding_status.ts b/x-pack/plugins/observability_onboarding/server/saved_objects/observability_onboarding_status.ts index 9bc6b31bf22f5..de030ba38166e 100644 --- a/x-pack/plugins/observability_onboarding/server/saved_objects/observability_onboarding_status.ts +++ b/x-pack/plugins/observability_onboarding/server/saved_objects/observability_onboarding_status.ts @@ -22,6 +22,10 @@ export interface SystemLogsState { namespace: string; } +export interface ElasticAgentStepPayload { + agentId: string; +} + export type ObservabilityOnboardingType = 'logFiles' | 'systemLogs'; type ObservabilityOnboardingFlowState = @@ -37,6 +41,7 @@ export interface ObservabilityOnboardingFlow { { status: string; message?: string; + payload?: ElasticAgentStepPayload; } >; } @@ -59,6 +64,10 @@ const SystemLogsStateSchema = schema.object({ namespace: schema.string(), }); +const ElasticAgentStepPayloadSchema = schema.object({ + agentId: schema.string(), +}); + export const observabilityOnboardingFlow: SavedObjectsType = { name: OBSERVABILITY_ONBOARDING_STATE_SAVED_OBJECT_TYPE, hidden: false, @@ -84,6 +93,7 @@ export const observabilityOnboardingFlow: SavedObjectsType = { schema.object({ status: schema.string(), message: schema.maybe(schema.string()), + payload: schema.maybe(ElasticAgentStepPayloadSchema), }) ), }), diff --git a/x-pack/plugins/observability_shared/public/components/technical_preview_badge/technical_preview_badge.tsx b/x-pack/plugins/observability_shared/public/components/technical_preview_badge/technical_preview_badge.tsx index 4055d5c888b91..ec322403dd15b 100644 --- a/x-pack/plugins/observability_shared/public/components/technical_preview_badge/technical_preview_badge.tsx +++ b/x-pack/plugins/observability_shared/public/components/technical_preview_badge/technical_preview_badge.tsx @@ -21,7 +21,7 @@ export function TechnicalPreviewBadge({ icon = 'beaker', size, style }: Props) { })} tooltipContent={i18n.translate('xpack.observabilityShared.technicalPreviewBadgeDescription', { defaultMessage: - 'This functionality is in technical preview and may be changed or removed completely in a future release. Elastic will take a best effort approach to fix any issues, but features in technical preview are not subject to the support SLA of official GA features.', + 'This functionality is in technical preview and may be changed or removed completely in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features.', })} iconType={icon} size={size} diff --git a/x-pack/plugins/observability_shared/public/infra/index.ts b/x-pack/plugins/observability_shared/public/infra/index.ts new file mode 100644 index 0000000000000..db000cc39d9ad --- /dev/null +++ b/x-pack/plugins/observability_shared/public/infra/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 InfraAppId = 'logs' | 'metrics'; diff --git a/x-pack/plugins/osquery/common/api/asset/assets_status.gen.ts b/x-pack/plugins/osquery/common/api/asset/assets_status.gen.ts new file mode 100644 index 0000000000000..5874e8146f5c0 --- /dev/null +++ b/x-pack/plugins/osquery/common/api/asset/assets_status.gen.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 { z } from 'zod'; + +/* + * NOTICE: Do not edit this file manually. + * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. + */ + +export type AssetsRequestQuery = z.infer; +export const AssetsRequestQuery = z.object({}); + +export type SuccessResponse = z.infer; +export const SuccessResponse = z.object({}); diff --git a/x-pack/plugins/osquery/common/api/fleet_wrapper/get_agent_details.gen.ts b/x-pack/plugins/osquery/common/api/fleet_wrapper/get_agent_details.gen.ts new file mode 100644 index 0000000000000..9fa827aa002f0 --- /dev/null +++ b/x-pack/plugins/osquery/common/api/fleet_wrapper/get_agent_details.gen.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 { z } from 'zod'; + +/* + * NOTICE: Do not edit this file manually. + * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. + */ + +export type GetAgentDetailsRequestParams = z.infer; +export const GetAgentDetailsRequestParams = z.object({}); + +export type SuccessResponse = z.infer; +export const SuccessResponse = z.object({}); diff --git a/x-pack/plugins/osquery/common/api/fleet_wrapper/get_agent_policies.gen.ts b/x-pack/plugins/osquery/common/api/fleet_wrapper/get_agent_policies.gen.ts new file mode 100644 index 0000000000000..603351f7efd72 --- /dev/null +++ b/x-pack/plugins/osquery/common/api/fleet_wrapper/get_agent_policies.gen.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 { z } from 'zod'; + +/* + * NOTICE: Do not edit this file manually. + * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. + */ + +export type GetAgentPoliciesRequestParams = z.infer; +export const GetAgentPoliciesRequestParams = z.object({}); + +export type SuccessResponse = z.infer; +export const SuccessResponse = z.object({}); diff --git a/x-pack/plugins/osquery/common/api/fleet_wrapper/get_agent_policy.gen.ts b/x-pack/plugins/osquery/common/api/fleet_wrapper/get_agent_policy.gen.ts new file mode 100644 index 0000000000000..a1969fa271067 --- /dev/null +++ b/x-pack/plugins/osquery/common/api/fleet_wrapper/get_agent_policy.gen.ts @@ -0,0 +1,23 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { z } from 'zod'; + +/* + * NOTICE: Do not edit this file manually. + * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. + */ + +import { Id } from '../model/schema/common_attributes.gen'; + +export type GetAgentPolicyRequestParams = z.infer; +export const GetAgentPolicyRequestParams = z.object({ + id: Id.optional(), +}); + +export type SuccessResponse = z.infer; +export const SuccessResponse = z.object({}); diff --git a/x-pack/plugins/osquery/common/api/fleet_wrapper/get_agent_status.gen.ts b/x-pack/plugins/osquery/common/api/fleet_wrapper/get_agent_status.gen.ts new file mode 100644 index 0000000000000..1869dadbbe6b1 --- /dev/null +++ b/x-pack/plugins/osquery/common/api/fleet_wrapper/get_agent_status.gen.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 { z } from 'zod'; + +/* + * NOTICE: Do not edit this file manually. + * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. + */ + +import { KueryOrUndefined, Id } from '../model/schema/common_attributes.gen'; + +export type GetAgentStatusRequestParams = z.infer; +export const GetAgentStatusRequestParams = z.object({}); + +export type GetAgentStatusRequestQueryParams = z.infer; +export const GetAgentStatusRequestQueryParams = z.object({ + kuery: KueryOrUndefined.optional(), + policyId: Id.optional(), +}); + +export type SuccessResponse = z.infer; +export const SuccessResponse = z.object({}); diff --git a/x-pack/plugins/osquery/common/api/fleet_wrapper/get_agents.gen.ts b/x-pack/plugins/osquery/common/api/fleet_wrapper/get_agents.gen.ts new file mode 100644 index 0000000000000..549e5f3ddfe56 --- /dev/null +++ b/x-pack/plugins/osquery/common/api/fleet_wrapper/get_agents.gen.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 { z } from 'zod'; + +/* + * NOTICE: Do not edit this file manually. + * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. + */ + +export type GetAgentsRequestParams = z.infer; +export const GetAgentsRequestParams = z.object({}); + +export type SuccessResponse = z.infer; +export const SuccessResponse = z.object({}); diff --git a/x-pack/plugins/osquery/common/api/fleet_wrapper/get_package_policies.gen.ts b/x-pack/plugins/osquery/common/api/fleet_wrapper/get_package_policies.gen.ts new file mode 100644 index 0000000000000..d4def39d3fea3 --- /dev/null +++ b/x-pack/plugins/osquery/common/api/fleet_wrapper/get_package_policies.gen.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 { z } from 'zod'; + +/* + * NOTICE: Do not edit this file manually. + * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. + */ + +export type GetPackagePoliciesRequestParams = z.infer; +export const GetPackagePoliciesRequestParams = z.object({}); + +export type SuccessResponse = z.infer; +export const SuccessResponse = z.object({}); diff --git a/x-pack/plugins/osquery/common/api/live_query/create_live_query.gen.ts b/x-pack/plugins/osquery/common/api/live_query/create_live_query.gen.ts new file mode 100644 index 0000000000000..566dd638b0ea1 --- /dev/null +++ b/x-pack/plugins/osquery/common/api/live_query/create_live_query.gen.ts @@ -0,0 +1,41 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { z } from 'zod'; + +/* + * NOTICE: Do not edit this file manually. + * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. + */ + +import { + QueryOrUndefined, + ArrayQueries, + SavedQueryIdOrUndefined, + ECSMappingOrUndefined, + PackIdOrUndefined, +} from '../model/schema/common_attributes.gen'; + +export type CreateLiveQueryRequestBody = z.infer; +export const CreateLiveQueryRequestBody = z.object({ + agent_ids: z.array(z.string()).optional(), + agent_all: z.boolean().optional(), + agent_platforms: z.array(z.string()).optional(), + agent_policy_ids: z.array(z.string()).optional(), + query: QueryOrUndefined.optional(), + queries: ArrayQueries.optional(), + saved_query_id: SavedQueryIdOrUndefined.optional(), + ecs_mapping: ECSMappingOrUndefined.optional(), + pack_id: PackIdOrUndefined.optional(), + alert_ids: z.array(z.string()).optional(), + case_ids: z.array(z.string()).optional(), + event_ids: z.array(z.string()).optional(), + metadata: z.object({}).nullable().optional(), +}); + +export type SuccessResponse = z.infer; +export const SuccessResponse = z.object({}); diff --git a/x-pack/plugins/osquery/common/api/live_query/find_live_query.gen.ts b/x-pack/plugins/osquery/common/api/live_query/find_live_query.gen.ts new file mode 100644 index 0000000000000..872cca6515745 --- /dev/null +++ b/x-pack/plugins/osquery/common/api/live_query/find_live_query.gen.ts @@ -0,0 +1,33 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { z } from 'zod'; + +/* + * NOTICE: Do not edit this file manually. + * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. + */ + +import { + KueryOrUndefined, + PageOrUndefined, + PageSizeOrUndefined, + SortOrUndefined, + SortOrderOrUndefined, +} from '../model/schema/common_attributes.gen'; + +export type FindLiveQueryRequestQuery = z.infer; +export const FindLiveQueryRequestQuery = z.object({ + kuery: KueryOrUndefined.optional(), + page: PageOrUndefined.optional(), + pageSize: PageSizeOrUndefined.optional(), + sort: SortOrUndefined.optional(), + sortOrder: SortOrderOrUndefined.optional(), +}); + +export type SuccessResponse = z.infer; +export const SuccessResponse = z.object({}); diff --git a/x-pack/plugins/osquery/common/api/live_query/get_live_query_details.gen.ts b/x-pack/plugins/osquery/common/api/live_query/get_live_query_details.gen.ts new file mode 100644 index 0000000000000..cd6447ac1ab43 --- /dev/null +++ b/x-pack/plugins/osquery/common/api/live_query/get_live_query_details.gen.ts @@ -0,0 +1,16 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { z } from 'zod'; + +/* + * NOTICE: Do not edit this file manually. + * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. + */ + +export type SuccessResponse = z.infer; +export const SuccessResponse = z.object({}); diff --git a/x-pack/plugins/osquery/common/api/live_query/get_live_query_results.gen.ts b/x-pack/plugins/osquery/common/api/live_query/get_live_query_results.gen.ts new file mode 100644 index 0000000000000..c3b1eb0378407 --- /dev/null +++ b/x-pack/plugins/osquery/common/api/live_query/get_live_query_results.gen.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 { z } from 'zod'; + +/* + * NOTICE: Do not edit this file manually. + * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. + */ + +import { + KueryOrUndefined, + PageOrUndefined, + PageSizeOrUndefined, + SortOrUndefined, + SortOrderOrUndefined, + Id, +} from '../model/schema/common_attributes.gen'; + +export type GetLiveQueryResultsRequestQuery = z.infer; +export const GetLiveQueryResultsRequestQuery = z.object({ + kuery: KueryOrUndefined.optional(), + page: PageOrUndefined.optional(), + pageSize: PageSizeOrUndefined.optional(), + sort: SortOrUndefined.optional(), + sortOrder: SortOrderOrUndefined.optional(), +}); + +export type GetLiveQueryResultsRequestParams = z.infer; +export const GetLiveQueryResultsRequestParams = z.object({ + id: Id.optional(), + actionId: Id.optional(), +}); + +export type SuccessResponse = z.infer; +export const SuccessResponse = z.object({}); diff --git a/x-pack/plugins/osquery/common/api/model/schema/common_attributes.gen.ts b/x-pack/plugins/osquery/common/api/model/schema/common_attributes.gen.ts new file mode 100644 index 0000000000000..bd7d0fd8063fe --- /dev/null +++ b/x-pack/plugins/osquery/common/api/model/schema/common_attributes.gen.ts @@ -0,0 +1,176 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { z } from 'zod'; + +/* + * NOTICE: Do not edit this file manually. + * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. + */ + +export type Id = z.infer; +export const Id = z.string(); + +export type IdOrUndefined = z.infer; +export const IdOrUndefined = Id.nullable(); + +export type AgentSelection = z.infer; +export const AgentSelection = z.object({ + agents: z.array(z.string()).optional(), + allAgentsSelected: z.boolean().optional(), + platformsSelected: z.array(z.string()).optional(), + policiesSelected: z.array(z.string()).optional(), +}); + +export type AgentSelectionOrUndefined = z.infer; +export const AgentSelectionOrUndefined = AgentSelection.nullable(); + +export type Description = z.infer; +export const Description = z.string(); + +export type DescriptionOrUndefined = z.infer; +export const DescriptionOrUndefined = Description.nullable(); + +export type Platform = z.infer; +export const Platform = z.string(); + +export type PlatformOrUndefined = z.infer; +export const PlatformOrUndefined = Platform.nullable(); + +export type Query = z.infer; +export const Query = z.string(); + +export type QueryOrUndefined = z.infer; +export const QueryOrUndefined = Query.nullable(); + +export type Version = z.infer; +export const Version = z.string(); + +export type VersionOrUndefined = z.infer; +export const VersionOrUndefined = Version.nullable(); + +export type Interval = z.infer; +export const Interval = z.string(); + +export type IntervalOrUndefined = z.infer; +export const IntervalOrUndefined = Interval.nullable(); + +export type Snapshot = z.infer; +export const Snapshot = z.boolean(); + +export type SnapshotOrUndefined = z.infer; +export const SnapshotOrUndefined = Snapshot.nullable(); + +export type Removed = z.infer; +export const Removed = z.boolean(); + +export type RemovedOrUndefined = z.infer; +export const RemovedOrUndefined = Removed.nullable(); + +export type PackName = z.infer; +export const PackName = z.string(); + +export type SavedQueryId = z.infer; +export const SavedQueryId = z.string(); + +export type SavedQueryIdOrUndefined = z.infer; +export const SavedQueryIdOrUndefined = SavedQueryId.nullable(); + +export type PackId = z.infer; +export const PackId = z.string(); + +export type PackIdOrUndefined = z.infer; +export const PackIdOrUndefined = PackId.nullable(); + +export type Enabled = z.infer; +export const Enabled = z.boolean(); + +export type EnabledOrUndefined = z.infer; +export const EnabledOrUndefined = Enabled.nullable(); + +export type PolicyIds = z.infer; +export const PolicyIds = z.array(z.string()); + +export type PolicyIdsOrUndefined = z.infer; +export const PolicyIdsOrUndefined = PolicyIds.nullable(); + +export type ExecutionContext = z.infer; +export const ExecutionContext = z.object({ + name: z.string().nullable().optional(), + url: z.string().nullable().optional(), +}); + +export type ExecutionContextOrUndefined = z.infer; +export const ExecutionContextOrUndefined = ExecutionContext.nullable(); + +export type ECSMappingItem = z.infer; +export const ECSMappingItem = z.object({ + field: z.string().optional(), + value: z.union([z.string(), z.array(z.string())]).optional(), +}); + +export type ECSMapping = z.infer; +export const ECSMapping = z.object({}).catchall(ECSMappingItem); + +export type ECSMappingOrUndefined = z.infer; +export const ECSMappingOrUndefined = ECSMapping.nullable(); + +export type StringArrayOrUndefined = z.infer; +export const StringArrayOrUndefined = z.array(z.string().nullable()); + +export type ArrayQueriesItem = z.infer; +export const ArrayQueriesItem = z.object({ + id: Id.optional(), + query: Query.optional(), + ecs_mapping: ECSMappingOrUndefined.optional(), + version: VersionOrUndefined.optional(), + platform: PlatformOrUndefined.optional(), + removed: RemovedOrUndefined.optional(), + snapshot: SnapshotOrUndefined.optional(), +}); + +export type ArrayQueries = z.infer; +export const ArrayQueries = z.array(ArrayQueriesItem); + +export type ObjectQueriesItem = z.infer; +export const ObjectQueriesItem = z.object({ + query: Query.optional(), + id: Id.optional(), + ecs_mapping: ECSMappingOrUndefined.optional(), + version: VersionOrUndefined.optional(), + platform: PlatformOrUndefined.optional(), + saved_query_id: SavedQueryIdOrUndefined.optional(), + removed: RemovedOrUndefined.optional(), + snapshot: SnapshotOrUndefined.optional(), +}); + +export type ObjectQueries = z.infer; +export const ObjectQueries = z.object({}).catchall(ObjectQueriesItem); + +export type Queries = z.infer; +export const Queries = z.union([ArrayQueries, ObjectQueries]); + +export type QueriesOrUndefined = z.infer; +export const QueriesOrUndefined = Queries.nullable(); + +export type KueryOrUndefined = z.infer; +export const KueryOrUndefined = z.string().nullable(); + +export type PageOrUndefined = z.infer; +export const PageOrUndefined = z.number().int().nullable(); + +export type PageSizeOrUndefined = z.infer; +export const PageSizeOrUndefined = z.number().int().nullable(); + +export type SortOrUndefined = z.infer; +export const SortOrUndefined = z.string().nullable(); + +export type SortOrderOrUndefined = z.infer; +export const SortOrderOrUndefined = z.union([z.string().nullable(), z.unknown()]); + +export type Shards = z.infer; +export const Shards = z.object({}).catchall(z.number()); diff --git a/x-pack/plugins/osquery/common/api/packs/create_pack.gen.ts b/x-pack/plugins/osquery/common/api/packs/create_pack.gen.ts new file mode 100644 index 0000000000000..4c811fdf5941a --- /dev/null +++ b/x-pack/plugins/osquery/common/api/packs/create_pack.gen.ts @@ -0,0 +1,35 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { z } from 'zod'; + +/* + * NOTICE: Do not edit this file manually. + * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. + */ + +import { + PackName, + DescriptionOrUndefined, + EnabledOrUndefined, + PolicyIdsOrUndefined, + Shards, + ObjectQueries, +} from '../model/schema/common_attributes.gen'; + +export type CreatePacksRequestBody = z.infer; +export const CreatePacksRequestBody = z.object({ + name: PackName.optional(), + description: DescriptionOrUndefined.optional(), + enabled: EnabledOrUndefined.optional(), + policy_ids: PolicyIdsOrUndefined.optional(), + shards: Shards.optional(), + queries: ObjectQueries.optional(), +}); + +export type SuccessResponse = z.infer; +export const SuccessResponse = z.object({}); diff --git a/x-pack/plugins/osquery/common/api/packs/delete_packs.gen.ts b/x-pack/plugins/osquery/common/api/packs/delete_packs.gen.ts new file mode 100644 index 0000000000000..76cccaa169868 --- /dev/null +++ b/x-pack/plugins/osquery/common/api/packs/delete_packs.gen.ts @@ -0,0 +1,23 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { z } from 'zod'; + +/* + * NOTICE: Do not edit this file manually. + * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. + */ + +import { PackId } from '../model/schema/common_attributes.gen'; + +export type DeletePacksRequestQuery = z.infer; +export const DeletePacksRequestQuery = z.object({ + id: PackId.optional(), +}); + +export type SuccessResponse = z.infer; +export const SuccessResponse = z.object({}); diff --git a/x-pack/plugins/osquery/common/api/packs/find_packs.gen.ts b/x-pack/plugins/osquery/common/api/packs/find_packs.gen.ts new file mode 100644 index 0000000000000..c85d9e324e3d3 --- /dev/null +++ b/x-pack/plugins/osquery/common/api/packs/find_packs.gen.ts @@ -0,0 +1,31 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { z } from 'zod'; + +/* + * NOTICE: Do not edit this file manually. + * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. + */ + +import { + PageOrUndefined, + PageSizeOrUndefined, + SortOrUndefined, + SortOrderOrUndefined, +} from '../model/schema/common_attributes.gen'; + +export type FindPacksRequestQuery = z.infer; +export const FindPacksRequestQuery = z.object({ + page: PageOrUndefined.optional(), + pageSize: PageSizeOrUndefined.optional(), + sort: SortOrUndefined.optional(), + sortOrder: SortOrderOrUndefined.optional(), +}); + +export type SuccessResponse = z.infer; +export const SuccessResponse = z.object({}); diff --git a/x-pack/plugins/osquery/common/api/packs/read_packs.gen.ts b/x-pack/plugins/osquery/common/api/packs/read_packs.gen.ts new file mode 100644 index 0000000000000..a16e7e7029b43 --- /dev/null +++ b/x-pack/plugins/osquery/common/api/packs/read_packs.gen.ts @@ -0,0 +1,23 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { z } from 'zod'; + +/* + * NOTICE: Do not edit this file manually. + * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. + */ + +import { PackId } from '../model/schema/common_attributes.gen'; + +export type ReadPacksRequestQuery = z.infer; +export const ReadPacksRequestQuery = z.object({ + id: PackId.optional(), +}); + +export type SuccessResponse = z.infer; +export const SuccessResponse = z.object({}); diff --git a/x-pack/plugins/osquery/common/api/packs/update_packs.gen.ts b/x-pack/plugins/osquery/common/api/packs/update_packs.gen.ts new file mode 100644 index 0000000000000..bbeb77100da1b --- /dev/null +++ b/x-pack/plugins/osquery/common/api/packs/update_packs.gen.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 { z } from 'zod'; + +/* + * NOTICE: Do not edit this file manually. + * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. + */ + +import { + PackId, + DescriptionOrUndefined, + EnabledOrUndefined, + PolicyIdsOrUndefined, + Shards, + ObjectQueries, +} from '../model/schema/common_attributes.gen'; + +export type UpdatePacksRequestParams = z.infer; +export const UpdatePacksRequestParams = z.object({ + id: PackId.optional(), +}); + +export type UpdatePacksRequestBody = z.infer; +export const UpdatePacksRequestBody = z.object({ + id: PackId.optional(), + description: DescriptionOrUndefined.optional(), + enabled: EnabledOrUndefined.optional(), + policy_ids: PolicyIdsOrUndefined.optional(), + shards: Shards.optional(), + queries: ObjectQueries.optional(), +}); + +export type SuccessResponse = z.infer; +export const SuccessResponse = z.object({}); diff --git a/x-pack/plugins/osquery/common/api/saved_query/create_saved_query.gen.ts b/x-pack/plugins/osquery/common/api/saved_query/create_saved_query.gen.ts new file mode 100644 index 0000000000000..cc881049a5cbf --- /dev/null +++ b/x-pack/plugins/osquery/common/api/saved_query/create_saved_query.gen.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 { z } from 'zod'; + +/* + * NOTICE: Do not edit this file manually. + * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. + */ + +import { + SavedQueryId, + DescriptionOrUndefined, + QueryOrUndefined, + ECSMappingOrUndefined, + VersionOrUndefined, + Interval, + SnapshotOrUndefined, + RemovedOrUndefined, +} from '../model/schema/common_attributes.gen'; + +export type CreateSavedQueryRequestBody = z.infer; +export const CreateSavedQueryRequestBody = z.object({ + id: SavedQueryId.optional(), + description: DescriptionOrUndefined.optional(), + query: QueryOrUndefined.optional(), + ecs_mapping: ECSMappingOrUndefined.optional(), + version: VersionOrUndefined.optional(), + platform: DescriptionOrUndefined.optional(), + interval: Interval.optional(), + snapshot: SnapshotOrUndefined.optional(), + removed: RemovedOrUndefined.optional(), +}); + +export type SuccessResponse = z.infer; +export const SuccessResponse = z.object({}); diff --git a/x-pack/plugins/osquery/common/api/saved_query/delete_saved_query.gen.ts b/x-pack/plugins/osquery/common/api/saved_query/delete_saved_query.gen.ts new file mode 100644 index 0000000000000..da915ad32da1a --- /dev/null +++ b/x-pack/plugins/osquery/common/api/saved_query/delete_saved_query.gen.ts @@ -0,0 +1,23 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { z } from 'zod'; + +/* + * NOTICE: Do not edit this file manually. + * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. + */ + +import { SavedQueryId } from '../model/schema/common_attributes.gen'; + +export type DeleteSavedQueryRequestQuery = z.infer; +export const DeleteSavedQueryRequestQuery = z.object({ + id: SavedQueryId.optional(), +}); + +export type SuccessResponse = z.infer; +export const SuccessResponse = z.object({}); diff --git a/x-pack/plugins/osquery/common/api/saved_query/find_saved_query.gen.ts b/x-pack/plugins/osquery/common/api/saved_query/find_saved_query.gen.ts new file mode 100644 index 0000000000000..43ab5c93a6549 --- /dev/null +++ b/x-pack/plugins/osquery/common/api/saved_query/find_saved_query.gen.ts @@ -0,0 +1,31 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { z } from 'zod'; + +/* + * NOTICE: Do not edit this file manually. + * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. + */ + +import { + PageOrUndefined, + PageSizeOrUndefined, + SortOrUndefined, + SortOrderOrUndefined, +} from '../model/schema/common_attributes.gen'; + +export type FindSavedQueryRequestQuery = z.infer; +export const FindSavedQueryRequestQuery = z.object({ + page: PageOrUndefined.optional(), + pageSize: PageSizeOrUndefined.optional(), + sort: SortOrUndefined.optional(), + sortOrder: SortOrderOrUndefined.optional(), +}); + +export type SuccessResponse = z.infer; +export const SuccessResponse = z.object({}); diff --git a/x-pack/plugins/osquery/common/api/saved_query/read_saved_query.gen.ts b/x-pack/plugins/osquery/common/api/saved_query/read_saved_query.gen.ts new file mode 100644 index 0000000000000..e6d76e1dd7bd2 --- /dev/null +++ b/x-pack/plugins/osquery/common/api/saved_query/read_saved_query.gen.ts @@ -0,0 +1,23 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { z } from 'zod'; + +/* + * NOTICE: Do not edit this file manually. + * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. + */ + +import { SavedQueryId } from '../model/schema/common_attributes.gen'; + +export type ReadSavedQueryRequestQuery = z.infer; +export const ReadSavedQueryRequestQuery = z.object({ + id: SavedQueryId.optional(), +}); + +export type SuccessResponse = z.infer; +export const SuccessResponse = z.object({}); diff --git a/x-pack/plugins/osquery/common/api/saved_query/update_saved_query.gen.ts b/x-pack/plugins/osquery/common/api/saved_query/update_saved_query.gen.ts new file mode 100644 index 0000000000000..b6eddccae6fa3 --- /dev/null +++ b/x-pack/plugins/osquery/common/api/saved_query/update_saved_query.gen.ts @@ -0,0 +1,45 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { z } from 'zod'; + +/* + * NOTICE: Do not edit this file manually. + * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. + */ + +import { + SavedQueryId, + DescriptionOrUndefined, + QueryOrUndefined, + ECSMappingOrUndefined, + VersionOrUndefined, + IntervalOrUndefined, + SnapshotOrUndefined, + RemovedOrUndefined, +} from '../model/schema/common_attributes.gen'; + +export type UpdateSavedQueryRequestParams = z.infer; +export const UpdateSavedQueryRequestParams = z.object({ + id: SavedQueryId.optional(), +}); + +export type UpdateSavedQueryRequestBody = z.infer; +export const UpdateSavedQueryRequestBody = z.object({ + id: SavedQueryId.optional(), + description: DescriptionOrUndefined.optional(), + query: QueryOrUndefined.optional(), + ecs_mapping: ECSMappingOrUndefined.optional(), + version: VersionOrUndefined.optional(), + platform: DescriptionOrUndefined.optional(), + interval: IntervalOrUndefined.optional(), + snapshot: SnapshotOrUndefined.optional(), + removed: RemovedOrUndefined.optional(), +}); + +export type SuccessResponse = z.infer; +export const SuccessResponse = z.object({}); diff --git a/x-pack/plugins/osquery/cypress/cypress.config.ts b/x-pack/plugins/osquery/cypress/cypress.config.ts index e3321d7ff6865..defc409a76719 100644 --- a/x-pack/plugins/osquery/cypress/cypress.config.ts +++ b/x-pack/plugins/osquery/cypress/cypress.config.ts @@ -11,6 +11,7 @@ import path from 'path'; import { safeLoad as loadYaml } from 'js-yaml'; import { readFileSync } from 'fs'; +import { getFailedSpecVideos } from './support/filter_videos'; import type { YamlRoleDefinitions } from '../../../test_serverless/shared/lib'; import { setupUserDataLoader } from '../../../test_serverless/functional/test_suites/security/cypress/support/setup_data_loader_tasks'; const ROLES_YAML_FILE_PATH = path.join( @@ -36,8 +37,9 @@ export default defineCypressConfig({ screenshotsFolder: '../../../target/kibana-osquery/cypress/screenshots', trashAssetsBeforeRuns: false, - video: false, + video: true, videosFolder: '../../../target/kibana-osquery/cypress/videos', + videoCompression: 15, viewportHeight: 900, viewportWidth: 1440, experimentalStudio: true, @@ -59,6 +61,7 @@ export default defineCypressConfig({ numTestsKeptInMemory: 3, setupNodeEvents(on, config) { setupUserDataLoader(on, config, { roleDefinitions, additionalRoleName: 'viewer' }); + on('after:spec', getFailedSpecVideos); return config; }, diff --git a/x-pack/plugins/osquery/cypress/e2e/all/add_integration.cy.ts b/x-pack/plugins/osquery/cypress/e2e/all/add_integration.cy.ts index 47691d1cdace6..b26e9b1787abe 100644 --- a/x-pack/plugins/osquery/cypress/e2e/all/add_integration.cy.ts +++ b/x-pack/plugins/osquery/cypress/e2e/all/add_integration.cy.ts @@ -66,8 +66,7 @@ describe('ALL - Add Integration', { tags: ['@ess', '@serverless'] }, () => { } ); - // FLAKY: https://github.com/elastic/kibana/issues/169702 - describe.skip('Add and upgrade integration', { tags: ['@ess', '@serverless'] }, () => { + describe('Add and upgrade integration', { tags: ['@ess', '@serverless'] }, () => { const oldVersion = '0.7.4'; const [integrationName, policyName] = generateRandomStringName(2); let policyId: string; diff --git a/x-pack/plugins/osquery/cypress/e2e/all/alerts_automated_action_results.cy.ts b/x-pack/plugins/osquery/cypress/e2e/all/alerts_automated_action_results.cy.ts index 2aff49d395369..7b201bddd0ec6 100644 --- a/x-pack/plugins/osquery/cypress/e2e/all/alerts_automated_action_results.cy.ts +++ b/x-pack/plugins/osquery/cypress/e2e/all/alerts_automated_action_results.cy.ts @@ -5,15 +5,19 @@ * 2.0. */ +import { initializeDataViews } from '../../tasks/login'; import { cleanupRule, loadRule } from '../../tasks/api_fixtures'; import { checkActionItemsInResults, loadRuleAlerts } from '../../tasks/live_query'; const UUID_REGEX = '[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{12}'; -// FLAKY: https://github.com/elastic/kibana/issues/169727 -describe.skip('Alert Flyout Automated Action Results', () => { +describe('Alert Flyout Automated Action Results', () => { let ruleId: string; + before(() => { + initializeDataViews(); + }); + beforeEach(() => { loadRule(true).then((data) => { ruleId = data.id; diff --git a/x-pack/plugins/osquery/cypress/e2e/all/alerts_cases.cy.ts b/x-pack/plugins/osquery/cypress/e2e/all/alerts_cases.cy.ts index 2d681bdc71729..3c93bef865b96 100644 --- a/x-pack/plugins/osquery/cypress/e2e/all/alerts_cases.cy.ts +++ b/x-pack/plugins/osquery/cypress/e2e/all/alerts_cases.cy.ts @@ -5,6 +5,7 @@ * 2.0. */ +import { initializeDataViews } from '../../tasks/login'; import { OSQUERY_FLYOUT_BODY_EDITOR } from '../../screens/live_query'; import { cleanupCase, @@ -29,6 +30,9 @@ describe('Alert Event Details - Cases', { tags: ['@ess', '@serverless'] }, () => let packId: string; let packName: string; const packData = packFixture(); + before(() => { + initializeDataViews(); + }); beforeEach(() => { loadPack(packData).then((data) => { diff --git a/x-pack/plugins/osquery/cypress/e2e/all/alerts_linked_apps.cy.ts b/x-pack/plugins/osquery/cypress/e2e/all/alerts_linked_apps.cy.ts index 8fca7b0164eef..945410e656beb 100644 --- a/x-pack/plugins/osquery/cypress/e2e/all/alerts_linked_apps.cy.ts +++ b/x-pack/plugins/osquery/cypress/e2e/all/alerts_linked_apps.cy.ts @@ -5,6 +5,7 @@ * 2.0. */ +import { initializeDataViews } from '../../tasks/login'; import { cleanupRule, loadRule } from '../../tasks/api_fixtures'; import { RESPONSE_ACTIONS_ITEM_0, RESPONSE_ACTIONS_ITEM_1 } from '../../tasks/response_actions'; import { @@ -25,7 +26,9 @@ describe( () => { let ruleId: string; let ruleName: string; - + before(() => { + initializeDataViews(); + }); beforeEach(() => { loadRule().then((data) => { ruleId = data.id; diff --git a/x-pack/plugins/osquery/cypress/e2e/all/alerts_multiple_agents.cy.ts b/x-pack/plugins/osquery/cypress/e2e/all/alerts_multiple_agents.cy.ts index 12d3f30ad632a..afea9bb8c0adf 100644 --- a/x-pack/plugins/osquery/cypress/e2e/all/alerts_multiple_agents.cy.ts +++ b/x-pack/plugins/osquery/cypress/e2e/all/alerts_multiple_agents.cy.ts @@ -5,6 +5,7 @@ * 2.0. */ +import { initializeDataViews } from '../../tasks/login'; import { cleanupRule, loadRule } from '../../tasks/api_fixtures'; import { inputQuery, @@ -14,8 +15,7 @@ import { } from '../../tasks/live_query'; import { OSQUERY_FLYOUT_BODY_EDITOR } from '../../screens/live_query'; -// FLAKY: https://github.com/elastic/kibana/issues/170157 -describe.skip( +describe( 'Alert Event Details - dynamic params', { tags: ['@ess', '@serverless'], @@ -25,6 +25,7 @@ describe.skip( let ruleName: string; before(() => { + initializeDataViews(); loadRule(true).then((data) => { ruleId = data.id; ruleName = data.name; diff --git a/x-pack/plugins/osquery/cypress/e2e/all/alerts_response_actions_form.cy.ts b/x-pack/plugins/osquery/cypress/e2e/all/alerts_response_actions_form.cy.ts index 78e7b8ff93aa5..15fb98540e438 100644 --- a/x-pack/plugins/osquery/cypress/e2e/all/alerts_response_actions_form.cy.ts +++ b/x-pack/plugins/osquery/cypress/e2e/all/alerts_response_actions_form.cy.ts @@ -5,6 +5,7 @@ * 2.0. */ +import { initializeDataViews } from '../../tasks/login'; import { cleanupPack, cleanupRule, @@ -31,7 +32,9 @@ describe('Alert Event Details - Response Actions Form', { tags: ['@ess', '@serve let packName: string; const packData = packFixture(); const multiQueryPackData = multiQueryPackFixture(); - + before(() => { + initializeDataViews(); + }); beforeEach(() => { loadPack(packData).then((data) => { packId = data.saved_object_id; @@ -55,6 +58,7 @@ describe('Alert Event Details - Response Actions Form', { tags: ['@ess', '@serve it('adds response actions with osquery with proper validation and form values', () => { cy.visit('/app/security/rules'); clickRuleName(ruleName); + cy.getBySel('globalLoadingIndicator').should('not.exist'); cy.getBySel('editRuleSettingsLink').click(); cy.getBySel('globalLoadingIndicator').should('not.exist'); closeDateTabIfVisible(); @@ -81,20 +85,22 @@ describe('Alert Event Details - Response Actions Form', { tags: ['@ess', '@serve cy.getBySel(OSQUERY_RESPONSE_ACTION_ADD_BUTTON).click(); - cy.getBySel(RESPONSE_ACTIONS_ITEM_2).within(() => { - cy.contains('Query is a required field'); - inputQuery('select * from uptime'); - cy.contains('Query is a required field').should('not.exist'); - cy.contains('Advanced').click(); - typeInECSFieldInput('{downArrow}{enter}'); - cy.getBySel('osqueryColumnValueSelect').type('days{downArrow}{enter}'); - cy.wait(1000); // wait for the validation to trigger - cypress is way faster than users ;) - }); + cy.getBySel(RESPONSE_ACTIONS_ITEM_2) + .within(() => { + cy.contains('Query is a required field'); + inputQuery('select * from uptime'); + cy.contains('Query is a required field').should('not.exist'); + cy.contains('Advanced').click(); + typeInECSFieldInput('{downArrow}{enter}'); + cy.getBySel('osqueryColumnValueSelect').type('days{downArrow}{enter}'); + }) + .clickOutside(); cy.getBySel('ruleEditSubmitButton').click(); cy.contains(`${ruleName} was saved`).should('exist'); closeToastIfVisible(); + cy.getBySel('globalLoadingIndicator').should('not.exist'); cy.getBySel('editRuleSettingsLink').click(); cy.getBySel('globalLoadingIndicator').should('not.exist'); cy.getBySel('edit-rule-actions-tab').click(); @@ -114,11 +120,13 @@ describe('Alert Event Details - Response Actions Form', { tags: ['@ess', '@serve cy.contains('select * from uptime1'); cy.getBySel('remove-response-action').click(); }); - cy.getBySel(RESPONSE_ACTIONS_ITEM_0).within(() => { - cy.contains('Search for a pack to run'); - cy.contains('Pack is a required field'); - cy.getBySel('comboBoxInput').type(`${packName}{downArrow}{enter}`); - }); + cy.getBySel(RESPONSE_ACTIONS_ITEM_0) + .within(() => { + cy.contains('Search for a pack to run'); + cy.contains('Pack is a required field'); + cy.getBySel('comboBoxInput').type(`${packName}{downArrow}{enter}`); + }) + .clickOutside(); cy.getBySel(RESPONSE_ACTIONS_ITEM_1).within(() => { cy.contains('select * from uptime'); cy.contains('Custom key/value pairs. e.g. {"application":"foo-bar","env":"production"}'); @@ -126,6 +134,7 @@ describe('Alert Event Details - Response Actions Form', { tags: ['@ess', '@serve }); cy.intercept('PUT', '/api/detection_engine/rules').as('saveRuleSingleQuery'); + cy.getBySel('ruleEditSubmitButton').click(); cy.wait('@saveRuleSingleQuery').should(({ request }) => { const oneQuery = [ @@ -141,8 +150,10 @@ describe('Alert Event Details - Response Actions Form', { tags: ['@ess', '@serve cy.contains(`${ruleName} was saved`).should('exist'); closeToastIfVisible(); + cy.getBySel('globalLoadingIndicator').should('not.exist'); cy.getBySel('editRuleSettingsLink').click(); cy.getBySel('globalLoadingIndicator').should('not.exist'); + cy.getBySel('edit-rule-actions-tab').click(); cy.getBySel(RESPONSE_ACTIONS_ITEM_0) .within(() => { @@ -153,12 +164,15 @@ describe('Alert Event Details - Response Actions Form', { tags: ['@ess', '@serve }) .clickOutside(); - cy.getBySel(RESPONSE_ACTIONS_ITEM_1).within(() => { - cy.contains('select * from uptime'); - cy.contains('Custom key/value pairs. e.g. {"application":"foo-bar","env":"production"}'); - cy.contains('Days of uptime'); - }); + cy.getBySel(RESPONSE_ACTIONS_ITEM_1) + .within(() => { + cy.contains('select * from uptime'); + cy.contains('Custom key/value pairs. e.g. {"application":"foo-bar","env":"production"}'); + cy.contains('Days of uptime'); + }) + .clickOutside(); cy.intercept('PUT', '/api/detection_engine/rules').as('saveRuleMultiQuery'); + cy.contains('Save changes').click(); cy.wait('@saveRuleMultiQuery').should(({ request }) => { const threeQueries = [ diff --git a/x-pack/plugins/osquery/cypress/e2e/all/cases.cy.ts b/x-pack/plugins/osquery/cypress/e2e/all/cases.cy.ts index 72d4adcbe2669..1c6a96bfccb4f 100644 --- a/x-pack/plugins/osquery/cypress/e2e/all/cases.cy.ts +++ b/x-pack/plugins/osquery/cypress/e2e/all/cases.cy.ts @@ -5,6 +5,7 @@ * 2.0. */ +import { initializeDataViews } from '../../tasks/login'; import { addLiveQueryToCase, checkActionItemsInResults, @@ -14,11 +15,11 @@ import { navigateTo } from '../../tasks/navigation'; import { loadLiveQuery, loadCase, cleanupCase } from '../../tasks/api_fixtures'; import { ServerlessRoleName } from '../../support/roles'; -// FLAKY: https://github.com/elastic/kibana/issues/169747 -describe.skip('Add to Cases', () => { +describe('Add to Cases', () => { let liveQueryId: string; let liveQueryQuery: string; before(() => { + initializeDataViews(); loadLiveQuery({ agent_all: true, query: "SELECT * FROM os_version where name='Ubuntu';", @@ -32,7 +33,7 @@ describe.skip('Add to Cases', () => { describe('observability', { tags: ['@ess'] }, () => { let caseId: string; let caseTitle: string; - before(() => { + beforeEach(() => { loadCase('observability').then((caseInfo) => { caseId = caseInfo.id; caseTitle = caseInfo.title; @@ -41,7 +42,7 @@ describe.skip('Add to Cases', () => { navigateTo('/app/osquery'); }); - after(() => { + afterEach(() => { cleanupCase(caseId); }); @@ -64,7 +65,7 @@ describe.skip('Add to Cases', () => { let caseId: string; let caseTitle: string; - before(() => { + beforeEach(() => { loadCase('securitySolution').then((caseInfo) => { caseId = caseInfo.id; caseTitle = caseInfo.title; @@ -73,7 +74,7 @@ describe.skip('Add to Cases', () => { navigateTo('/app/osquery'); }); - after(() => { + afterEach(() => { cleanupCase(caseId); }); diff --git a/x-pack/plugins/osquery/cypress/e2e/all/custom_space.cy.ts b/x-pack/plugins/osquery/cypress/e2e/all/custom_space.cy.ts index edee4bdb0c8b1..ba85ec700ccc2 100644 --- a/x-pack/plugins/osquery/cypress/e2e/all/custom_space.cy.ts +++ b/x-pack/plugins/osquery/cypress/e2e/all/custom_space.cy.ts @@ -5,6 +5,7 @@ * 2.0. */ +import { initializeDataViews } from '../../tasks/login'; import { navigateTo } from '../../tasks/navigation'; import { checkActionItemsInResults, @@ -28,6 +29,7 @@ describe('ALL - Custom space', () => { let spaceId: string; before(() => { + initializeDataViews(); cy.wrap( new Promise((resolve) => { if (testSpace.name !== 'default') { diff --git a/x-pack/plugins/osquery/cypress/e2e/all/ecs_mappings.cy.ts b/x-pack/plugins/osquery/cypress/e2e/all/ecs_mappings.cy.ts index 98ad7ad0a26c2..069753f96fa9a 100644 --- a/x-pack/plugins/osquery/cypress/e2e/all/ecs_mappings.cy.ts +++ b/x-pack/plugins/osquery/cypress/e2e/all/ecs_mappings.cy.ts @@ -5,6 +5,7 @@ * 2.0. */ +import { initializeDataViews } from '../../tasks/login'; import { getAdvancedButton } from '../../screens/integrations'; import { navigateTo } from '../../tasks/navigation'; import { @@ -19,6 +20,10 @@ import { import { ServerlessRoleName } from '../../support/roles'; describe('EcsMapping', { tags: ['@ess', '@serverless'] }, () => { + before(() => { + initializeDataViews(); + }); + beforeEach(() => { cy.login(ServerlessRoleName.SOC_MANAGER); }); diff --git a/x-pack/plugins/osquery/cypress/e2e/all/live_query.cy.ts b/x-pack/plugins/osquery/cypress/e2e/all/live_query.cy.ts index dd8aaef9149f5..21308b52ba057 100644 --- a/x-pack/plugins/osquery/cypress/e2e/all/live_query.cy.ts +++ b/x-pack/plugins/osquery/cypress/e2e/all/live_query.cy.ts @@ -18,8 +18,7 @@ import { LIVE_QUERY_EDITOR } from '../../screens/live_query'; import { getAdvancedButton } from '../../screens/integrations'; import { ServerlessRoleName } from '../../support/roles'; -// FLAKY: https://github.com/elastic/kibana/issues/169725 -describe.skip('ALL - Live Query', { tags: ['@ess', '@serverless'] }, () => { +describe('ALL - Live Query', { tags: ['@ess', '@serverless'] }, () => { beforeEach(() => { cy.login(ServerlessRoleName.SOC_MANAGER); navigateTo('/app/osquery'); @@ -87,6 +86,6 @@ describe.skip('ALL - Live Query', { tags: ['@ess', '@serverless'] }, () => { inputQuery('{selectall}{backspace}{selectall}{backspace}'); // not sure if this is how it used to work when I implemented the functionality, but let's leave it like this for now - cy.get(LIVE_QUERY_EDITOR).invoke('height').should('be.gt', 200).and('be.lt', 380); + cy.get(LIVE_QUERY_EDITOR).invoke('height').should('be.gt', 200).and('be.lt', 400); }); }); diff --git a/x-pack/plugins/osquery/cypress/e2e/all/metrics.cy.ts b/x-pack/plugins/osquery/cypress/e2e/all/metrics.cy.ts index 70614f958bb2f..e0442be19ece5 100644 --- a/x-pack/plugins/osquery/cypress/e2e/all/metrics.cy.ts +++ b/x-pack/plugins/osquery/cypress/e2e/all/metrics.cy.ts @@ -11,9 +11,7 @@ import { loadSavedQuery, cleanupSavedQuery } from '../../tasks/api_fixtures'; import { triggerLoadData } from '../../tasks/inventory'; import { ServerlessRoleName } from '../../support/roles'; -// FLAKY: https://github.com/elastic/kibana/issues/169574 -// FLAKY: https://github.com/elastic/kibana/issues/169575 -describe.skip('ALL - Inventory', { tags: ['@ess'] }, () => { +describe('ALL - Inventory', { tags: ['@ess'] }, () => { let savedQueryName: string; let savedQueryId: string; diff --git a/x-pack/plugins/osquery/cypress/e2e/all/packs_create_edit.cy.ts b/x-pack/plugins/osquery/cypress/e2e/all/packs_create_edit.cy.ts index de71f491cf213..922a5b7471eb7 100644 --- a/x-pack/plugins/osquery/cypress/e2e/all/packs_create_edit.cy.ts +++ b/x-pack/plugins/osquery/cypress/e2e/all/packs_create_edit.cy.ts @@ -15,7 +15,7 @@ import { findFormFieldByRowsLabelAndType, inputQuery, } from '../../tasks/live_query'; -import { activatePack, deactivatePack, preparePack } from '../../tasks/packs'; +import { changePackActiveStatus, preparePack } from '../../tasks/packs'; import { closeModalIfVisible, closeToastIfVisible, @@ -513,8 +513,8 @@ describe('Packs - Create and Edit', { tags: ['@ess', '@serverless'] }, () => { it('', () => { cy.contains('Packs').click(); - deactivatePack(packName); - activatePack(packName); + changePackActiveStatus(packName); + changePackActiveStatus(packName); }); }); diff --git a/x-pack/plugins/osquery/cypress/e2e/all/packs_integration.cy.ts b/x-pack/plugins/osquery/cypress/e2e/all/packs_integration.cy.ts index 0ba8d631905f9..a9222abc60c10 100644 --- a/x-pack/plugins/osquery/cypress/e2e/all/packs_integration.cy.ts +++ b/x-pack/plugins/osquery/cypress/e2e/all/packs_integration.cy.ts @@ -8,17 +8,15 @@ import { find } from 'lodash'; import type { PackagePolicy } from '@kbn/fleet-plugin/common'; import { API_VERSIONS } from '../../../common/constants'; -import { FLEET_AGENT_POLICIES, navigateTo } from '../../tasks/navigation'; +import { FLEET_AGENT_POLICIES, navigateToWithoutWaitForReact } from '../../tasks/navigation'; import { checkActionItemsInResults, checkResults, deleteAndConfirm, - findAndClickButton, - findFormFieldByRowsLabelAndType, selectAllAgents, submitQuery, } from '../../tasks/live_query'; -import { activatePack, cleanupAllPrebuiltPacks, deactivatePack } from '../../tasks/packs'; +import { changePackActiveStatus, cleanupAllPrebuiltPacks } from '../../tasks/packs'; import { addIntegration, closeModalIfVisible, @@ -62,19 +60,19 @@ describe('ALL - Packs', { tags: ['@ess', '@serverless'] }, () => { cy.contains(integration).click(); addIntegration(AGENT_POLICY_NAME); cy.contains('Add Elastic Agent later').click(); - navigateTo('app/osquery/packs'); - findAndClickButton('Add pack'); - findFormFieldByRowsLabelAndType('Name', REMOVING_PACK); - findFormFieldByRowsLabelAndType('Scheduled agent policies (optional)', AGENT_POLICY_NAME); - findAndClickButton('Save pack'); - + navigateToWithoutWaitForReact('app/osquery/packs'); + cy.getBySel('addPackButton').click(); + cy.get('input[name="name"]').type(`${REMOVING_PACK}{downArrow}{enter}`); + cy.getBySel('policyIdsComboBox').type(`${AGENT_POLICY_NAME}{downArrow}{enter}`); + cy.getBySel('savePackButton').click(); closeToastIfVisible(); cy.getBySel('tablePaginationPopoverButton').click(); cy.getBySel('tablePagination-50-rows').click(); - cy.react('ScheduledQueryNameComponent', { props: { name: REMOVING_PACK } }).click(); + cy.contains(REMOVING_PACK).click(); cy.contains(`${REMOVING_PACK} details`).should('exist'); - findAndClickButton('Edit'); - cy.react('EuiComboBoxInput', { props: { value: AGENT_POLICY_NAME } }).should('exist'); + cy.get('span').contains('Edit').click(); + + cy.getBySel('comboBoxInput').contains(AGENT_POLICY_NAME).should('exist'); cy.visit(FLEET_AGENT_POLICIES); cy.contains(AGENT_POLICY_NAME).click(); @@ -86,12 +84,13 @@ describe('ALL - Packs', { tags: ['@ess', '@serverless'] }, () => { cy.contains(/^Delete integration$/).click(); closeModalIfVisible(); cy.contains(/^Deleted integration 'osquery_manager-*/); - navigateTo('app/osquery/packs'); + navigateToWithoutWaitForReact('app/osquery/packs'); cy.contains(REMOVING_PACK).click(); cy.contains(`${REMOVING_PACK} details`).should('exist'); cy.wait(1000); - findAndClickButton('Edit'); - cy.react('EuiComboBoxInput', { props: { value: '' } }).should('exist'); + cy.get('span').contains('Edit').click(); + + cy.getBySel('comboBoxInput').should('have.value', ''); }); } ); @@ -100,49 +99,44 @@ describe('ALL - Packs', { tags: ['@ess', '@serverless'] }, () => { afterEach(() => { cleanupAllPrebuiltPacks(); }); - const PREBUILD_PACK_NAME = 'it-compliance'; describe('', () => { beforeEach(() => { cy.login(ServerlessRoleName.SOC_MANAGER); - navigateTo('/app/osquery/packs'); + navigateToWithoutWaitForReact('/app/osquery/packs'); }); it('should load prebuilt packs', () => { cy.contains('Load Elastic prebuilt packs').click(); cy.contains('Load Elastic prebuilt packs').should('not.exist'); cy.wait(1000); - cy.react('EuiTableRow').should('have.length.above', 5); + cy.get('tbody > tr').should('have.length.above', 5); }); it('should be able to activate pack', () => { - activatePack(PREBUILD_PACK_NAME); - deactivatePack(PREBUILD_PACK_NAME); + changePackActiveStatus(PREBUILD_PACK_NAME); + changePackActiveStatus(PREBUILD_PACK_NAME); }); it('should be able to add policy to it', () => { cy.contains(PREBUILD_PACK_NAME).click(); cy.contains('Edit').click(); - findFormFieldByRowsLabelAndType( - 'Scheduled agent policies (optional)', - `${DEFAULT_POLICY} {downArrow}{enter}` - ); - cy.contains('Update pack').click(); + cy.getBySel('policyIdsComboBox').type(`${DEFAULT_POLICY} {downArrow}{enter}`); + cy.getBySel('updatePackButton').click(); cy.getBySel('confirmModalConfirmButton').click(); cy.contains(`Successfully updated "${PREBUILD_PACK_NAME}" pack`); }); it('should be able to activate pack with agent inside', () => { - activatePack(PREBUILD_PACK_NAME); - deactivatePack(PREBUILD_PACK_NAME); + changePackActiveStatus(PREBUILD_PACK_NAME); + changePackActiveStatus(PREBUILD_PACK_NAME); }); it('should not be able to update prebuilt pack', () => { cy.contains(PREBUILD_PACK_NAME).click(); cy.contains('Edit').click(); - cy.react('EuiFieldText', { props: { name: 'name', isDisabled: true } }); - cy.react('EuiFieldText', { props: { name: 'description', isDisabled: true } }); + cy.get('input[name="name"]').should('be.disabled'); + cy.get('input[name="description"]').should('be.disabled'); cy.contains('Add Query').should('not.exist'); - cy.react('ExpandedItemActions', { options: { timeout: 1000 } }); cy.get('.euiTableRowCell--hasActions').should('not.exist'); }); it('should be able to delete prebuilt pack and add it again', () => { @@ -156,7 +150,7 @@ describe('ALL - Packs', { tags: ['@ess', '@serverless'] }, () => { }); it('should be able to run live prebuilt pack', () => { - navigateTo('/app/osquery/live_queries'); + navigateToWithoutWaitForReact('/app/osquery/live_queries'); cy.contains('New live query').click(); cy.contains('Run a set of queries in a pack.').click(); cy.get(LIVE_QUERY_EDITOR).should('not.exist'); @@ -171,17 +165,16 @@ describe('ALL - Packs', { tags: ['@ess', '@serverless'] }, () => { cases: true, timeline: false, }); - navigateTo('/app/osquery'); + navigateToWithoutWaitForReact('/app/osquery'); cy.contains('osquery-monitoring'); }); }); }); - // FLAKY: https://github.com/elastic/kibana/issues/169688 - describe.skip('Global packs', { tags: ['@ess', '@serverless'] }, () => { + describe('Global packs', { tags: ['@ess', '@serverless'] }, () => { beforeEach(() => { cy.login(ServerlessRoleName.PLATFORM_ENGINEER); - navigateTo('/app/osquery/packs'); + navigateToWithoutWaitForReact('/app/osquery/packs'); }); describe('add proper shard to policies packs config', () => { @@ -205,14 +198,12 @@ describe('ALL - Packs', { tags: ['@ess', '@serverless'] }, () => { }); it('add global packs to policies', () => { - findAndClickButton('Add pack'); - findFormFieldByRowsLabelAndType('Name', globalPack); + cy.getBySel('addPackButton').click(); + cy.get('input[name="name"]').type(`${globalPack}{downArrow}{enter}`); cy.getBySel('policyIdsComboBox').should('exist'); cy.getBySel('osqueryPackTypeGlobal').click(); cy.getBySel('policyIdsComboBox').should('not.exist'); - - findAndClickButton('Save pack'); - + cy.getBySel('savePackButton').click(); cy.getBySel('tablePaginationPopoverButton').click(); cy.getBySel('tablePagination-50-rows').click(); cy.contains(globalPack); @@ -269,8 +260,8 @@ describe('ALL - Packs', { tags: ['@ess', '@serverless'] }, () => { it('', () => { const shardPack = 'shardPack' + generateRandomStringName(1)[0]; - findAndClickButton('Add pack'); - findFormFieldByRowsLabelAndType('Name', shardPack); + cy.getBySel('addPackButton').click(); + cy.get('input[name="name"]').type(`${shardPack}{downArrow}{enter}`); cy.contains('Partial deployment (shards)').click(); cy.getBySel('packShardsForm-0').within(() => { @@ -281,7 +272,7 @@ describe('ALL - Packs', { tags: ['@ess', '@serverless'] }, () => { cy.getBySel('shards-field-policy').type(`${OSQUERY_POLICY}{downArrow}{enter}`); cy.get('#shardsPercentage1').type('{backspace}{backspace}{backspace}'); }); - findAndClickButton('Save pack'); + cy.getBySel('savePackButton').click(); cy.contains(`Successfully created "${shardPack}" pack`); closeToastIfVisible(); @@ -319,9 +310,9 @@ describe('ALL - Packs', { tags: ['@ess', '@serverless'] }, () => { cy.get('[data-test-subj="packShardsForm-1"]').within(() => { cy.get(`[aria-label="Delete shards row"]`).click(); }); - cy.getBySel('comboBoxInput').contains(OSQUERY_POLICY).should('not.exist'); - cy.getBySel('policyIdsComboBox').click(); - cy.contains(OSQUERY_POLICY).should('exist'); + cy.getBySel('policyIdsComboBox').contains(OSQUERY_POLICY).should('not.exist'); + cy.getBySel('policyIdsComboBox').click().type(`${OSQUERY_POLICY}{downArrow}{enter}`); + cy.getBySel('policyIdsComboBox').contains(OSQUERY_POLICY).should('exist'); }); }); }); diff --git a/x-pack/plugins/osquery/cypress/e2e/all/saved_queries.cy.ts b/x-pack/plugins/osquery/cypress/e2e/all/saved_queries.cy.ts index c7528a1410d87..dd812d25d6bc2 100644 --- a/x-pack/plugins/osquery/cypress/e2e/all/saved_queries.cy.ts +++ b/x-pack/plugins/osquery/cypress/e2e/all/saved_queries.cy.ts @@ -105,18 +105,14 @@ describe('ALL - Saved queries', { tags: ['@ess', '@serverless'] }, () => { }); it('checks result type on prebuilt saved query', () => { - cy.react('CustomItemAction', { - props: { index: 1, item: { id: 'users_elastic' } }, - }).click(); + cy.get(`[aria-label="Edit users_elastic"]`).click(); cy.getBySel('resultsTypeField').within(() => { cy.contains('Snapshot'); }); }); it('user can run prebuilt saved query and add to case', () => { - cy.react('PlayButtonComponent', { - props: { savedQuery: { id: 'users_elastic' } }, - }).click(); + cy.get(`[aria-label="Run users_elastic"]`).click(); selectAllAgents(); submitQuery(); @@ -126,9 +122,7 @@ describe('ALL - Saved queries', { tags: ['@ess', '@serverless'] }, () => { }); it('user can not delete prebuilt saved query but can delete normal saved query', () => { - cy.react('CustomItemAction', { - props: { index: 1, item: { id: 'users_elastic' } }, - }).click(); + cy.get(`[aria-label="Edit users_elastic"]`).click(); cy.contains('Delete query').should('not.exist'); navigateTo(`/app/osquery/saved_queries/${savedQueryId}`); @@ -142,18 +136,14 @@ describe('ALL - Saved queries', { tags: ['@ess', '@serverless'] }, () => { findAndClickButton('Add query'); cy.contains('Attach next query'); - cy.react('EuiComboBox', { - props: { placeholder: 'Search for a query to run, or write a new query below' }, - }) - .click() - .type('users_elastic{downArrow} {enter}'); + cy.getBySel('savedQuerySelect').click().type('users_elastic{downArrow} {enter}'); inputQuery('where name=1'); cy.getBySel('resultsTypeField').click(); cy.contains('Differential (Ignore removals)').click(); cy.contains('Unique identifier of the us').should('exist'); cy.contains('User ID').should('exist'); - cy.react('EuiFlyoutBody').within(() => { + cy.get(`[aria-labelledby="flyoutTitle"]`).within(() => { cy.getBySel('ECSMappingEditorForm') .first() .within(() => { @@ -162,16 +152,15 @@ describe('ALL - Saved queries', { tags: ['@ess', '@serverless'] }, () => { }); cy.contains('Unique identifier of the us').should('not.exist'); cy.contains('User ID').should('not.exist'); - cy.react('EuiFlyoutFooter').react('EuiButton').contains('Save').click(); + cy.get(`[aria-labelledby="flyoutTitle"]`).contains('Save').click(); + + cy.get(`[aria-label="Edit users_elastic"]`).click(); - cy.react('CustomItemAction', { - props: { index: 0, item: { id: 'users_elastic' } }, - }).click(); cy.contains('SELECT * FROM users;where name=1'); cy.contains('Unique identifier of the us.').should('not.exist'); cy.contains('User ID').should('not.exist'); cy.contains('Differential (Ignore removals)').should('exist'); - cy.react('EuiFlyoutFooter').react('EuiButtonEmpty').contains('Cancel').click(); + cy.get(`[aria-labelledby="flyoutTitle"]`).contains('Cancel').click(); }); }); }); diff --git a/x-pack/plugins/osquery/cypress/e2e/all/timelines.cy.ts b/x-pack/plugins/osquery/cypress/e2e/all/timelines.cy.ts index 08a1c0925ffb9..6c2380664ba4d 100644 --- a/x-pack/plugins/osquery/cypress/e2e/all/timelines.cy.ts +++ b/x-pack/plugins/osquery/cypress/e2e/all/timelines.cy.ts @@ -5,10 +5,14 @@ * 2.0. */ +import { initializeDataViews } from '../../tasks/login'; import { takeOsqueryActionWithParams } from '../../tasks/live_query'; import { ServerlessRoleName } from '../../support/roles'; describe.skip('ALL - Timelines', { tags: ['@ess'] }, () => { + before(() => { + initializeDataViews(); + }); beforeEach(() => { cy.login(ServerlessRoleName.SOC_MANAGER); }); diff --git a/x-pack/plugins/osquery/cypress/e2e/roles/alert_test.cy.ts b/x-pack/plugins/osquery/cypress/e2e/roles/alert_test.cy.ts index 38352c49c6459..718c2f32fd581 100644 --- a/x-pack/plugins/osquery/cypress/e2e/roles/alert_test.cy.ts +++ b/x-pack/plugins/osquery/cypress/e2e/roles/alert_test.cy.ts @@ -5,6 +5,7 @@ * 2.0. */ +import { initializeDataViews } from '../../tasks/login'; import { checkResults, clickRuleName, submitQuery } from '../../tasks/live_query'; import { loadRule, cleanupRule } from '../../tasks/api_fixtures'; import { ServerlessRoleName } from '../../support/roles'; @@ -14,6 +15,7 @@ describe('Alert Test', { tags: ['@ess'] }, () => { let ruleId: string; before(() => { + initializeDataViews(); loadRule().then((data) => { ruleName = data.name; ruleId = data.id; diff --git a/x-pack/plugins/osquery/cypress/serverless_cypress.config.ts b/x-pack/plugins/osquery/cypress/serverless_cypress.config.ts index 506204de66aa2..fac363698170a 100644 --- a/x-pack/plugins/osquery/cypress/serverless_cypress.config.ts +++ b/x-pack/plugins/osquery/cypress/serverless_cypress.config.ts @@ -6,6 +6,7 @@ */ import { defineCypressConfig } from '@kbn/cypress-config'; +import { getFailedSpecVideos } from './support/filter_videos'; import { setupUserDataLoader } from '../../../test_serverless/functional/test_suites/security/cypress/support/setup_data_loader_tasks'; // eslint-disable-next-line import/no-default-export @@ -21,7 +22,9 @@ export default defineCypressConfig({ responseTimeout: 60000, screenshotsFolder: '../../../target/kibana-osquery/cypress/screenshots', trashAssetsBeforeRuns: false, - video: false, + video: true, + videosFolder: '../../../target/kibana-osquery/cypress/videos', + videoCompression: 15, viewportHeight: 946, viewportWidth: 1680, @@ -40,6 +43,7 @@ export default defineCypressConfig({ numTestsKeptInMemory: 3, setupNodeEvents: (on, config) => { setupUserDataLoader(on, config, { additionalRoleName: 'viewer' }); + on('after:spec', getFailedSpecVideos); return config; }, diff --git a/x-pack/plugins/osquery/cypress/support/e2e.ts b/x-pack/plugins/osquery/cypress/support/e2e.ts index 56bcab0e700ad..d5943e655e5ae 100644 --- a/x-pack/plugins/osquery/cypress/support/e2e.ts +++ b/x-pack/plugins/osquery/cypress/support/e2e.ts @@ -23,6 +23,7 @@ // *********************************************************** // force ESM in this module + export {}; // @ts-expect-error ts(2306) module has some interesting ways of importing, see https://github.com/cypress-io/cypress/blob/0871b03c5b21711cd23056454da8f23dcaca4950/npm/grep/README.md#support-file @@ -33,7 +34,7 @@ registerCypressGrep(); import type { SecuritySolutionDescribeBlockFtrConfig } from '@kbn/security-solution-plugin/scripts/run_cypress/utils'; import { login } from '@kbn/security-solution-plugin/public/management/cypress/tasks/login'; -import { ServerlessRoleName } from './roles'; +import type { ServerlessRoleName } from './roles'; import 'cypress-react-selector'; import { waitUntil } from '../tasks/wait_until'; @@ -92,12 +93,3 @@ Cypress.Commands.add('waitUntil', waitUntil); // Alternatively you can use CommonJS syntax: // require('./commands') Cypress.on('uncaught:exception', () => false); - -// Login as a SOC_MANAGER to properly initialize Security Solution App -before(() => { - cy.login(ServerlessRoleName.SOC_MANAGER); - cy.visit('/app/security/alerts'); - cy.getBySel('globalLoadingIndicator').should('exist'); - cy.getBySel('globalLoadingIndicator').should('not.exist'); - cy.getBySel('manage-alert-detection-rules').should('exist'); -}); diff --git a/x-pack/plugins/osquery/cypress/support/filter_videos.ts b/x-pack/plugins/osquery/cypress/support/filter_videos.ts new file mode 100644 index 0000000000000..69826fb39b0bc --- /dev/null +++ b/x-pack/plugins/osquery/cypress/support/filter_videos.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 fs from 'fs'; + +// makes sure we save videos just for failed specs +export const getFailedSpecVideos = (spec: Cypress.Spec, results: CypressCommandLine.RunResult) => { + if (results && results.video) { + // Do we have failures for any retry attempts? + const failures = results.tests.some((test) => + test.attempts.some((attempt) => attempt.state === 'failed') + ); + if (!failures) { + // delete the video if the spec passed and no tests retried + fs.unlinkSync(results.video); + } + } +}; diff --git a/x-pack/plugins/osquery/cypress/tasks/integrations.ts b/x-pack/plugins/osquery/cypress/tasks/integrations.ts index d1020c51db9a3..760f9da287dba 100644 --- a/x-pack/plugins/osquery/cypress/tasks/integrations.ts +++ b/x-pack/plugins/osquery/cypress/tasks/integrations.ts @@ -54,7 +54,8 @@ export const integrationExistsWithinPolicyDetails = (integrationName: string) => }; export const interceptAgentPolicyId = (cb: (policyId: string) => void) => { - cy.intercept('POST', '**/api/fleet/agent_policies**', (req) => { + // create policy has agent_policies?SOMEPARAMS=true , this ? helps to distinguish it from the delete agent_policies/delete route + cy.intercept('POST', '**/api/fleet/agent_policies?**', (req) => { req.continue((res) => { cb(res.body.item.id); diff --git a/x-pack/plugins/osquery/cypress/tasks/inventory.ts b/x-pack/plugins/osquery/cypress/tasks/inventory.ts index 8ba6fc0702d21..d4a2d1111db8f 100644 --- a/x-pack/plugins/osquery/cypress/tasks/inventory.ts +++ b/x-pack/plugins/osquery/cypress/tasks/inventory.ts @@ -9,7 +9,15 @@ export const triggerLoadData = () => { cy.getBySel('infraWaffleTimeControlsAutoRefreshButton').should('exist'); cy.wait(1000); cy.getBySel('infraWaffleTimeControlsAutoRefreshButton').click(); - cy.getBySel('nodeContainer').last().should('exist'); + // @ts-expect-error update types for multiple true + cy.getBySel('nodeContainer', { multiple: true }) + .not(':contains("dev-fleet-server")') + .first() + .should('exist'); cy.getBySel('infraWaffleTimeControlsStopRefreshingButton').click(); - cy.getBySel('nodeContainer').last().click(); + // @ts-expect-error update types for multiple true + cy.getBySel('nodeContainer', { multiple: true }) + .not(':contains("dev-fleet-server")') + .first() + .click(); }; diff --git a/x-pack/plugins/osquery/cypress/tasks/live_query.ts b/x-pack/plugins/osquery/cypress/tasks/live_query.ts index 2530eeaf45c7b..4b1b2d41b2283 100644 --- a/x-pack/plugins/osquery/cypress/tasks/live_query.ts +++ b/x-pack/plugins/osquery/cypress/tasks/live_query.ts @@ -7,7 +7,6 @@ import { LIVE_QUERY_EDITOR, OSQUERY_FLYOUT_BODY_EDITOR } from '../screens/live_query'; import { ServerlessRoleName } from '../support/roles'; -import { isServerless } from './serverless'; import { waitForAlertsToPopulate } from '../../../../test/security_solution_cypress/cypress/tasks/create_new_rule'; export const DEFAULT_QUERY = 'select * from processes;'; @@ -80,9 +79,9 @@ export const findFormFieldByRowsLabelAndType = (label: string, text: string) => }; export const deleteAndConfirm = (type: string) => { - cy.react('EuiButton').contains(`Delete ${type}`).click(); + cy.get('span').contains(`Delete ${type}`).click(); cy.contains(`Are you sure you want to delete this ${type}?`); - cy.react('EuiButton').contains('Confirm').click(); + cy.get('span').contains('Confirm').click(); cy.get('[data-test-subj="globalToastList"]') .first() .contains('Successfully deleted') @@ -146,10 +145,8 @@ export const checkActionItemsInResults = ({ cases: boolean; timeline: boolean; }) => { - cy.contains('View in Discover').should( - isServerless ? 'not.exist' : discover ? 'exist' : 'not.exist' - ); - cy.contains('View in Lens').should(isServerless ? 'not.exist' : lens ? 'exist' : 'not.exist'); + cy.contains('View in Discover').should(discover ? 'exist' : 'not.exist'); + cy.contains('View in Lens').should(lens ? 'exist' : 'not.exist'); cy.contains('Add to Case').should(cases ? 'exist' : 'not.exist'); cy.contains('Add to timeline investigation').should(timeline ? 'exist' : 'not.exist'); }; diff --git a/x-pack/plugins/osquery/cypress/tasks/login.ts b/x-pack/plugins/osquery/cypress/tasks/login.ts new file mode 100644 index 0000000000000..89dab4ca72e56 --- /dev/null +++ b/x-pack/plugins/osquery/cypress/tasks/login.ts @@ -0,0 +1,17 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { ServerlessRoleName } from '../support/roles'; + +// Login as a SOC_MANAGER to properly initialize Security Solution App +export const initializeDataViews = () => { + cy.login(ServerlessRoleName.SOC_MANAGER); + cy.visit('/app/security/alerts'); + cy.getBySel('globalLoadingIndicator').should('exist'); + cy.getBySel('globalLoadingIndicator').should('not.exist'); + cy.getBySel('manage-alert-detection-rules').should('exist'); +}; diff --git a/x-pack/plugins/osquery/cypress/tasks/navigation.ts b/x-pack/plugins/osquery/cypress/tasks/navigation.ts index b6acc081feccd..7a4b9df573370 100644 --- a/x-pack/plugins/osquery/cypress/tasks/navigation.ts +++ b/x-pack/plugins/osquery/cypress/tasks/navigation.ts @@ -24,6 +24,19 @@ export const navigateTo = (page: string, opts?: Partial) = waitForReact(); }; +// We're moving away from using react-cypress-selector, I'll be adjusting this on file by file approach +export const navigateToWithoutWaitForReact = ( + page: string, + opts?: Partial +) => { + cy.visit(page, opts); + cy.contains('Loading Elastic').should('exist'); + cy.contains('Loading Elastic').should('not.exist'); + + // There's a security warning toast that seemingly makes ui elements in the bottom right unavailable, so we close it + closeToastIfVisible(); +}; + export const waitForReact = () => { cy.waitForReact( 10000, diff --git a/x-pack/plugins/osquery/cypress/tasks/packs.ts b/x-pack/plugins/osquery/cypress/tasks/packs.ts index f8bd23f2c7b10..98d10e39c1813 100644 --- a/x-pack/plugins/osquery/cypress/tasks/packs.ts +++ b/x-pack/plugins/osquery/cypress/tasks/packs.ts @@ -20,26 +20,16 @@ export const preparePack = (packName: string) => { createdPack.click(); }; -export const deactivatePack = (packName: string) => { - cy.react('ActiveStateSwitchComponent', { - props: { item: { name: packName } }, - }).click(); - closeModalIfVisible(); +export const changePackActiveStatus = (packName: string) => { + const regex = new RegExp(`Successfully (activated|deactivated) "${packName}" pack`); - cy.contains(`Successfully deactivated "${packName}" pack`).should('not.exist'); - cy.contains(`Successfully deactivated "${packName}" pack`).should('exist'); - closeToastIfVisible(); -}; - -export const activatePack = (packName: string) => { - cy.react('ActiveStateSwitchComponent', { - props: { item: { name: packName } }, - }).click(); + cy.getBySel('globalLoadingIndicator').should('not.exist'); + cy.get(`[aria-label="${packName}"]`).click(); closeModalIfVisible(); - - cy.contains(`Successfully activated "${packName}" pack`).should('not.exist'); - cy.contains(`Successfully activated "${packName}" pack`).should('exist'); + cy.contains(regex).should('not.exist'); + cy.contains(regex).should('exist'); closeToastIfVisible(); + cy.contains(regex).should('not.exist'); }; export const cleanupAllPrebuiltPacks = () => { diff --git a/x-pack/plugins/osquery/cypress/tasks/wait_until.ts b/x-pack/plugins/osquery/cypress/tasks/wait_until.ts index 30df5bc0708fe..361a371865dcb 100644 --- a/x-pack/plugins/osquery/cypress/tasks/wait_until.ts +++ b/x-pack/plugins/osquery/cypress/tasks/wait_until.ts @@ -6,7 +6,7 @@ */ export const waitUntil = (fn: () => Cypress.Chainable) => { - const timeout = 90000; + const timeout = 120000; const interval = 5000; let attempts = timeout / interval; diff --git a/x-pack/plugins/osquery/package.json b/x-pack/plugins/osquery/package.json index e9ab128dd45fb..4e9070d780d28 100644 --- a/x-pack/plugins/osquery/package.json +++ b/x-pack/plugins/osquery/package.json @@ -15,6 +15,7 @@ "cypress:serverless:run": "yarn cypress:serverless run", "nyc": "../../../node_modules/.bin/nyc report --reporter=text-summary", "junit:merge": "../../../node_modules/.bin/mochawesome-merge ../../../target/kibana-osquery/cypress/results/mochawesome*.json > ../../../target/kibana-osquery/cypress/results/output.json && ../../../node_modules/.bin/marge ../../../target/kibana-osquery/cypress/results/output.json --reportDir ../../../target/kibana-osquery/cypress/results && yarn junit:transform && mkdir -p ../../../target/junit && cp ../../../target/kibana-osquery/cypress/results/*.xml ../../../target/junit/", - "junit:transform": "node ../security_solution/scripts/junit_transformer --pathPattern '../../../target/kibana-osquery/cypress/results/*.xml' --rootDirectory ../../../ --reportName 'Osquery Cypress' --writeInPlace" + "junit:transform": "node ../security_solution/scripts/junit_transformer --pathPattern '../../../target/kibana-osquery/cypress/results/*.xml' --rootDirectory ../../../ --reportName 'Osquery Cypress' --writeInPlace", + "openapi:generate": "node scripts/openapi/generate" } } diff --git a/x-pack/plugins/osquery/public/packs/active_state_switch.tsx b/x-pack/plugins/osquery/public/packs/active_state_switch.tsx index 7d973e2af82d6..92cd929ae5298 100644 --- a/x-pack/plugins/osquery/public/packs/active_state_switch.tsx +++ b/x-pack/plugins/osquery/public/packs/active_state_switch.tsx @@ -96,6 +96,7 @@ const ActiveStateSwitchComponent: React.FC = ({ item }) checked={!!item.enabled} disabled={!permissions.writePacks || isLoading} showLabel={false} + aria-label={item.name} label="" onChange={handleToggleActiveClick} /> diff --git a/x-pack/plugins/osquery/public/packs/add_pack_button.tsx b/x-pack/plugins/osquery/public/packs/add_pack_button.tsx index 70a97f2354a54..07df6d83c7284 100644 --- a/x-pack/plugins/osquery/public/packs/add_pack_button.tsx +++ b/x-pack/plugins/osquery/public/packs/add_pack_button.tsx @@ -25,6 +25,7 @@ const AddPackButtonComponent: React.FC = ({ fill = {...newQueryLinkProps} iconType="plusInCircle" isDisabled={!permissions.writePacks} + data-test-subj={'addPackButton'} > diff --git a/x-pack/plugins/osquery/public/packs/form/index.tsx b/x-pack/plugins/osquery/public/packs/form/index.tsx index 259e6d0d7b9ee..43420efd47e3f 100644 --- a/x-pack/plugins/osquery/public/packs/form/index.tsx +++ b/x-pack/plugins/osquery/public/packs/form/index.tsx @@ -315,6 +315,7 @@ const PackFormComponent: React.FC = ({ size="m" iconType="save" onClick={handleSaveClick} + data-test-subj={`${editMode ? 'update' : 'save'}PackButton`} > {editMode ? ( = ({ limit, charts, showFrames }) => { +export function ChartGrid({ limit, charts, showFrames }: ChartGridProps) { const maximum = Math.min(limit, charts.length ?? 0); - const ncharts = Math.min(maximum, charts.length); const [selectedSubchart, setSelectedSubchart] = useState(undefined); + const subCharts = useMemo(() => { + return take(charts, ncharts).map((subchart, i) => ( + + + { + setSelectedSubchart(subchart); + }} + showFrames={showFrames} + padTitle + /> + + + )); + }, [charts, ncharts, showFrames]); + return ( <> -

Top {charts.length}

+

+ {i18n.translate('xpack.profiling.chartGrid.h1.topLabel', { + defaultMessage: 'Top {size}', + values: { size: charts.length }, + })} +

- {take(charts, ncharts).map((subchart, i) => ( - - - { - setSelectedSubchart(subchart); - }} - showFrames={showFrames} - padTitle - /> - - - ))} + {subCharts} {selectedSubchart && ( = ({ limit, charts, showFrames data={selectedSubchart.Series} sample={null} showAxes - onShowMoreClick={null} showFrames={showFrames} padTitle /> @@ -82,4 +90,4 @@ export const ChartGrid: React.FC = ({ limit, charts, showFrames )} ); -}; +} diff --git a/x-pack/plugins/profiling/public/components/topn_functions_summary/index.tsx b/x-pack/plugins/profiling/public/components/frames_summary/index.tsx similarity index 64% rename from x-pack/plugins/profiling/public/components/topn_functions_summary/index.tsx rename to x-pack/plugins/profiling/public/components/frames_summary/index.tsx index e3994ab442b7b..e90527ffefe11 100644 --- a/x-pack/plugins/profiling/public/components/topn_functions_summary/index.tsx +++ b/x-pack/plugins/profiling/public/components/frames_summary/index.tsx @@ -5,67 +5,74 @@ * 2.0. */ -import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; +import { + EuiAccordion, + EuiFlexGroup, + EuiFlexItem, + EuiIcon, + EuiSpacer, + EuiText, + EuiTextColor, +} from '@elastic/eui'; import React, { useMemo } from 'react'; -import type { TopNFunctions } from '@kbn/profiling-utils'; +import { i18n } from '@kbn/i18n'; +import { useCalculateImpactEstimate } from '../../hooks/use_calculate_impact_estimates'; import { asCost } from '../../utils/formatters/as_cost'; import { asWeight } from '../../utils/formatters/as_weight'; import { calculateBaseComparisonDiff } from '../topn_functions/utils'; import { SummaryItem } from './summary_item'; -import { useCalculateImpactEstimate } from '../../hooks/use_calculate_impact_estimates'; + +interface FrameValue { + selfCPU: number; + totalCPU: number; + totalCount: number; + duration: number; + scaleFactor?: number; +} interface Props { - baselineTopNFunctions?: TopNFunctions; - comparisonTopNFunctions?: TopNFunctions; - baselineScaleFactor?: number; - comparisonScaleFactor?: number; + baseValue?: FrameValue; + comparisonValue?: FrameValue; isLoading: boolean; - baselineDuration: number; - comparisonDuration: number; } const ESTIMATED_VALUE_LABEL = i18n.translate('xpack.profiling.diffTopNFunctions.estimatedValue', { defaultMessage: 'Estimated value', }) as string; -export function TopNFunctionsSummary({ - baselineTopNFunctions, - comparisonTopNFunctions, - baselineScaleFactor = 1, - comparisonScaleFactor = 1, - isLoading, - baselineDuration, - comparisonDuration, -}: Props) { +function getScaleFactor(scaleFactor: number = 1) { + return scaleFactor; +} + +export function FramesSummary({ baseValue, comparisonValue, isLoading }: Props) { const calculateImpactEstimates = useCalculateImpactEstimate(); - const baselineScaledTotalSamples = baselineTopNFunctions - ? baselineTopNFunctions.TotalCount * baselineScaleFactor + const baselineScaledTotalSamples = baseValue + ? baseValue.totalCount * getScaleFactor(baseValue.scaleFactor) : 0; - const comparisonScaledTotalSamples = comparisonTopNFunctions - ? comparisonTopNFunctions.TotalCount * comparisonScaleFactor + const comparisonScaledTotalSamples = comparisonValue + ? comparisonValue.totalCount * getScaleFactor(comparisonValue.scaleFactor) : 0; const { co2EmissionDiff, costImpactDiff, totalSamplesDiff } = useMemo(() => { - const baseImpactEstimates = baselineTopNFunctions + const baseImpactEstimates = baseValue ? // Do NOT scale values here. This is intended to show the exact values spent throughout the year calculateImpactEstimates({ - countExclusive: baselineTopNFunctions.selfCPU, - countInclusive: baselineTopNFunctions.totalCPU, - totalSamples: baselineTopNFunctions.TotalCount, - totalSeconds: baselineDuration, + countExclusive: baseValue.selfCPU, + countInclusive: baseValue.totalCPU, + totalSamples: baseValue.totalCount, + totalSeconds: baseValue.duration, }) : undefined; - const comparisonImpactEstimates = comparisonTopNFunctions + const comparisonImpactEstimates = comparisonValue ? // Do NOT scale values here. This is intended to show the exact values spent throughout the year calculateImpactEstimates({ - countExclusive: comparisonTopNFunctions.selfCPU, - countInclusive: comparisonTopNFunctions.totalCPU, - totalSamples: comparisonTopNFunctions.TotalCount, - totalSeconds: comparisonDuration, + countExclusive: comparisonValue.selfCPU, + countInclusive: comparisonValue.totalCPU, + totalSamples: comparisonValue.totalCount, + totalSeconds: comparisonValue.duration, }) : undefined; @@ -86,13 +93,11 @@ export function TopNFunctionsSummary({ }), }; }, [ - baselineDuration, + baseValue, baselineScaledTotalSamples, - baselineTopNFunctions, calculateImpactEstimates, - comparisonDuration, comparisonScaledTotalSamples, - comparisonTopNFunctions, + comparisonValue, ]); const data = [ @@ -155,14 +160,41 @@ export function TopNFunctionsSummary({ ]; return ( - - {data.map((item, idx) => { - return ( - - + + + + {data[0].title} + + + {data[0].baseIcon && ( + + + + )} + + + {data[0].baseValue} + - ); - })} - +
+ } + > + <> + + + {data.map((item, idx) => { + return ( + + + + ); + })} + + + ); } diff --git a/x-pack/plugins/profiling/public/components/topn_functions_summary/summary_item.test.ts b/x-pack/plugins/profiling/public/components/frames_summary/summary_item.test.ts similarity index 100% rename from x-pack/plugins/profiling/public/components/topn_functions_summary/summary_item.test.ts rename to x-pack/plugins/profiling/public/components/frames_summary/summary_item.test.ts diff --git a/x-pack/plugins/profiling/public/components/topn_functions_summary/summary_item.tsx b/x-pack/plugins/profiling/public/components/frames_summary/summary_item.tsx similarity index 100% rename from x-pack/plugins/profiling/public/components/topn_functions_summary/summary_item.tsx rename to x-pack/plugins/profiling/public/components/frames_summary/summary_item.tsx diff --git a/x-pack/plugins/profiling/public/components/stacked_bar_chart/index.tsx b/x-pack/plugins/profiling/public/components/stacked_bar_chart/index.tsx index 55892be80b31f..ad4aedfc81b46 100644 --- a/x-pack/plugins/profiling/public/components/stacked_bar_chart/index.tsx +++ b/x-pack/plugins/profiling/public/components/stacked_bar_chart/index.tsx @@ -84,7 +84,6 @@ export function StackedBarChart({ height={128} width={MAX_TOOLTIP_WIDTH} showAxes={false} - onShowMoreClick={null} padTitle={false} /> diff --git a/x-pack/plugins/profiling/public/components/subchart.tsx b/x-pack/plugins/profiling/public/components/subchart.tsx index 4aaf0e683d839..4ae0056f63b24 100644 --- a/x-pack/plugins/profiling/public/components/subchart.tsx +++ b/x-pack/plugins/profiling/public/components/subchart.tsx @@ -20,9 +20,11 @@ import { } from '@elastic/charts'; import { EuiAccordion, + EuiAccordionProps, EuiBadge, EuiButton, EuiFlexGroup, + EuiFlexGroupProps, EuiFlexItem, EuiHorizontalRule, EuiIcon, @@ -35,7 +37,7 @@ import { import { i18n } from '@kbn/i18n'; import type { StackFrameMetadata } from '@kbn/profiling-utils'; import { groupBy } from 'lodash'; -import React, { Fragment } from 'react'; +import React, { Fragment, useMemo, useState } from 'react'; import { css } from '@emotion/react'; import { CountPerTime, OTHER_BUCKET_LABEL, TopNSample } from '../../common/topn'; import { useKibanaTimeZoneSetting } from '../hooks/use_kibana_timezone_setting'; @@ -58,8 +60,8 @@ export interface SubChartProps { data: CountPerTime[]; showAxes: boolean; metadata: StackFrameMetadata[]; - onShowMoreClick: (() => void) | null; - style?: React.ComponentProps['style']; + onShowMoreClick?: () => void; + style?: EuiFlexGroupProps['style']; showFrames: boolean; padTitle: boolean; sample: TopNSample | null; @@ -98,6 +100,9 @@ export function SubChart({ sample, }: SubChartProps) { const theme = useEuiTheme(); + const [accordionState, setAccordionState] = useState< + Record + >({}); const profilingRouter = useProfilingRouter(); @@ -114,15 +119,21 @@ export function SubChart({ const compact = !!onShowMoreClick; - const groupedMetadata = groupBy(metadata, 'AddressOrLine'); - const parentsMetadata = Object.values(groupedMetadata) - .map((items) => items.shift()) - .filter((_) => _) as StackFrameMetadata[]; - + const parentsMetadata = metadata.filter((item) => item.Inline === false); const displayedFrames = compact ? parentsMetadata.concat().reverse().slice(0, NUM_DISPLAYED_FRAMES) : parentsMetadata.concat().reverse(); + const childrenMetadata = useMemo(() => { + const groupedMetadata = groupBy(metadata, 'AddressOrLine'); + return Object.keys(groupedMetadata).reduce>((acc, key) => { + // Removes the first item as it will always be the parent item. + const [_, ...children] = groupedMetadata[key]; + acc[key] = children; + return acc; + }, {}); + }, [metadata]); + const hasMoreFrames = displayedFrames.length < metadata.length; let bottomElement: React.ReactElement; @@ -139,12 +150,23 @@ export function SubChart({ {displayedFrames.map((frame, frameIndex) => { const parentIndex = parentsMetadata.indexOf(frame) + 1; - const children = groupedMetadata[frame.AddressOrLine].concat().reverse(); - + const children = childrenMetadata[frame.AddressOrLine].concat().reverse(); + const key = [frameIndex, frame.FrameID].join('|'); + const currentAccordionState = accordionState[key]; return ( - <> + {children.length > 0 ? ( { + setAccordionState((state) => ({ + ...state, + [key]: isOpen ? 'open' : 'closed', + })); + }} css={css` display: flex; flex-direction: column-reverse; @@ -171,22 +193,24 @@ export function SubChart({ } > - - {children.map((child, childIndex) => { - return ( - - {renderFrameItem( - child, - `${parentIndex}.${children.length - childIndex} ->` - )} - - ); - })} - + {currentAccordionState === 'open' ? ( + + {children.map((child, childIndex) => { + return ( + + {renderFrameItem( + child, + `${parentIndex}.${children.length - childIndex} ->` + )} + + ); + })} + + ) : null} ) : ( renderFrameItem(frame, parentIndex) @@ -196,7 +220,7 @@ export function SubChart({
) : null} - + ); })}
diff --git a/x-pack/plugins/profiling/public/components/topn_functions_summary/extra_value.tsx b/x-pack/plugins/profiling/public/components/topn_functions_summary/extra_value.tsx deleted file mode 100644 index c331ebf9d810b..0000000000000 --- a/x-pack/plugins/profiling/public/components/topn_functions_summary/extra_value.tsx +++ /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 { EuiFlexGroup, EuiFlexItem, EuiIcon, EuiText } from '@elastic/eui'; -import React from 'react'; - -interface Props { - value?: string; - diff?: string; - color?: string; - icon?: string; -} - -export function ExtraValue({ value, diff, color, icon }: Props) { - return ( - - - - {`${value} (${diff})`} - - - - {icon && } - - - ); -} diff --git a/x-pack/plugins/profiling/public/views/flamegraphs/differential_flamegraphs/index.tsx b/x-pack/plugins/profiling/public/views/flamegraphs/differential_flamegraphs/index.tsx index c176826baa4fe..a6f0a9bb42203 100644 --- a/x-pack/plugins/profiling/public/views/flamegraphs/differential_flamegraphs/index.tsx +++ b/x-pack/plugins/profiling/public/views/flamegraphs/differential_flamegraphs/index.tsx @@ -4,7 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import { EuiFlexGroup, EuiFlexItem, EuiPanel } from '@elastic/eui'; +import { EuiFlexGroup, EuiFlexItem, EuiPanel, EuiSpacer } from '@elastic/eui'; import React from 'react'; import { AsyncComponent } from '../../../components/async_component'; import { useProfilingDependencies } from '../../../components/contexts/profiling_dependencies/use_profiling_dependencies'; @@ -16,6 +16,8 @@ import { useProfilingRouter } from '../../../hooks/use_profiling_router'; import { useTimeRange } from '../../../hooks/use_time_range'; import { useTimeRangeAsync } from '../../../hooks/use_time_range_async'; import { DifferentialFlameGraphSearchPanel } from './differential_flame_graph_search_panel'; +import { FramesSummary } from '../../../components/frames_summary'; +import { AsyncStatus } from '../../../hooks/use_async'; export function DifferentialFlameGraphsView() { const { @@ -118,6 +120,32 @@ export function DifferentialFlameGraphsView() { normalizationMode={normalizationMode} normalizationOptions={normalizationOptions} /> + +
diff --git a/x-pack/plugins/profiling/public/views/functions/differential_topn/index.tsx b/x-pack/plugins/profiling/public/views/functions/differential_topn/index.tsx index b853bbc5eb0d2..cf538642afce8 100644 --- a/x-pack/plugins/profiling/public/views/functions/differential_topn/index.tsx +++ b/x-pack/plugins/profiling/public/views/functions/differential_topn/index.tsx @@ -13,11 +13,12 @@ import { EuiPanel, EuiSpacer, } from '@elastic/eui'; +import { TopNFunctionSortField } from '@kbn/profiling-utils'; import React, { useRef } from 'react'; import { GridOnScrollProps } from 'react-window'; -import { TopNFunctionSortField } from '@kbn/profiling-utils'; import { AsyncComponent } from '../../../components/async_component'; import { useProfilingDependencies } from '../../../components/contexts/profiling_dependencies/use_profiling_dependencies'; +import { FramesSummary } from '../../../components/frames_summary'; import { NormalizationMenu, NormalizationMode, @@ -25,7 +26,6 @@ import { } from '../../../components/normalization_menu'; import { PrimaryAndComparisonSearchBar } from '../../../components/primary_and_comparison_search_bar'; import { TopNFunctionsGrid } from '../../../components/topn_functions'; -import { TopNFunctionsSummary } from '../../../components/topn_functions_summary'; import { AsyncStatus } from '../../../hooks/use_async'; import { useProfilingParams } from '../../../hooks/use_profiling_params'; import { useProfilingRouter } from '../../../hooks/use_profiling_router'; @@ -192,21 +192,36 @@ export function DifferentialTopNFunctionsView() { onChange={onChangeNormalizationMode} /> - - diff --git a/x-pack/plugins/reporting/server/lib/content_stream.ts b/x-pack/plugins/reporting/server/lib/content_stream.ts index 0228132200e62..7bf7f1108776e 100644 --- a/x-pack/plugins/reporting/server/lib/content_stream.ts +++ b/x-pack/plugins/reporting/server/lib/content_stream.ts @@ -8,7 +8,7 @@ import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { ByteSizeValue } from '@kbn/config-schema'; import type { ElasticsearchClient, Logger } from '@kbn/core/server'; import { defaults, get } from 'lodash'; -import Puid from 'puid'; +import { v4 as uuidv4 } from 'uuid'; import { Duplex } from 'stream'; import type { ReportingCore } from '..'; import type { ReportSource } from '../../common/types'; @@ -74,7 +74,6 @@ export class ContentStream extends Duplex { private jobSize?: number; private maxChunkSize?: number; private parameters: Required; - private puid = new Puid(); private primaryTerm?: number; private seqNo?: number; @@ -233,7 +232,7 @@ export class ContentStream extends Duplex { private async writeChunk(content: string) { const { id: parentId, index } = this.document; - const id = this.puid.generate(); + const id = uuidv4(); this.logger.debug(`Writing chunk #${this.chunksWritten} (${id}).`); diff --git a/x-pack/plugins/security/server/plugin.ts b/x-pack/plugins/security/server/plugin.ts index d196dd9f41139..341ab79e97e5b 100644 --- a/x-pack/plugins/security/server/plugin.ts +++ b/x-pack/plugins/security/server/plugin.ts @@ -201,6 +201,7 @@ export class SecurityPlugin private readonly userSettingService: UserSettingService; private userSettingServiceStart?: UserSettingServiceStart; + private userProfileSettingsClient: UserProfileSettingsClient; private readonly getUserProfileService = () => { if (!this.userProfileStart) { throw new Error(`userProfileStart is not registered!`); @@ -233,6 +234,10 @@ export class SecurityPlugin ); this.analyticsService = new AnalyticsService(this.initializerContext.logger.get('analytics')); + + this.userProfileSettingsClient = new UserProfileSettingsClient( + this.initializerContext.logger.get('user-settings-client') + ); } public setup( @@ -255,25 +260,12 @@ export class SecurityPlugin const kibanaIndexName = this.getKibanaIndexName(); // A subset of `start` services we need during `setup`. - const startServicesPromise = core - .getStartServices() - .then(([coreServices, depsServices, startServices]) => ({ - elasticsearch: coreServices.elasticsearch, - features: depsServices.features, - userProfiles: startServices.userProfiles, - })); - - /** - * Once the UserProfileServiceStart is available, use it to start the SecurityPlugin > UserSettingService. - * - * Then the UserProfileSettingsClient is created with the SecurityPlugin > UserSettingServiceStart and set on - * the Core > UserSettingsServiceSetup - */ - startServicesPromise.then(({ userProfiles }) => { - this.userSettingServiceStart = this.userSettingService.start(userProfiles); - const client = new UserProfileSettingsClient(this.userSettingServiceStart); - core.userSettings.setUserProfileSettings(client); - }); + const startServicesPromise = core.getStartServices().then(([coreServices, depsServices]) => ({ + elasticsearch: coreServices.elasticsearch, + features: depsServices.features, + })); + + core.userSettings.setUserProfileSettings(this.userProfileSettingsClient); const { license } = this.securityLicenseService.setup({ license$: licensing.license$, @@ -408,6 +400,7 @@ export class SecurityPlugin this.userProfileStart = this.userProfileService.start({ clusterClient, session }); this.userSettingServiceStart = this.userSettingService.start(this.userProfileStart); + this.userProfileSettingsClient.setUserSettingsServiceStart(this.userSettingServiceStart); // In serverless, we want to redirect users to the list of projects instead of standard "Logged Out" page. const customLogoutURL = diff --git a/x-pack/plugins/security/server/user_profile/user_profile_settings_client.test.ts b/x-pack/plugins/security/server/user_profile/user_profile_settings_client.test.ts index dfcc88c8ca5a1..46202d5a94ea2 100644 --- a/x-pack/plugins/security/server/user_profile/user_profile_settings_client.test.ts +++ b/x-pack/plugins/security/server/user_profile/user_profile_settings_client.test.ts @@ -5,7 +5,9 @@ * 2.0. */ +import { loggingSystemMock } from '@kbn/core/server/mocks'; import type { httpServerMock } from '@kbn/core-http-server-mocks'; +import type { Logger } from '@kbn/logging'; import { UserProfileSettingsClient } from './user_profile_settings_client'; import type { UserSettingServiceStart } from './user_setting_service'; @@ -13,20 +15,31 @@ import type { UserSettingServiceStart } from './user_setting_service'; describe('UserProfileSettingsClient', () => { let mockRequest: ReturnType; let client: UserProfileSettingsClient; + let logger: Logger; + let userSettingServiceStart: jest.Mocked; beforeEach(() => { - const userSettingsServiceStart = { + userSettingServiceStart = { getCurrentUserProfileSettings: jest.fn(), - } as jest.Mocked; + }; - userSettingsServiceStart.getCurrentUserProfileSettings.mockResolvedValue({ darkMode: 'dark' }); + userSettingServiceStart.getCurrentUserProfileSettings.mockResolvedValue({ darkMode: 'dark' }); - client = new UserProfileSettingsClient(userSettingsServiceStart); + logger = loggingSystemMock.createLogger(); + client = new UserProfileSettingsClient(logger); }); describe('#get', () => { - it('should return user settings', async () => { + it('should return empty before UserSettingServiceStart is set', async () => { const userSettings = await client.get(mockRequest); + expect(userSettings).toEqual({}); + expect(logger.debug).toHaveBeenCalledWith('UserSettingsServiceStart has not been set yet'); + }); + + it('should return user settings after UserSettingServiceStart is set', async () => { + client.setUserSettingsServiceStart(userSettingServiceStart); + const userSettings = await client.get(mockRequest); + expect(userSettings).toEqual({ darkMode: 'dark' }); }); }); diff --git a/x-pack/plugins/security/server/user_profile/user_profile_settings_client.ts b/x-pack/plugins/security/server/user_profile/user_profile_settings_client.ts index a888f22256acc..03bf4855cbc79 100644 --- a/x-pack/plugins/security/server/user_profile/user_profile_settings_client.ts +++ b/x-pack/plugins/security/server/user_profile/user_profile_settings_client.ts @@ -4,28 +4,42 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ - +import type { Logger } from '@kbn/core/server'; import type { KibanaRequest } from '@kbn/core-http-server'; import type { UserProfileSettingsClientContract } from '@kbn/core-user-settings-server'; import type { UserSettingServiceStart } from './user_setting_service'; - /** * A wrapper client around {@link UserSettingServiceStart} that exposes a method to get the current user's profile */ export class UserProfileSettingsClient implements UserProfileSettingsClientContract { - private userSettingsServiceStart: UserSettingServiceStart; + private userSettingServiceStart: UserSettingServiceStart | undefined; + private logger: Logger; - constructor(userSettingsServiceStart: UserSettingServiceStart) { - this.userSettingsServiceStart = userSettingsServiceStart; + constructor(logger: Logger) { + this.logger = logger; } /** * Returns the current user's user profile settings * * @param request the KibanaRequest that is required to get the current user and their settings + * @return the User Settings values retrieved from the UserSettingsServiceStart, if it has been set, otherwise, + * default to an empty Record */ async get(request: KibanaRequest): Promise> { - return await this.userSettingsServiceStart.getCurrentUserProfileSettings(request); + let result: Record = {} as Record; + + if (this.userSettingServiceStart) { + result = await this.userSettingServiceStart.getCurrentUserProfileSettings(request); + } else { + this.logger.debug('UserSettingsServiceStart has not been set yet'); + } + + return result; + } + + setUserSettingsServiceStart(userSettingServiceStart: UserSettingServiceStart) { + this.userSettingServiceStart = userSettingServiceStart; } } diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/left/components/entities_details.test.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/entities_details.test.tsx index 80d7324d1cf51..0a8807b2fb75a 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/left/components/entities_details.test.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/entities_details.test.tsx @@ -14,6 +14,14 @@ import { EntitiesDetails } from './entities_details'; import { ENTITIES_DETAILS_TEST_ID, HOST_DETAILS_TEST_ID, USER_DETAILS_TEST_ID } from './test_ids'; import { mockContextValue } from '../mocks/mock_context'; import { EXPANDABLE_PANEL_CONTENT_TEST_ID } from '../../../shared/components/test_ids'; +import type { Anomalies } from '../../../../common/components/ml/types'; +import { useMlCapabilities } from '../../../../common/components/ml/hooks/use_ml_capabilities'; +import { useRiskScore } from '../../../../explore/containers/risk_score'; +import { mockAnomalies } from '../../../../common/components/ml/mock'; +import { useHostDetails } from '../../../../explore/hosts/containers/hosts/details'; +import { useHostRelatedUsers } from '../../../../common/containers/related_entities/related_users'; +import { useObservedUserDetails } from '../../../../explore/users/containers/users/observed_details'; +import { useUserRelatedHosts } from '../../../../common/containers/related_entities/related_hosts'; jest.mock('react-router-dom', () => { const actual = jest.requireActual('react-router-dom'); @@ -32,6 +40,61 @@ jest.mock('react-redux', () => { }; }); +const from = '2022-07-28T08:20:18.966Z'; +const to = '2022-07-28T08:20:18.966Z'; +jest.mock('../../../../common/containers/use_global_time', () => { + const actual = jest.requireActual('../../../../common/containers/use_global_time'); + return { + ...actual, + useGlobalTime: jest + .fn() + .mockReturnValue({ from, to, setQuery: jest.fn(), deleteQuery: jest.fn() }), + }; +}); + +jest.mock('uuid', () => ({ + v4: jest.fn().mockReturnValue('uuid'), +})); + +jest.mock('../../../../common/components/ml/hooks/use_ml_capabilities'); +const mockUseMlUserPermissions = useMlCapabilities as jest.Mock; + +const mockUseHasSecurityCapability = jest.fn().mockReturnValue(false); +jest.mock('../../../../helper_hooks', () => ({ + useHasSecurityCapability: () => mockUseHasSecurityCapability(), +})); + +jest.mock('../../../../common/containers/sourcerer', () => ({ + useSourcererDataView: jest.fn().mockReturnValue({ selectedPatterns: ['index'] }), +})); + +jest.mock('../../../../common/components/ml/anomaly/anomaly_table_provider', () => ({ + AnomalyTableProvider: ({ + children, + }: { + children: (args: { + anomaliesData: Anomalies; + isLoadingAnomaliesData: boolean; + jobNameById: Record; + }) => React.ReactNode; + }) => children({ anomaliesData: mockAnomalies, isLoadingAnomaliesData: false, jobNameById: {} }), +})); + +jest.mock('../../../../explore/hosts/containers/hosts/details'); +const mockUseHostDetails = useHostDetails as jest.Mock; + +jest.mock('../../../../common/containers/related_entities/related_users'); +const mockUseHostsRelatedUsers = useHostRelatedUsers as jest.Mock; + +jest.mock('../../../../explore/containers/risk_score'); +const mockUseRiskScore = useRiskScore as jest.Mock; + +jest.mock('../../../../explore/users/containers/users/observed_details'); +const mockUseObservedUserDetails = useObservedUserDetails as jest.Mock; + +jest.mock('../../../../common/containers/related_entities/related_hosts'); +const mockUseUsersRelatedHosts = useUserRelatedHosts as jest.Mock; + const USER_TEST_ID = EXPANDABLE_PANEL_CONTENT_TEST_ID(USER_DETAILS_TEST_ID); const HOST_TEST_ID = EXPANDABLE_PANEL_CONTENT_TEST_ID(HOST_DETAILS_TEST_ID); @@ -47,6 +110,26 @@ const renderEntitiesDetails = (contextValue: LeftPanelContext) => ); describe('', () => { + beforeEach(() => { + mockUseMlUserPermissions.mockReturnValue({ isPlatinumOrTrialLicense: false, capabilities: {} }); + mockUseHasSecurityCapability.mockReturnValue(false); + mockUseHostDetails.mockReturnValue([false, {}]); + mockUseRiskScore.mockReturnValue({ data: [], isAuthorized: false }); + mockUseHostsRelatedUsers.mockReturnValue({ + inspect: jest.fn(), + refetch: jest.fn(), + relatedUsers: [], + loading: false, + }); + mockUseObservedUserDetails.mockReturnValue([false, {}]); + mockUseUsersRelatedHosts.mockReturnValue({ + inspect: jest.fn(), + refetch: jest.fn(), + relatedHosts: [], + loading: false, + }); + }); + it('renders entities details correctly', () => { const { getByTestId, queryByText } = renderEntitiesDetails(mockContextValue); expect(getByTestId(ENTITIES_DETAILS_TEST_ID)).toBeInTheDocument(); diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/preview/components/rule_preview.test.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/preview/components/rule_preview.test.tsx index 095973bb0d260..78f8dff0e3211 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/preview/components/rule_preview.test.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/preview/components/rule_preview.test.tsx @@ -72,6 +72,7 @@ const NO_DATA_MESSAGE = 'There was an error displaying data.'; describe('', () => { afterEach(() => { jest.clearAllMocks(); + mockUseGetSavedQuery.mockReturnValue({ isSavedQueryLoading: false, savedQueryBar: null }); }); it('should render rule preview and its sub sections', async () => { @@ -84,7 +85,6 @@ describe('', () => { scheduleRuleData: mockScheduleStepRule(), ruleActionsData: { actions: ['action'] }, }); - mockUseGetSavedQuery.mockReturnValue({ isSavedQueryLoading: false, savedQueryBar: null }); const { getByTestId } = renderRulePreview(); @@ -124,6 +124,7 @@ describe('', () => { it('should render loading spinner when rule is loading', async () => { mockUseRuleWithFallback.mockReturnValue({ loading: true, rule: null }); + mockGetStepsData.mockReturnValue({}); const { getByTestId } = renderRulePreview(); await act(async () => { expect(getByTestId(RULE_PREVIEW_LOADING_TEST_ID)).toBeInTheDocument(); @@ -132,6 +133,7 @@ describe('', () => { it('should not render rule preview when rule is null', async () => { mockUseRuleWithFallback.mockReturnValue({}); + mockGetStepsData.mockReturnValue({}); const { queryByTestId, getByText } = renderRulePreview(); await act(async () => { expect(queryByTestId(RULE_PREVIEW_BODY_TEST_ID)).not.toBeInTheDocument(); diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/entities_overview.test.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/entities_overview.test.tsx index bfee7825748b6..117420358ded5 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/entities_overview.test.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/entities_overview.test.tsx @@ -15,6 +15,10 @@ import { } from './test_ids'; import { EntitiesOverview } from './entities_overview'; import { TestProviders } from '../../../../common/mock'; +import { useRiskScore } from '../../../../explore/containers/risk_score'; +import { useFirstLastSeen } from '../../../../common/containers/use_first_last_seen'; +import { useObservedUserDetails } from '../../../../explore/users/containers/users/observed_details'; +import { useHostDetails } from '../../../../explore/hosts/containers/hosts/details'; import { mockGetFieldsData } from '../../shared/mocks/mock_get_fields_data'; import { EXPANDABLE_PANEL_HEADER_TITLE_ICON_TEST_ID, @@ -23,6 +27,36 @@ import { EXPANDABLE_PANEL_TOGGLE_ICON_TEST_ID, } from '../../../shared/components/test_ids'; +const from = '2022-04-05T12:00:00.000Z'; +const to = '2022-04-08T12:00:00.;000Z'; +const selectedPatterns = 'alerts'; + +const mockUseGlobalTime = jest.fn().mockReturnValue({ from, to }); +jest.mock('../../../../common/containers/use_global_time', () => { + return { + useGlobalTime: (...props: unknown[]) => mockUseGlobalTime(...props), + }; +}); + +const mockUseSourcererDataView = jest.fn().mockReturnValue({ selectedPatterns }); +jest.mock('../../../../common/containers/sourcerer', () => { + return { + useSourcererDataView: (...props: unknown[]) => mockUseSourcererDataView(...props), + }; +}); + +const mockUseUserDetails = useObservedUserDetails as jest.Mock; +jest.mock('../../../../explore/users/containers/users/observed_details'); + +const mockUseRiskScore = useRiskScore as jest.Mock; +jest.mock('../../../../explore/containers/risk_score'); + +const mockUseFirstLastSeen = useFirstLastSeen as jest.Mock; +jest.mock('../../../../common/containers/use_first_last_seen'); + +const mockUseHostDetails = useHostDetails as jest.Mock; +jest.mock('../../../../explore/hosts/containers/hosts/details'); + const TOGGLE_ICON_TEST_ID = EXPANDABLE_PANEL_TOGGLE_ICON_TEST_ID(INSIGHTS_ENTITIES_TEST_ID); const TITLE_LINK_TEST_ID = EXPANDABLE_PANEL_HEADER_TITLE_LINK_TEST_ID(INSIGHTS_ENTITIES_TEST_ID); const TITLE_ICON_TEST_ID = EXPANDABLE_PANEL_HEADER_TITLE_ICON_TEST_ID(INSIGHTS_ENTITIES_TEST_ID); @@ -47,6 +81,12 @@ const renderEntitiesOverview = (contextValue: RightPanelContext) => const NO_DATA_MESSAGE = 'Host and user information are unavailable for this alert.'; describe('', () => { + beforeEach(() => { + mockUseUserDetails.mockReturnValue([false, { userDetails: null }]); + mockUseRiskScore.mockReturnValue({ data: null, isAuthorized: false }); + mockUseHostDetails.mockReturnValue([false, { hostDetails: null }]); + mockUseFirstLastSeen.mockReturnValue([false, { lastSeen: null }]); + }); it('should render wrapper component', () => { const { getByTestId, queryByTestId } = renderEntitiesOverview(mockContextValue); diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/insights_section.test.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/insights_section.test.tsx index a7edc0927fb12..bb776547d2a9f 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/insights_section.test.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/insights_section.test.tsx @@ -10,6 +10,12 @@ import { render } from '@testing-library/react'; import { RightPanelContext } from '../context'; import { INSIGHTS_HEADER_TEST_ID } from './test_ids'; import { TestProviders } from '../../../../common/mock'; +import { useRiskScore } from '../../../../explore/containers/risk_score'; +import { useFirstLastSeen } from '../../../../common/containers/use_first_last_seen'; +import { useObservedUserDetails } from '../../../../explore/users/containers/users/observed_details'; +import { useHostDetails } from '../../../../explore/hosts/containers/hosts/details'; +import { useFetchThreatIntelligence } from '../hooks/use_fetch_threat_intelligence'; +import { usePrevalence } from '../../shared/hooks/use_prevalence'; import { mockGetFieldsData } from '../../shared/mocks/mock_get_fields_data'; import { mockDataFormattedForFieldBrowser } from '../../shared/mocks/mock_data_formatted_for_field_browser'; import { InsightsSection } from './insights_section'; @@ -41,6 +47,40 @@ jest.mock('react-router-dom', () => { alertIds: [], }); +const from = '2022-04-05T12:00:00.000Z'; +const to = '2022-04-08T12:00:00.;000Z'; +const selectedPatterns = 'alerts'; + +const mockUseGlobalTime = jest.fn().mockReturnValue({ from, to }); +jest.mock('../../../../common/containers/use_global_time', () => { + return { + useGlobalTime: (...props: unknown[]) => mockUseGlobalTime(...props), + }; +}); + +const mockUseSourcererDataView = jest.fn().mockReturnValue({ selectedPatterns }); +jest.mock('../../../../common/containers/sourcerer', () => { + return { + useSourcererDataView: (...props: unknown[]) => mockUseSourcererDataView(...props), + }; +}); + +const mockUseUserDetails = useObservedUserDetails as jest.Mock; +jest.mock('../../../../explore/users/containers/users/observed_details'); + +const mockUseRiskScore = useRiskScore as jest.Mock; +jest.mock('../../../../explore/containers/risk_score'); + +const mockUseFirstLastSeen = useFirstLastSeen as jest.Mock; +jest.mock('../../../../common/containers/use_first_last_seen'); + +const mockUseHostDetails = useHostDetails as jest.Mock; +jest.mock('../../../../explore/hosts/containers/hosts/details'); + +jest.mock('../hooks/use_fetch_threat_intelligence'); + +jest.mock('../../shared/hooks/use_prevalence'); + const renderInsightsSection = (contextValue: RightPanelContext, expanded: boolean) => render( @@ -51,6 +91,23 @@ const renderInsightsSection = (contextValue: RightPanelContext, expanded: boolea ); describe('', () => { + beforeEach(() => { + mockUseUserDetails.mockReturnValue([false, { userDetails: null }]); + mockUseRiskScore.mockReturnValue({ data: null, isAuthorized: false }); + mockUseHostDetails.mockReturnValue([false, { hostDetails: null }]); + mockUseFirstLastSeen.mockReturnValue([false, { lastSeen: null }]); + (useFetchThreatIntelligence as jest.Mock).mockReturnValue({ + loading: false, + threatMatchesCount: 2, + threatEnrichmentsCount: 2, + }); + (usePrevalence as jest.Mock).mockReturnValue({ + loading: false, + error: false, + data: [], + }); + }); + it('should render insights component', () => { const contextValue = { eventId: 'some_Id', diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/suppressed_alerts.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/suppressed_alerts.tsx index ce466a66a499d..ca98a20bc36b1 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/suppressed_alerts.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/suppressed_alerts.tsx @@ -53,7 +53,7 @@ export const SuppressedAlerts: React.VFC = ({ alertSuppre tooltipContent={ } tooltipPosition="bottom" diff --git a/x-pack/plugins/security_solution/public/management/cypress/e2e/artifacts/artifact_tabs_in_policy_details.cy.ts b/x-pack/plugins/security_solution/public/management/cypress/e2e/artifacts/artifact_tabs_in_policy_details.cy.ts index 52df24ab87826..5988b73852af5 100644 --- a/x-pack/plugins/security_solution/public/management/cypress/e2e/artifacts/artifact_tabs_in_policy_details.cy.ts +++ b/x-pack/plugins/security_solution/public/management/cypress/e2e/artifacts/artifact_tabs_in_policy_details.cy.ts @@ -5,13 +5,13 @@ * 2.0. */ +import { getEndpointSecurityPolicyManager } from '../../../../../scripts/endpoint/common/roles_users'; import { getRoleWithArtifactReadPrivilege } from '../../fixtures/role_with_artifact_read_privilege'; -import { getEndpointSecurityPolicyManager } from '../../../../../scripts/endpoint/common/roles_users/endpoint_security_policy_manager'; import { getArtifactsListTestsData } from '../../fixtures/artifacts_page'; import { visitPolicyDetailsPage } from '../../screens/policy_details'; import { - createPerPolicyArtifact, createArtifactList, + createPerPolicyArtifact, removeAllArtifacts, removeExceptionsList, yieldFirstPolicyID, diff --git a/x-pack/plugins/security_solution/public/management/cypress/e2e/response_actions/document_signing.cy.ts b/x-pack/plugins/security_solution/public/management/cypress/e2e/response_actions/document_signing.cy.ts new file mode 100644 index 0000000000000..b806323726018 --- /dev/null +++ b/x-pack/plugins/security_solution/public/management/cypress/e2e/response_actions/document_signing.cy.ts @@ -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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { PolicyData } from '../../../../../common/endpoint/types'; +import type { CreateAndEnrollEndpointHostResponse } from '../../../../../scripts/endpoint/common/endpoint_host_services'; +import { + openResponseConsoleFromEndpointList, + performCommandInputChecks, + submitCommand, + waitForEndpointListPageToBeLoaded, +} from '../../tasks/response_console'; +import type { IndexedFleetEndpointPolicyResponse } from '../../../../../common/endpoint/data_loaders/index_fleet_endpoint_policy'; +import { createAgentPolicyTask, getEndpointIntegrationVersion } from '../../tasks/fleet'; +import { checkEndpointListForOnlyUnIsolatedHosts } from '../../tasks/isolate'; + +import { login } from '../../tasks/login'; +import { enableAllPolicyProtections } from '../../tasks/endpoint_policy'; +import { createEndpointHost } from '../../tasks/create_endpoint_host'; +import { deleteAllLoadedEndpointData } from '../../tasks/delete_all_endpoint_data'; + +describe('Document signing:', { tags: ['@ess', '@serverless', '@brokenInServerless'] }, () => { + let indexedPolicy: IndexedFleetEndpointPolicyResponse; + let policy: PolicyData; + let createdHost: CreateAndEnrollEndpointHostResponse; + + before(() => { + getEndpointIntegrationVersion().then((version) => + createAgentPolicyTask(version).then((data) => { + indexedPolicy = data; + policy = indexedPolicy.integrationPolicies[0]; + + return enableAllPolicyProtections(policy.id).then(() => { + // Create and enroll a new Endpoint host + return createEndpointHost(policy.policy_id).then((host) => { + createdHost = host as CreateAndEnrollEndpointHostResponse; + }); + }); + }) + ); + }); + + after(() => { + if (createdHost) { + cy.task('destroyEndpointHost', createdHost); + } + + if (indexedPolicy) { + cy.task('deleteIndexedFleetEndpointPolicies', indexedPolicy); + } + + if (createdHost) { + deleteAllLoadedEndpointData({ endpointAgentIds: [createdHost.agentId] }); + } + }); + + beforeEach(() => { + login(); + }); + + it('should fail if data tampered', () => { + waitForEndpointListPageToBeLoaded(createdHost.hostname); + checkEndpointListForOnlyUnIsolatedHosts(); + openResponseConsoleFromEndpointList(); + performCommandInputChecks('isolate'); + + // stop host so that we ensure tamper happens before endpoint processes the action + cy.task('stopEndpointHost', createdHost.hostname); + // get action doc before we submit command, so we know when the new action doc is indexed + cy.task('getLatestActionDoc').then((previousActionDoc) => { + submitCommand(); + cy.task('tamperActionDoc', previousActionDoc); + }); + cy.task('startEndpointHost', createdHost.hostname); + + const actionValidationErrorMsg = + 'Fleet action response error: Failed to validate action signature; check Endpoint logs for details'; + // wait for 3 minutes for the response to be indexed + cy.contains(actionValidationErrorMsg, { timeout: 180000 }).should('exist'); + }); +}); diff --git a/x-pack/plugins/security_solution/public/management/cypress/e2e/response_actions/response_console/execute.cy.ts b/x-pack/plugins/security_solution/public/management/cypress/e2e/response_actions/response_console/execute.cy.ts new file mode 100644 index 0000000000000..dad573bb09c2b --- /dev/null +++ b/x-pack/plugins/security_solution/public/management/cypress/e2e/response_actions/response_console/execute.cy.ts @@ -0,0 +1,74 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import type { PolicyData } from '../../../../../../common/endpoint/types'; +import type { CreateAndEnrollEndpointHostResponse } from '../../../../../../scripts/endpoint/common/endpoint_host_services'; +import { + inputConsoleCommand, + openResponseConsoleFromEndpointList, + submitCommand, + waitForCommandToBeExecuted, + waitForEndpointListPageToBeLoaded, +} from '../../../tasks/response_console'; +import type { IndexedFleetEndpointPolicyResponse } from '../../../../../../common/endpoint/data_loaders/index_fleet_endpoint_policy'; +import { createAgentPolicyTask, getEndpointIntegrationVersion } from '../../../tasks/fleet'; + +import { login } from '../../../tasks/login'; +import { enableAllPolicyProtections } from '../../../tasks/endpoint_policy'; +import { createEndpointHost } from '../../../tasks/create_endpoint_host'; +import { deleteAllLoadedEndpointData } from '../../../tasks/delete_all_endpoint_data'; + +describe('Response console', { tags: ['@ess', '@serverless'] }, () => { + beforeEach(() => { + login(); + }); + + describe('Execute operations:', () => { + const homeFilePath = process.env.CI || true ? '/home/vagrant' : `/home/ubuntu`; + + let indexedPolicy: IndexedFleetEndpointPolicyResponse; + let policy: PolicyData; + let createdHost: CreateAndEnrollEndpointHostResponse; + + before(() => { + getEndpointIntegrationVersion().then((version) => + createAgentPolicyTask(version).then((data) => { + indexedPolicy = data; + policy = indexedPolicy.integrationPolicies[0]; + + return enableAllPolicyProtections(policy.id).then(() => { + // Create and enroll a new Endpoint host + return createEndpointHost(policy.policy_id).then((host) => { + createdHost = host as CreateAndEnrollEndpointHostResponse; + }); + }); + }) + ); + }); + + after(() => { + if (createdHost) { + cy.task('destroyEndpointHost', createdHost); + } + + if (indexedPolicy) { + cy.task('deleteIndexedFleetEndpointPolicies', indexedPolicy); + } + + if (createdHost) { + deleteAllLoadedEndpointData({ endpointAgentIds: [createdHost.agentId] }); + } + }); + + it('"execute --command" - should execute a command', () => { + waitForEndpointListPageToBeLoaded(createdHost.hostname); + openResponseConsoleFromEndpointList(); + inputConsoleCommand(`execute --command "ls -al ${homeFilePath}"`); + submitCommand(); + waitForCommandToBeExecuted('execute'); + }); + }); +}); diff --git a/x-pack/plugins/security_solution/public/management/cypress/e2e/response_actions/response_console/file_operations.cy.ts b/x-pack/plugins/security_solution/public/management/cypress/e2e/response_actions/response_console/file_operations.cy.ts new file mode 100644 index 0000000000000..ccea07c117820 --- /dev/null +++ b/x-pack/plugins/security_solution/public/management/cypress/e2e/response_actions/response_console/file_operations.cy.ts @@ -0,0 +1,121 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import type { PolicyData } from '../../../../../../common/endpoint/types'; +import type { CreateAndEnrollEndpointHostResponse } from '../../../../../../scripts/endpoint/common/endpoint_host_services'; +import { + inputConsoleCommand, + openResponseConsoleFromEndpointList, + submitCommand, + waitForCommandToBeExecuted, + waitForEndpointListPageToBeLoaded, +} from '../../../tasks/response_console'; +import type { IndexedFleetEndpointPolicyResponse } from '../../../../../../common/endpoint/data_loaders/index_fleet_endpoint_policy'; +import { createAgentPolicyTask, getEndpointIntegrationVersion } from '../../../tasks/fleet'; + +import { login } from '../../../tasks/login'; +import { enableAllPolicyProtections } from '../../../tasks/endpoint_policy'; +import { createEndpointHost } from '../../../tasks/create_endpoint_host'; +import { deleteAllLoadedEndpointData } from '../../../tasks/delete_all_endpoint_data'; + +describe('Response console', { tags: ['@ess', '@serverless'] }, () => { + beforeEach(() => { + login(); + }); + + describe('File operations:', () => { + const homeFilePath = process.env.CI || true ? '/home/vagrant' : `/home/ubuntu`; + + const fileContent = 'This is a test file for the get-file command.'; + const filePath = `${homeFilePath}/test_file.txt`; + + let indexedPolicy: IndexedFleetEndpointPolicyResponse; + let policy: PolicyData; + let createdHost: CreateAndEnrollEndpointHostResponse; + + before(() => { + getEndpointIntegrationVersion().then((version) => + createAgentPolicyTask(version).then((data) => { + indexedPolicy = data; + policy = indexedPolicy.integrationPolicies[0]; + + return enableAllPolicyProtections(policy.id).then(() => { + // Create and enroll a new Endpoint host + return createEndpointHost(policy.policy_id).then((host) => { + createdHost = host as CreateAndEnrollEndpointHostResponse; + }); + }); + }) + ); + }); + + after(() => { + if (createdHost) { + cy.task('destroyEndpointHost', createdHost); + } + + if (indexedPolicy) { + cy.task('deleteIndexedFleetEndpointPolicies', indexedPolicy); + } + + if (createdHost) { + deleteAllLoadedEndpointData({ endpointAgentIds: [createdHost.agentId] }); + } + }); + + it('"get-file --path" - should retrieve a file', () => { + waitForEndpointListPageToBeLoaded(createdHost.hostname); + cy.task('createFileOnEndpoint', { + hostname: createdHost.hostname, + path: filePath, + content: fileContent, + }); + openResponseConsoleFromEndpointList(); + inputConsoleCommand(`get-file --path ${filePath}`); + submitCommand(); + cy.getByTestSubj('getFileSuccess', { timeout: 60000 }).within(() => { + cy.contains('File retrieved from the host.'); + cy.contains('(ZIP file passcode: elastic)'); + cy.contains( + 'Files are periodically deleted to clear storage space. Download and save file locally if needed.' + ); + cy.contains('Click here to download').click(); + const downloadsFolder = Cypress.config('downloadsFolder'); + cy.readFile(`${downloadsFolder}/upload.zip`); + + cy.task('uploadFileToEndpoint', { + hostname: createdHost.hostname, + srcPath: `${downloadsFolder}/upload.zip`, + destPath: `${homeFilePath}/upload.zip`, + }); + + cy.task('readZippedFileContentOnEndpoint', { + hostname: createdHost.hostname, + path: `${homeFilePath}/upload.zip`, + password: 'elastic', + }).then((unzippedFileContent) => { + expect(unzippedFileContent).to.equal(fileContent); + }); + }); + }); + + it('"upload --file" - should upload a file', () => { + waitForEndpointListPageToBeLoaded(createdHost.hostname); + openResponseConsoleFromEndpointList(); + inputConsoleCommand(`upload --file`); + cy.getByTestSubj('console-arg-file-picker').selectFile( + { + contents: Cypress.Buffer.from('upload file content here!'), + fileName: 'upload_file.txt', + lastModified: Date.now(), + }, + { force: true } + ); + submitCommand(); + waitForCommandToBeExecuted('upload'); + }); + }); +}); diff --git a/x-pack/plugins/security_solution/public/management/cypress/e2e/response_actions/response_console/isolation.cy.ts b/x-pack/plugins/security_solution/public/management/cypress/e2e/response_actions/response_console/isolation.cy.ts new file mode 100644 index 0000000000000..5b0d198742ede --- /dev/null +++ b/x-pack/plugins/security_solution/public/management/cypress/e2e/response_actions/response_console/isolation.cy.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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { PolicyData } from '../../../../../../common/endpoint/types'; +import type { CreateAndEnrollEndpointHostResponse } from '../../../../../../scripts/endpoint/common/endpoint_host_services'; +import { + openResponseConsoleFromEndpointList, + performCommandInputChecks, + submitCommand, + waitForCommandToBeExecuted, + waitForEndpointListPageToBeLoaded, +} from '../../../tasks/response_console'; +import type { IndexedFleetEndpointPolicyResponse } from '../../../../../../common/endpoint/data_loaders/index_fleet_endpoint_policy'; +import { createAgentPolicyTask, getEndpointIntegrationVersion } from '../../../tasks/fleet'; +import { + checkEndpointListForOnlyIsolatedHosts, + checkEndpointListForOnlyUnIsolatedHosts, + isolateHostFromEndpointList, +} from '../../../tasks/isolate'; + +import { login } from '../../../tasks/login'; +import { enableAllPolicyProtections } from '../../../tasks/endpoint_policy'; +import { createEndpointHost } from '../../../tasks/create_endpoint_host'; +import { deleteAllLoadedEndpointData } from '../../../tasks/delete_all_endpoint_data'; + +// Failing: See https://github.com/elastic/kibana/issues/170470 +describe.skip('Response console', { tags: ['@ess', '@serverless'] }, () => { + beforeEach(() => { + login(); + }); + + describe('Host Isolation:', () => { + let indexedPolicy: IndexedFleetEndpointPolicyResponse; + let policy: PolicyData; + let createdHost: CreateAndEnrollEndpointHostResponse; + + before(() => { + getEndpointIntegrationVersion().then((version) => + createAgentPolicyTask(version).then((data) => { + indexedPolicy = data; + policy = indexedPolicy.integrationPolicies[0]; + + return enableAllPolicyProtections(policy.id).then(() => { + // Create and enroll a new Endpoint host + return createEndpointHost(policy.policy_id).then((host) => { + createdHost = host as CreateAndEnrollEndpointHostResponse; + }); + }); + }) + ); + }); + + after(() => { + if (createdHost) { + cy.task('destroyEndpointHost', createdHost); + } + + if (indexedPolicy) { + cy.task('deleteIndexedFleetEndpointPolicies', indexedPolicy); + } + + if (createdHost) { + deleteAllLoadedEndpointData({ endpointAgentIds: [createdHost.agentId] }); + } + }); + + it('should release an isolated host from response console', () => { + const command = 'release'; + waitForEndpointListPageToBeLoaded(createdHost.hostname); + // isolate the host first + isolateHostFromEndpointList(); + checkEndpointListForOnlyIsolatedHosts(); + openResponseConsoleFromEndpointList(); + performCommandInputChecks(command); + submitCommand(); + waitForCommandToBeExecuted(command); + waitForEndpointListPageToBeLoaded(createdHost.hostname); + checkEndpointListForOnlyUnIsolatedHosts(); + }); + + it('should isolate a host from response console', () => { + const command = 'isolate'; + waitForEndpointListPageToBeLoaded(createdHost.hostname); + checkEndpointListForOnlyUnIsolatedHosts(); + openResponseConsoleFromEndpointList(); + performCommandInputChecks(command); + submitCommand(); + waitForCommandToBeExecuted(command); + waitForEndpointListPageToBeLoaded(createdHost.hostname); + checkEndpointListForOnlyIsolatedHosts(); + }); + }); +}); diff --git a/x-pack/plugins/security_solution/public/management/cypress/e2e/response_actions/response_console/process_operations.cy.ts b/x-pack/plugins/security_solution/public/management/cypress/e2e/response_actions/response_console/process_operations.cy.ts new file mode 100644 index 0000000000000..3faf7373f5569 --- /dev/null +++ b/x-pack/plugins/security_solution/public/management/cypress/e2e/response_actions/response_console/process_operations.cy.ts @@ -0,0 +1,126 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license 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 { PolicyData } from '../../../../../../common/endpoint/types'; +import type { CreateAndEnrollEndpointHostResponse } from '../../../../../../scripts/endpoint/common/endpoint_host_services'; +import { + inputConsoleCommand, + openResponseConsoleFromEndpointList, + performCommandInputChecks, + submitCommand, + waitForCommandToBeExecuted, + waitForEndpointListPageToBeLoaded, +} from '../../../tasks/response_console'; +import type { IndexedFleetEndpointPolicyResponse } from '../../../../../../common/endpoint/data_loaders/index_fleet_endpoint_policy'; +import { createAgentPolicyTask, getEndpointIntegrationVersion } from '../../../tasks/fleet'; + +import { login } from '../../../tasks/login'; +import { enableAllPolicyProtections } from '../../../tasks/endpoint_policy'; +import { createEndpointHost } from '../../../tasks/create_endpoint_host'; +import { deleteAllLoadedEndpointData } from '../../../tasks/delete_all_endpoint_data'; + +describe('Response console', { tags: ['@ess', '@serverless'] }, () => { + beforeEach(() => { + login(); + }); + + describe('Processes operations:', () => { + let cronPID: string; + let newCronPID: string; + + let indexedPolicy: IndexedFleetEndpointPolicyResponse; + let policy: PolicyData; + let createdHost: CreateAndEnrollEndpointHostResponse; + + before(() => { + getEndpointIntegrationVersion().then((version) => + createAgentPolicyTask(version).then((data) => { + indexedPolicy = data; + policy = indexedPolicy.integrationPolicies[0]; + + return enableAllPolicyProtections(policy.id).then(() => { + // Create and enroll a new Endpoint host + return createEndpointHost(policy.policy_id).then((host) => { + createdHost = host as CreateAndEnrollEndpointHostResponse; + }); + }); + }) + ); + }); + + after(() => { + if (createdHost) { + cy.task('destroyEndpointHost', createdHost); + } + + if (indexedPolicy) { + cy.task('deleteIndexedFleetEndpointPolicies', indexedPolicy); + } + + if (createdHost) { + deleteAllLoadedEndpointData({ endpointAgentIds: [createdHost.agentId] }); + } + }); + + it('"processes" - should obtain a list of processes', () => { + waitForEndpointListPageToBeLoaded(createdHost.hostname); + openResponseConsoleFromEndpointList(); + performCommandInputChecks('processes'); + submitCommand(); + cy.contains('Action pending.').should('exist'); + cy.getByTestSubj('getProcessesSuccessCallout', { timeout: 120000 }).within(() => { + ['USER', 'PID', 'ENTITY ID', 'COMMAND'].forEach((header) => { + cy.contains(header); + }); + + cy.get('tbody > tr').should('have.length.greaterThan', 0); + cy.get('tbody > tr > td').should('contain', '/usr/sbin/cron'); + cy.get('tbody > tr > td') + .contains('/usr/sbin/cron') + .parents('td') + .siblings('td') + .eq(1) + .find('span') + .then((span) => { + cronPID = span.text(); + }); + }); + }); + + it('"kill-process --pid" - should kill a process', () => { + waitForEndpointListPageToBeLoaded(createdHost.hostname); + openResponseConsoleFromEndpointList(); + inputConsoleCommand(`kill-process --pid ${cronPID}`); + submitCommand(); + waitForCommandToBeExecuted('kill-process'); + + performCommandInputChecks('processes'); + submitCommand(); + + cy.getByTestSubj('getProcessesSuccessCallout', { timeout: 120000 }).within(() => { + cy.get('tbody > tr > td') + .contains('/usr/sbin/cron') + .parents('td') + .siblings('td') + .eq(1) + .find('span') + .then((span) => { + newCronPID = span.text(); + }); + }); + expect(newCronPID).to.not.equal(cronPID); + }); + + it('"suspend-process --pid" - should suspend a process', () => { + waitForEndpointListPageToBeLoaded(createdHost.hostname); + openResponseConsoleFromEndpointList(); + inputConsoleCommand(`suspend-process --pid ${newCronPID}`); + submitCommand(); + waitForCommandToBeExecuted('suspend-process'); + }); + }); +}); diff --git a/x-pack/plugins/security_solution/public/management/cypress/e2e/response_actions/response_console_actions.cy.ts b/x-pack/plugins/security_solution/public/management/cypress/e2e/response_actions/response_console_actions.cy.ts deleted file mode 100644 index 858da349c51ad..0000000000000 --- a/x-pack/plugins/security_solution/public/management/cypress/e2e/response_actions/response_console_actions.cy.ts +++ /dev/null @@ -1,348 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import type { PolicyData } from '../../../../../common/endpoint/types'; -import type { CreateAndEnrollEndpointHostResponse } from '../../../../../scripts/endpoint/common/endpoint_host_services'; -import { - inputConsoleCommand, - openResponseConsoleFromEndpointList, - performCommandInputChecks, - submitCommand, - waitForCommandToBeExecuted, - waitForEndpointListPageToBeLoaded, -} from '../../tasks/response_console'; -import type { IndexedFleetEndpointPolicyResponse } from '../../../../../common/endpoint/data_loaders/index_fleet_endpoint_policy'; -import { createAgentPolicyTask, getEndpointIntegrationVersion } from '../../tasks/fleet'; -import { - checkEndpointListForOnlyIsolatedHosts, - checkEndpointListForOnlyUnIsolatedHosts, -} from '../../tasks/isolate'; - -import { login } from '../../tasks/login'; -import { enableAllPolicyProtections } from '../../tasks/endpoint_policy'; -import { createEndpointHost } from '../../tasks/create_endpoint_host'; -import { deleteAllLoadedEndpointData } from '../../tasks/delete_all_endpoint_data'; - -describe('Response console', { tags: ['@ess', '@serverless'] }, () => { - beforeEach(() => { - login(); - }); - - describe('User journey for Isolate command: isolate and release an endpoint', () => { - let indexedPolicy: IndexedFleetEndpointPolicyResponse; - let policy: PolicyData; - let createdHost: CreateAndEnrollEndpointHostResponse; - - before(() => { - getEndpointIntegrationVersion().then((version) => - createAgentPolicyTask(version).then((data) => { - indexedPolicy = data; - policy = indexedPolicy.integrationPolicies[0]; - - return enableAllPolicyProtections(policy.id).then(() => { - // Create and enroll a new Endpoint host - return createEndpointHost(policy.policy_id).then((host) => { - createdHost = host as CreateAndEnrollEndpointHostResponse; - }); - }); - }) - ); - }); - - after(() => { - if (createdHost) { - cy.task('destroyEndpointHost', createdHost); - } - - if (indexedPolicy) { - cy.task('deleteIndexedFleetEndpointPolicies', indexedPolicy); - } - - if (createdHost) { - deleteAllLoadedEndpointData({ endpointAgentIds: [createdHost.agentId] }); - } - }); - - it('should isolate host from response console', () => { - const command = 'isolate'; - waitForEndpointListPageToBeLoaded(createdHost.hostname); - checkEndpointListForOnlyUnIsolatedHosts(); - openResponseConsoleFromEndpointList(); - performCommandInputChecks(command); - submitCommand(); - waitForCommandToBeExecuted(command); - waitForEndpointListPageToBeLoaded(createdHost.hostname); - checkEndpointListForOnlyIsolatedHosts(); - }); - - it('should release host from response console', () => { - const command = 'release'; - waitForEndpointListPageToBeLoaded(createdHost.hostname); - checkEndpointListForOnlyIsolatedHosts(); - openResponseConsoleFromEndpointList(); - performCommandInputChecks(command); - submitCommand(); - waitForCommandToBeExecuted(command); - waitForEndpointListPageToBeLoaded(createdHost.hostname); - checkEndpointListForOnlyUnIsolatedHosts(); - }); - }); - - describe('User journey for Processes operations: list, kill and suspend process', () => { - let cronPID: string; - let newCronPID: string; - - let indexedPolicy: IndexedFleetEndpointPolicyResponse; - let policy: PolicyData; - let createdHost: CreateAndEnrollEndpointHostResponse; - - before(() => { - getEndpointIntegrationVersion().then((version) => - createAgentPolicyTask(version).then((data) => { - indexedPolicy = data; - policy = indexedPolicy.integrationPolicies[0]; - - return enableAllPolicyProtections(policy.id).then(() => { - // Create and enroll a new Endpoint host - return createEndpointHost(policy.policy_id).then((host) => { - createdHost = host as CreateAndEnrollEndpointHostResponse; - }); - }); - }) - ); - }); - - after(() => { - if (createdHost) { - cy.task('destroyEndpointHost', createdHost); - } - - if (indexedPolicy) { - cy.task('deleteIndexedFleetEndpointPolicies', indexedPolicy); - } - - if (createdHost) { - deleteAllLoadedEndpointData({ endpointAgentIds: [createdHost.agentId] }); - } - }); - - it('"processes" - should obtain a list of processes', () => { - waitForEndpointListPageToBeLoaded(createdHost.hostname); - openResponseConsoleFromEndpointList(); - performCommandInputChecks('processes'); - submitCommand(); - cy.contains('Action pending.').should('exist'); - cy.getByTestSubj('getProcessesSuccessCallout', { timeout: 120000 }).within(() => { - ['USER', 'PID', 'ENTITY ID', 'COMMAND'].forEach((header) => { - cy.contains(header); - }); - - cy.get('tbody > tr').should('have.length.greaterThan', 0); - cy.get('tbody > tr > td').should('contain', '/usr/sbin/cron'); - cy.get('tbody > tr > td') - .contains('/usr/sbin/cron') - .parents('td') - .siblings('td') - .eq(1) - .find('span') - .then((span) => { - cronPID = span.text(); - }); - }); - }); - - it('"kill-process --pid" - should kill a process', () => { - waitForEndpointListPageToBeLoaded(createdHost.hostname); - openResponseConsoleFromEndpointList(); - inputConsoleCommand(`kill-process --pid ${cronPID}`); - submitCommand(); - waitForCommandToBeExecuted('kill-process'); - - performCommandInputChecks('processes'); - submitCommand(); - - cy.getByTestSubj('getProcessesSuccessCallout', { timeout: 120000 }).within(() => { - cy.get('tbody > tr > td') - .contains('/usr/sbin/cron') - .parents('td') - .siblings('td') - .eq(1) - .find('span') - .then((span) => { - newCronPID = span.text(); - }); - }); - expect(newCronPID).to.not.equal(cronPID); - }); - - it('"suspend-process --pid" - should suspend a process', () => { - waitForEndpointListPageToBeLoaded(createdHost.hostname); - openResponseConsoleFromEndpointList(); - inputConsoleCommand(`suspend-process --pid ${newCronPID}`); - submitCommand(); - waitForCommandToBeExecuted('suspend-process'); - }); - }); - - describe('File operations: get-file, upload and execute', () => { - const homeFilePath = process.env.CI || true ? '/home/vagrant' : `/home/ubuntu`; - - const fileContent = 'This is a test file for the get-file command.'; - const filePath = `${homeFilePath}/test_file.txt`; - - let indexedPolicy: IndexedFleetEndpointPolicyResponse; - let policy: PolicyData; - let createdHost: CreateAndEnrollEndpointHostResponse; - - before(() => { - getEndpointIntegrationVersion().then((version) => - createAgentPolicyTask(version).then((data) => { - indexedPolicy = data; - policy = indexedPolicy.integrationPolicies[0]; - - return enableAllPolicyProtections(policy.id).then(() => { - // Create and enroll a new Endpoint host - return createEndpointHost(policy.policy_id).then((host) => { - createdHost = host as CreateAndEnrollEndpointHostResponse; - }); - }); - }) - ); - }); - - after(() => { - if (createdHost) { - cy.task('destroyEndpointHost', createdHost); - } - - if (indexedPolicy) { - cy.task('deleteIndexedFleetEndpointPolicies', indexedPolicy); - } - - if (createdHost) { - deleteAllLoadedEndpointData({ endpointAgentIds: [createdHost.agentId] }); - } - }); - - it('"get-file --path" - should retrieve a file', () => { - waitForEndpointListPageToBeLoaded(createdHost.hostname); - cy.task('createFileOnEndpoint', { - hostname: createdHost.hostname, - path: filePath, - content: fileContent, - }); - openResponseConsoleFromEndpointList(); - inputConsoleCommand(`get-file --path ${filePath}`); - submitCommand(); - cy.getByTestSubj('getFileSuccess', { timeout: 60000 }).within(() => { - cy.contains('File retrieved from the host.'); - cy.contains('(ZIP file passcode: elastic)'); - cy.contains( - 'Files are periodically deleted to clear storage space. Download and save file locally if needed.' - ); - cy.contains('Click here to download').click(); - const downloadsFolder = Cypress.config('downloadsFolder'); - cy.readFile(`${downloadsFolder}/upload.zip`); - - cy.task('uploadFileToEndpoint', { - hostname: createdHost.hostname, - srcPath: `${downloadsFolder}/upload.zip`, - destPath: `${homeFilePath}/upload.zip`, - }); - - cy.task('readZippedFileContentOnEndpoint', { - hostname: createdHost.hostname, - path: `${homeFilePath}/upload.zip`, - password: 'elastic', - }).then((unzippedFileContent) => { - expect(unzippedFileContent).to.equal(fileContent); - }); - }); - }); - - it('"execute --command" - should execute a command', () => { - waitForEndpointListPageToBeLoaded(createdHost.hostname); - openResponseConsoleFromEndpointList(); - inputConsoleCommand(`execute --command "ls -al ${homeFilePath}"`); - submitCommand(); - waitForCommandToBeExecuted('execute'); - }); - - it('"upload --file" - should upload a file', () => { - waitForEndpointListPageToBeLoaded(createdHost.hostname); - openResponseConsoleFromEndpointList(); - inputConsoleCommand(`upload --file`); - cy.getByTestSubj('console-arg-file-picker').selectFile( - { - contents: Cypress.Buffer.from('upload file content here!'), - fileName: 'upload_file.txt', - lastModified: Date.now(), - }, - { force: true } - ); - submitCommand(); - waitForCommandToBeExecuted('upload'); - }); - }); - - // FLAKY: https://github.com/elastic/kibana/issues/168296 - describe.skip('document signing', () => { - let indexedPolicy: IndexedFleetEndpointPolicyResponse; - let policy: PolicyData; - let createdHost: CreateAndEnrollEndpointHostResponse; - - before(() => { - getEndpointIntegrationVersion().then((version) => - createAgentPolicyTask(version).then((data) => { - indexedPolicy = data; - policy = indexedPolicy.integrationPolicies[0]; - - return enableAllPolicyProtections(policy.id).then(() => { - // Create and enroll a new Endpoint host - return createEndpointHost(policy.policy_id).then((host) => { - createdHost = host as CreateAndEnrollEndpointHostResponse; - }); - }); - }) - ); - }); - - after(() => { - if (createdHost) { - cy.task('destroyEndpointHost', createdHost); - } - - if (indexedPolicy) { - cy.task('deleteIndexedFleetEndpointPolicies', indexedPolicy); - } - - if (createdHost) { - deleteAllLoadedEndpointData({ endpointAgentIds: [createdHost.agentId] }); - } - }); - - it('should fail if data tampered', () => { - waitForEndpointListPageToBeLoaded(createdHost.hostname); - checkEndpointListForOnlyUnIsolatedHosts(); - openResponseConsoleFromEndpointList(); - performCommandInputChecks('isolate'); - - // stop host so that we ensure tamper happens before endpoint processes the action - cy.task('stopEndpointHost', createdHost.hostname); - // get action doc before we submit command so we know when the new action doc is indexed - cy.task('getLatestActionDoc').then((previousActionDoc) => { - submitCommand(); - cy.task('tamperActionDoc', previousActionDoc); - }); - cy.task('startEndpointHost', createdHost.hostname); - - const actionValidationErrorMsg = - 'Fleet action response error: Failed to validate action signature; check Endpoint logs for details'; - cy.contains(actionValidationErrorMsg, { timeout: 120000 }).should('exist'); - }); - }); -}); diff --git a/x-pack/plugins/security_solution/public/management/cypress/e2e/response_actions/response_console_mocked/execute.cy.ts b/x-pack/plugins/security_solution/public/management/cypress/e2e/response_actions/response_console_mocked/execute.cy.ts new file mode 100644 index 0000000000000..5c7432129e43b --- /dev/null +++ b/x-pack/plugins/security_solution/public/management/cypress/e2e/response_actions/response_console_mocked/execute.cy.ts @@ -0,0 +1,63 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { ActionDetails } from '../../../../../../common/endpoint/types'; +import type { ReturnTypeFromChainable } from '../../../types'; +import { indexEndpointHosts } from '../../../tasks/index_endpoint_hosts'; +import { + inputConsoleCommand, + openResponseConsoleFromEndpointList, + submitCommand, + waitForEndpointListPageToBeLoaded, +} from '../../../tasks/response_console'; +import { interceptActionRequests, sendActionResponse } from '../../../tasks/isolate'; +import { login } from '../../../tasks/login'; + +describe('Response console', { tags: ['@ess', '@serverless', '@brokenInServerless'] }, () => { + beforeEach(() => { + login(); + }); + + describe('`execute` command', () => { + let endpointData: ReturnTypeFromChainable; + let endpointHostname: string; + let executeRequestResponse: ActionDetails; + + beforeEach(() => { + indexEndpointHosts({ withResponseActions: false, isolation: false }).then( + (indexEndpoints) => { + endpointData = indexEndpoints; + endpointHostname = endpointData.data.hosts[0].host.name; + } + ); + }); + + afterEach(() => { + if (endpointData) { + endpointData.cleanup(); + // @ts-expect-error ignore setting to undefined + endpointData = undefined; + } + }); + + it('should execute a command from response console', () => { + waitForEndpointListPageToBeLoaded(endpointHostname); + openResponseConsoleFromEndpointList(); + inputConsoleCommand(`execute --command "ls -al"`); + + interceptActionRequests((responseBody) => { + executeRequestResponse = responseBody; + }, 'execute'); + submitCommand(); + cy.contains('Action pending.').should('exist'); + cy.wait('@execute').then(() => { + sendActionResponse(executeRequestResponse); + }); + cy.contains('Command execution was successful', { timeout: 120000 }).should('exist'); + }); + }); +}); diff --git a/x-pack/plugins/security_solution/public/management/cypress/e2e/response_actions/response_console_mocked/get_file.cy.ts b/x-pack/plugins/security_solution/public/management/cypress/e2e/response_actions/response_console_mocked/get_file.cy.ts new file mode 100644 index 0000000000000..978b1e2cd37df --- /dev/null +++ b/x-pack/plugins/security_solution/public/management/cypress/e2e/response_actions/response_console_mocked/get_file.cy.ts @@ -0,0 +1,73 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { ActionDetails } from '../../../../../../common/endpoint/types'; +import type { ReturnTypeFromChainable } from '../../../types'; +import { indexEndpointHosts } from '../../../tasks/index_endpoint_hosts'; +import { + inputConsoleCommand, + openResponseConsoleFromEndpointList, + submitCommand, + waitForEndpointListPageToBeLoaded, +} from '../../../tasks/response_console'; +import { interceptActionRequests, sendActionResponse } from '../../../tasks/isolate'; +import { login } from '../../../tasks/login'; + +describe('Response console', { tags: ['@ess', '@serverless', '@brokenInServerless'] }, () => { + beforeEach(() => { + login(); + }); + + describe('`get-file` command', () => { + let endpointData: ReturnTypeFromChainable; + let endpointHostname: string; + let getFileRequestResponse: ActionDetails; + + beforeEach(() => { + indexEndpointHosts({ withResponseActions: false, isolation: false }).then( + (indexEndpoints) => { + endpointData = indexEndpoints; + endpointHostname = endpointData.data.hosts[0].host.name; + } + ); + }); + + afterEach(() => { + if (endpointData) { + endpointData.cleanup(); + // @ts-expect-error ignore setting to undefined + endpointData = undefined; + } + }); + + it('should get file from response console', () => { + waitForEndpointListPageToBeLoaded(endpointHostname); + openResponseConsoleFromEndpointList(); + inputConsoleCommand(`get-file --path /test/path/test.txt`); + + interceptActionRequests((responseBody) => { + getFileRequestResponse = responseBody; + }, 'get-file'); + submitCommand(); + cy.contains('Retrieving the file from host.').should('exist'); + cy.wait('@get-file').then(() => { + sendActionResponse(getFileRequestResponse); + }); + cy.getByTestSubj('getFileSuccess').within(() => { + cy.contains('File retrieved from the host.'); + cy.contains('(ZIP file passcode: elastic)'); + cy.contains( + 'Files are periodically deleted to clear storage space. Download and save file locally if needed.' + ); + cy.contains('Click here to download').click(); + }); + + const downloadsFolder = Cypress.config('downloadsFolder'); + cy.readFile(`${downloadsFolder}/upload.zip`); + }); + }); +}); diff --git a/x-pack/plugins/security_solution/public/management/cypress/e2e/response_actions/response_console_mocked/isolate.cy.ts b/x-pack/plugins/security_solution/public/management/cypress/e2e/response_actions/response_console_mocked/isolate.cy.ts new file mode 100644 index 0000000000000..0afac2d5dc455 --- /dev/null +++ b/x-pack/plugins/security_solution/public/management/cypress/e2e/response_actions/response_console_mocked/isolate.cy.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 type { ActionDetails } from '../../../../../../common/endpoint/types'; +import type { ReturnTypeFromChainable } from '../../../types'; +import { indexEndpointHosts } from '../../../tasks/index_endpoint_hosts'; +import { + openResponseConsoleFromEndpointList, + performCommandInputChecks, + submitCommand, + waitForEndpointListPageToBeLoaded, +} from '../../../tasks/response_console'; +import { + checkEndpointIsIsolated, + checkEndpointIsNotIsolated, + interceptActionRequests, + sendActionResponse, +} from '../../../tasks/isolate'; +import { login } from '../../../tasks/login'; + +describe('Response console', { tags: ['@ess', '@serverless', '@brokenInServerless'] }, () => { + beforeEach(() => { + login(); + }); + + describe('`isolate` command', () => { + let endpointData: ReturnTypeFromChainable; + let endpointHostname: string; + let isolateRequestResponse: ActionDetails; + + beforeEach(() => { + indexEndpointHosts({ withResponseActions: false, isolation: false }).then( + (indexEndpoints) => { + endpointData = indexEndpoints; + endpointHostname = endpointData.data.hosts[0].host.name; + } + ); + }); + + afterEach(() => { + if (endpointData) { + endpointData.cleanup(); + // @ts-expect-error ignore setting to undefined + endpointData = undefined; + } + }); + + it('should isolate host from response console', () => { + waitForEndpointListPageToBeLoaded(endpointHostname); + checkEndpointIsNotIsolated(endpointHostname); + openResponseConsoleFromEndpointList(); + performCommandInputChecks('isolate'); + interceptActionRequests((responseBody) => { + isolateRequestResponse = responseBody; + }, 'isolate'); + + submitCommand(); + cy.contains('Action pending.').should('exist'); + cy.wait('@isolate').then(() => { + sendActionResponse(isolateRequestResponse); + }); + cy.contains('Action completed.', { timeout: 120000 }).should('exist'); + waitForEndpointListPageToBeLoaded(endpointHostname); + checkEndpointIsIsolated(endpointHostname); + }); + }); +}); diff --git a/x-pack/plugins/security_solution/public/management/cypress/e2e/response_actions/response_console_mocked/kill_process.cy.ts b/x-pack/plugins/security_solution/public/management/cypress/e2e/response_actions/response_console_mocked/kill_process.cy.ts new file mode 100644 index 0000000000000..3c484d2a6fa7d --- /dev/null +++ b/x-pack/plugins/security_solution/public/management/cypress/e2e/response_actions/response_console_mocked/kill_process.cy.ts @@ -0,0 +1,63 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { ActionDetails } from '../../../../../../common/endpoint/types'; +import type { ReturnTypeFromChainable } from '../../../types'; +import { indexEndpointHosts } from '../../../tasks/index_endpoint_hosts'; +import { + inputConsoleCommand, + openResponseConsoleFromEndpointList, + submitCommand, + waitForEndpointListPageToBeLoaded, +} from '../../../tasks/response_console'; +import { interceptActionRequests, sendActionResponse } from '../../../tasks/isolate'; +import { login } from '../../../tasks/login'; + +describe('Response console', { tags: ['@ess', '@serverless', '@brokenInServerless'] }, () => { + beforeEach(() => { + login(); + }); + + describe('`kill-process` command', () => { + let endpointData: ReturnTypeFromChainable; + let endpointHostname: string; + let killProcessRequestResponse: ActionDetails; + + beforeEach(() => { + indexEndpointHosts({ withResponseActions: false, isolation: false }).then( + (indexEndpoints) => { + endpointData = indexEndpoints; + endpointHostname = endpointData.data.hosts[0].host.name; + } + ); + }); + + afterEach(() => { + if (endpointData) { + endpointData.cleanup(); + // @ts-expect-error ignore setting to undefined + endpointData = undefined; + } + }); + + it('should kill process from response console', () => { + waitForEndpointListPageToBeLoaded(endpointHostname); + openResponseConsoleFromEndpointList(); + inputConsoleCommand(`kill-process --pid 1`); + + interceptActionRequests((responseBody) => { + killProcessRequestResponse = responseBody; + }, 'kill-process'); + submitCommand(); + cy.contains('Action pending.').should('exist'); + cy.wait('@kill-process').then(() => { + sendActionResponse(killProcessRequestResponse); + }); + cy.contains('Action completed.', { timeout: 120000 }).should('exist'); + }); + }); +}); diff --git a/x-pack/plugins/security_solution/public/management/cypress/e2e/response_actions/response_console_mocked/processes.cy.ts b/x-pack/plugins/security_solution/public/management/cypress/e2e/response_actions/response_console_mocked/processes.cy.ts new file mode 100644 index 0000000000000..e4226aae4c395 --- /dev/null +++ b/x-pack/plugins/security_solution/public/management/cypress/e2e/response_actions/response_console_mocked/processes.cy.ts @@ -0,0 +1,65 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { ActionDetails } from '../../../../../../common/endpoint/types'; +import type { ReturnTypeFromChainable } from '../../../types'; +import { indexEndpointHosts } from '../../../tasks/index_endpoint_hosts'; +import { + checkReturnedProcessesTable, + openResponseConsoleFromEndpointList, + performCommandInputChecks, + submitCommand, + waitForEndpointListPageToBeLoaded, +} from '../../../tasks/response_console'; +import { interceptActionRequests, sendActionResponse } from '../../../tasks/isolate'; +import { login } from '../../../tasks/login'; + +describe('Response console', { tags: ['@ess', '@serverless', '@brokenInServerless'] }, () => { + beforeEach(() => { + login(); + }); + + describe('`processes` command', () => { + let endpointData: ReturnTypeFromChainable; + let endpointHostname: string; + let processesRequestResponse: ActionDetails; + + beforeEach(() => { + indexEndpointHosts({ withResponseActions: false, isolation: false }).then( + (indexEndpoints) => { + endpointData = indexEndpoints; + endpointHostname = endpointData.data.hosts[0].host.name; + } + ); + }); + + afterEach(() => { + if (endpointData) { + endpointData.cleanup(); + // @ts-expect-error ignore setting to undefined + endpointData = undefined; + } + }); + + it('should return processes from response console', () => { + waitForEndpointListPageToBeLoaded(endpointHostname); + openResponseConsoleFromEndpointList(); + performCommandInputChecks('processes'); + interceptActionRequests((responseBody) => { + processesRequestResponse = responseBody; + }, 'processes'); + submitCommand(); + cy.contains('Action pending.').should('exist'); + cy.wait('@processes').then(() => { + sendActionResponse(processesRequestResponse); + }); + cy.getByTestSubj('getProcessesSuccessCallout', { timeout: 120000 }).within(() => { + checkReturnedProcessesTable(); + }); + }); + }); +}); diff --git a/x-pack/plugins/security_solution/public/management/cypress/e2e/response_actions/response_console_mocked/release.cy.ts b/x-pack/plugins/security_solution/public/management/cypress/e2e/response_actions/response_console_mocked/release.cy.ts new file mode 100644 index 0000000000000..f4c68a4fd0405 --- /dev/null +++ b/x-pack/plugins/security_solution/public/management/cypress/e2e/response_actions/response_console_mocked/release.cy.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 { ActionDetails } from '../../../../../../common/endpoint/types'; +import type { ReturnTypeFromChainable } from '../../../types'; +import { indexEndpointHosts } from '../../../tasks/index_endpoint_hosts'; +import { + openResponseConsoleFromEndpointList, + performCommandInputChecks, + submitCommand, + waitForEndpointListPageToBeLoaded, +} from '../../../tasks/response_console'; +import { + checkEndpointIsIsolated, + checkEndpointIsNotIsolated, + interceptActionRequests, + sendActionResponse, +} from '../../../tasks/isolate'; +import { login } from '../../../tasks/login'; + +describe('Response console', { tags: ['@ess', '@serverless', '@brokenInServerless'] }, () => { + beforeEach(() => { + login(); + }); + + describe('`release` command', () => { + let endpointData: ReturnTypeFromChainable; + let endpointHostname: string; + let releaseRequestResponse: ActionDetails; + + beforeEach(() => { + indexEndpointHosts({ withResponseActions: false, isolation: true }).then((indexEndpoints) => { + endpointData = indexEndpoints; + endpointHostname = endpointData.data.hosts[0].host.name; + }); + }); + + afterEach(() => { + if (endpointData) { + endpointData.cleanup(); + // @ts-expect-error ignore setting to undefined + endpointData = undefined; + } + }); + + it('should release host from response console', () => { + waitForEndpointListPageToBeLoaded(endpointHostname); + checkEndpointIsIsolated(endpointHostname); + openResponseConsoleFromEndpointList(); + performCommandInputChecks('release'); + interceptActionRequests((responseBody) => { + releaseRequestResponse = responseBody; + }, 'release'); + submitCommand(); + cy.contains('Action pending.').should('exist'); + cy.wait('@release').then(() => { + sendActionResponse(releaseRequestResponse); + }); + cy.contains('Action completed.', { timeout: 120000 }).should('exist'); + waitForEndpointListPageToBeLoaded(endpointHostname); + checkEndpointIsNotIsolated(endpointHostname); + }); + }); +}); diff --git a/x-pack/plugins/security_solution/public/management/cypress/e2e/response_actions/response_console_mocked/suspend_process.cy.ts b/x-pack/plugins/security_solution/public/management/cypress/e2e/response_actions/response_console_mocked/suspend_process.cy.ts new file mode 100644 index 0000000000000..b5ef08feb8075 --- /dev/null +++ b/x-pack/plugins/security_solution/public/management/cypress/e2e/response_actions/response_console_mocked/suspend_process.cy.ts @@ -0,0 +1,63 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { ActionDetails } from '../../../../../../common/endpoint/types'; +import type { ReturnTypeFromChainable } from '../../../types'; +import { indexEndpointHosts } from '../../../tasks/index_endpoint_hosts'; +import { + inputConsoleCommand, + openResponseConsoleFromEndpointList, + submitCommand, + waitForEndpointListPageToBeLoaded, +} from '../../../tasks/response_console'; +import { interceptActionRequests, sendActionResponse } from '../../../tasks/isolate'; +import { login } from '../../../tasks/login'; + +describe('Response console', { tags: ['@ess', '@serverless', '@brokenInServerless'] }, () => { + beforeEach(() => { + login(); + }); + + describe('`suspend-process` command', () => { + let endpointData: ReturnTypeFromChainable; + let endpointHostname: string; + let suspendProcessRequestResponse: ActionDetails; + + beforeEach(() => { + indexEndpointHosts({ withResponseActions: false, isolation: false }).then( + (indexEndpoints) => { + endpointData = indexEndpoints; + endpointHostname = endpointData.data.hosts[0].host.name; + } + ); + }); + + afterEach(() => { + if (endpointData) { + endpointData.cleanup(); + // @ts-expect-error ignore setting to undefined + endpointData = undefined; + } + }); + + it('should suspend process from response console', () => { + waitForEndpointListPageToBeLoaded(endpointHostname); + openResponseConsoleFromEndpointList(); + inputConsoleCommand(`suspend-process --pid 1`); + + interceptActionRequests((responseBody) => { + suspendProcessRequestResponse = responseBody; + }, 'suspend-process'); + submitCommand(); + cy.contains('Action pending.').should('exist'); + cy.wait('@suspend-process').then(() => { + sendActionResponse(suspendProcessRequestResponse); + }); + cy.contains('Action completed.', { timeout: 120000 }).should('exist'); + }); + }); +}); diff --git a/x-pack/plugins/security_solution/public/management/cypress/e2e/response_actions/response_console_mocked_data.cy.ts b/x-pack/plugins/security_solution/public/management/cypress/e2e/response_actions/response_console_mocked_data.cy.ts deleted file mode 100644 index 7ae7aa49f2e94..0000000000000 --- a/x-pack/plugins/security_solution/public/management/cypress/e2e/response_actions/response_console_mocked_data.cy.ts +++ /dev/null @@ -1,318 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import type { ActionDetails } from '../../../../../common/endpoint/types'; -import type { ReturnTypeFromChainable } from '../../types'; -import { indexEndpointHosts } from '../../tasks/index_endpoint_hosts'; -import { - checkReturnedProcessesTable, - inputConsoleCommand, - openResponseConsoleFromEndpointList, - performCommandInputChecks, - submitCommand, - waitForEndpointListPageToBeLoaded, -} from '../../tasks/response_console'; -import { - checkEndpointIsIsolated, - checkEndpointIsNotIsolated, - interceptActionRequests, - sendActionResponse, -} from '../../tasks/isolate'; -import { login } from '../../tasks/login'; - -describe('Response console', { tags: ['@ess', '@serverless', '@brokenInServerless'] }, () => { - beforeEach(() => { - login(); - }); - - describe('`isolate` command', () => { - let endpointData: ReturnTypeFromChainable; - let endpointHostname: string; - let isolateRequestResponse: ActionDetails; - - beforeEach(() => { - indexEndpointHosts({ withResponseActions: false, isolation: false }).then( - (indexEndpoints) => { - endpointData = indexEndpoints; - endpointHostname = endpointData.data.hosts[0].host.name; - } - ); - }); - - afterEach(() => { - if (endpointData) { - endpointData.cleanup(); - // @ts-expect-error ignore setting to undefined - endpointData = undefined; - } - }); - - it('should isolate host from response console', () => { - waitForEndpointListPageToBeLoaded(endpointHostname); - checkEndpointIsNotIsolated(endpointHostname); - openResponseConsoleFromEndpointList(); - performCommandInputChecks('isolate'); - interceptActionRequests((responseBody) => { - isolateRequestResponse = responseBody; - }, 'isolate'); - - submitCommand(); - cy.contains('Action pending.').should('exist'); - cy.wait('@isolate').then(() => { - sendActionResponse(isolateRequestResponse); - }); - cy.contains('Action completed.', { timeout: 120000 }).should('exist'); - waitForEndpointListPageToBeLoaded(endpointHostname); - checkEndpointIsIsolated(endpointHostname); - }); - }); - - describe('`release` command', () => { - let endpointData: ReturnTypeFromChainable; - let endpointHostname: string; - let releaseRequestResponse: ActionDetails; - - beforeEach(() => { - indexEndpointHosts({ withResponseActions: false, isolation: true }).then((indexEndpoints) => { - endpointData = indexEndpoints; - endpointHostname = endpointData.data.hosts[0].host.name; - }); - }); - - afterEach(() => { - if (endpointData) { - endpointData.cleanup(); - // @ts-expect-error ignore setting to undefined - endpointData = undefined; - } - }); - - it('should release host from response console', () => { - waitForEndpointListPageToBeLoaded(endpointHostname); - checkEndpointIsIsolated(endpointHostname); - openResponseConsoleFromEndpointList(); - performCommandInputChecks('release'); - interceptActionRequests((responseBody) => { - releaseRequestResponse = responseBody; - }, 'release'); - submitCommand(); - cy.contains('Action pending.').should('exist'); - cy.wait('@release').then(() => { - sendActionResponse(releaseRequestResponse); - }); - cy.contains('Action completed.', { timeout: 120000 }).should('exist'); - waitForEndpointListPageToBeLoaded(endpointHostname); - checkEndpointIsNotIsolated(endpointHostname); - }); - }); - - describe('`processes` command', () => { - let endpointData: ReturnTypeFromChainable; - let endpointHostname: string; - let processesRequestResponse: ActionDetails; - - beforeEach(() => { - indexEndpointHosts({ withResponseActions: false, isolation: false }).then( - (indexEndpoints) => { - endpointData = indexEndpoints; - endpointHostname = endpointData.data.hosts[0].host.name; - } - ); - }); - - afterEach(() => { - if (endpointData) { - endpointData.cleanup(); - // @ts-expect-error ignore setting to undefined - endpointData = undefined; - } - }); - - it('should return processes from response console', () => { - waitForEndpointListPageToBeLoaded(endpointHostname); - openResponseConsoleFromEndpointList(); - performCommandInputChecks('processes'); - interceptActionRequests((responseBody) => { - processesRequestResponse = responseBody; - }, 'processes'); - submitCommand(); - cy.contains('Action pending.').should('exist'); - cy.wait('@processes').then(() => { - sendActionResponse(processesRequestResponse); - }); - cy.getByTestSubj('getProcessesSuccessCallout', { timeout: 120000 }).within(() => { - checkReturnedProcessesTable(); - }); - }); - }); - - describe('`kill-process` command', () => { - let endpointData: ReturnTypeFromChainable; - let endpointHostname: string; - let killProcessRequestResponse: ActionDetails; - - beforeEach(() => { - indexEndpointHosts({ withResponseActions: false, isolation: false }).then( - (indexEndpoints) => { - endpointData = indexEndpoints; - endpointHostname = endpointData.data.hosts[0].host.name; - } - ); - }); - - afterEach(() => { - if (endpointData) { - endpointData.cleanup(); - // @ts-expect-error ignore setting to undefined - endpointData = undefined; - } - }); - - it('should kill process from response console', () => { - waitForEndpointListPageToBeLoaded(endpointHostname); - openResponseConsoleFromEndpointList(); - inputConsoleCommand(`kill-process --pid 1`); - - interceptActionRequests((responseBody) => { - killProcessRequestResponse = responseBody; - }, 'kill-process'); - submitCommand(); - cy.contains('Action pending.').should('exist'); - cy.wait('@kill-process').then(() => { - sendActionResponse(killProcessRequestResponse); - }); - cy.contains('Action completed.', { timeout: 120000 }).should('exist'); - }); - }); - - describe('`suspend-process` command', () => { - let endpointData: ReturnTypeFromChainable; - let endpointHostname: string; - let suspendProcessRequestResponse: ActionDetails; - - beforeEach(() => { - indexEndpointHosts({ withResponseActions: false, isolation: false }).then( - (indexEndpoints) => { - endpointData = indexEndpoints; - endpointHostname = endpointData.data.hosts[0].host.name; - } - ); - }); - - afterEach(() => { - if (endpointData) { - endpointData.cleanup(); - // @ts-expect-error ignore setting to undefined - endpointData = undefined; - } - }); - - it('should suspend process from response console', () => { - waitForEndpointListPageToBeLoaded(endpointHostname); - openResponseConsoleFromEndpointList(); - inputConsoleCommand(`suspend-process --pid 1`); - - interceptActionRequests((responseBody) => { - suspendProcessRequestResponse = responseBody; - }, 'suspend-process'); - submitCommand(); - cy.contains('Action pending.').should('exist'); - cy.wait('@suspend-process').then(() => { - sendActionResponse(suspendProcessRequestResponse); - }); - cy.contains('Action completed.', { timeout: 120000 }).should('exist'); - }); - }); - - describe('`get-file` command', () => { - let endpointData: ReturnTypeFromChainable; - let endpointHostname: string; - let getFileRequestResponse: ActionDetails; - - beforeEach(() => { - indexEndpointHosts({ withResponseActions: false, isolation: false }).then( - (indexEndpoints) => { - endpointData = indexEndpoints; - endpointHostname = endpointData.data.hosts[0].host.name; - } - ); - }); - - afterEach(() => { - if (endpointData) { - endpointData.cleanup(); - // @ts-expect-error ignore setting to undefined - endpointData = undefined; - } - }); - - it('should get file from response console', () => { - waitForEndpointListPageToBeLoaded(endpointHostname); - openResponseConsoleFromEndpointList(); - inputConsoleCommand(`get-file --path /test/path/test.txt`); - - interceptActionRequests((responseBody) => { - getFileRequestResponse = responseBody; - }, 'get-file'); - submitCommand(); - cy.contains('Retrieving the file from host.').should('exist'); - cy.wait('@get-file').then(() => { - sendActionResponse(getFileRequestResponse); - }); - cy.getByTestSubj('getFileSuccess').within(() => { - cy.contains('File retrieved from the host.'); - cy.contains('(ZIP file passcode: elastic)'); - cy.contains( - 'Files are periodically deleted to clear storage space. Download and save file locally if needed.' - ); - cy.contains('Click here to download').click(); - }); - - const downloadsFolder = Cypress.config('downloadsFolder'); - cy.readFile(`${downloadsFolder}/upload.zip`); - }); - }); - - describe('`execute` command', () => { - let endpointData: ReturnTypeFromChainable; - let endpointHostname: string; - let executeRequestResponse: ActionDetails; - - beforeEach(() => { - indexEndpointHosts({ withResponseActions: false, isolation: false }).then( - (indexEndpoints) => { - endpointData = indexEndpoints; - endpointHostname = endpointData.data.hosts[0].host.name; - } - ); - }); - - afterEach(() => { - if (endpointData) { - endpointData.cleanup(); - // @ts-expect-error ignore setting to undefined - endpointData = undefined; - } - }); - - it('should execute a command from response console', () => { - waitForEndpointListPageToBeLoaded(endpointHostname); - openResponseConsoleFromEndpointList(); - inputConsoleCommand(`execute --command "ls -al"`); - - interceptActionRequests((responseBody) => { - executeRequestResponse = responseBody; - }, 'execute'); - submitCommand(); - cy.contains('Action pending.').should('exist'); - cy.wait('@execute').then(() => { - sendActionResponse(executeRequestResponse); - }); - cy.contains('Command execution was successful', { timeout: 120000 }).should('exist'); - }); - }); -}); diff --git a/x-pack/plugins/security_solution/public/management/cypress/e2e/tamper_protection/disabled/unenroll_agent_from_fleet.cy.ts b/x-pack/plugins/security_solution/public/management/cypress/e2e/tamper_protection/disabled/unenroll_agent_from_fleet.cy.ts new file mode 100644 index 0000000000000..e0b26bc2f77dd --- /dev/null +++ b/x-pack/plugins/security_solution/public/management/cypress/e2e/tamper_protection/disabled/unenroll_agent_from_fleet.cy.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 type { PolicyData } from '../../../../../../common/endpoint/types'; +import type { CreateAndEnrollEndpointHostResponse } from '../../../../../../scripts/endpoint/common/endpoint_host_services'; +import { waitForEndpointListPageToBeLoaded } from '../../../tasks/response_console'; +import type { IndexedFleetEndpointPolicyResponse } from '../../../../../../common/endpoint/data_loaders/index_fleet_endpoint_policy'; +import { + getEndpointIntegrationVersion, + createAgentPolicyTask, + unenrollAgent, +} from '../../../tasks/fleet'; + +import { login } from '../../../tasks/login'; +import { enableAllPolicyProtections } from '../../../tasks/endpoint_policy'; +import { createEndpointHost } from '../../../tasks/create_endpoint_host'; +import { deleteAllLoadedEndpointData } from '../../../tasks/delete_all_endpoint_data'; + +describe( + 'Unenroll agent from fleet with agent tamper protection is disabled', + { tags: ['@ess'] }, + () => { + let indexedPolicy: IndexedFleetEndpointPolicyResponse; + let policy: PolicyData; + let createdHost: CreateAndEnrollEndpointHostResponse; + + before(() => { + getEndpointIntegrationVersion().then((version) => { + createAgentPolicyTask(version).then((data) => { + indexedPolicy = data; + policy = indexedPolicy.integrationPolicies[0]; + return enableAllPolicyProtections(policy.id); + }); + }); + }); + + beforeEach(() => { + login(); + // Create and enroll a new Endpoint host + return createEndpointHost(policy.policy_id).then((host) => { + createdHost = host as CreateAndEnrollEndpointHostResponse; + }); + }); + + after(() => { + if (indexedPolicy) { + cy.task('deleteIndexedFleetEndpointPolicies', indexedPolicy); + } + }); + + afterEach(() => { + if (createdHost) { + cy.task('destroyEndpointHost', createdHost); + } + + if (createdHost) { + deleteAllLoadedEndpointData({ endpointAgentIds: [createdHost.agentId] }); + } + }); + + it('should unenroll from fleet without issues', () => { + waitForEndpointListPageToBeLoaded(createdHost.hostname); + unenrollAgent(createdHost.agentId).then((isUnenrolled) => { + expect(isUnenrolled).to.eql(true); + }); + }); + } +); diff --git a/x-pack/plugins/security_solution/public/management/cypress/e2e/tamper_protection/disabled/uninstall_agent_from_host.cy.ts b/x-pack/plugins/security_solution/public/management/cypress/e2e/tamper_protection/disabled/uninstall_agent_from_host.cy.ts new file mode 100644 index 0000000000000..ed47855ac894a --- /dev/null +++ b/x-pack/plugins/security_solution/public/management/cypress/e2e/tamper_protection/disabled/uninstall_agent_from_host.cy.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 type { PolicyData } from '../../../../../../common/endpoint/types'; +import type { CreateAndEnrollEndpointHostResponse } from '../../../../../../scripts/endpoint/common/endpoint_host_services'; +import { waitForEndpointListPageToBeLoaded } from '../../../tasks/response_console'; +import type { IndexedFleetEndpointPolicyResponse } from '../../../../../../common/endpoint/data_loaders/index_fleet_endpoint_policy'; +import { + getEndpointIntegrationVersion, + createAgentPolicyTask, + isAgentAndEndpointUninstalledFromHost, + uninstallAgentFromHost, +} from '../../../tasks/fleet'; + +import { login } from '../../../tasks/login'; +import { enableAllPolicyProtections } from '../../../tasks/endpoint_policy'; +import { createEndpointHost } from '../../../tasks/create_endpoint_host'; +import { deleteAllLoadedEndpointData } from '../../../tasks/delete_all_endpoint_data'; + +describe( + 'Uninstall agent from host when agent tamper protection is disabled', + { tags: ['@ess'] }, + () => { + let indexedPolicy: IndexedFleetEndpointPolicyResponse; + let policy: PolicyData; + let createdHost: CreateAndEnrollEndpointHostResponse; + + before(() => { + getEndpointIntegrationVersion().then((version) => { + createAgentPolicyTask(version).then((data) => { + indexedPolicy = data; + policy = indexedPolicy.integrationPolicies[0]; + return enableAllPolicyProtections(policy.id); + }); + }); + }); + + beforeEach(() => { + login(); + // Create and enroll a new Endpoint host + return createEndpointHost(policy.policy_id).then((host) => { + createdHost = host as CreateAndEnrollEndpointHostResponse; + }); + }); + + after(() => { + if (indexedPolicy) { + cy.task('deleteIndexedFleetEndpointPolicies', indexedPolicy); + } + }); + + afterEach(() => { + if (createdHost) { + cy.task('destroyEndpointHost', createdHost); + } + + if (createdHost) { + deleteAllLoadedEndpointData({ endpointAgentIds: [createdHost.agentId] }); + } + }); + + it('should uninstall from host without issues', () => { + waitForEndpointListPageToBeLoaded(createdHost.hostname); + uninstallAgentFromHost(createdHost.hostname).then((response) => { + expect(response).to.not.match(/(.*)Invalid uninstall token(.*)/); + expect(response).to.match(/(.*)Elastic Agent has been uninstalled(.*)/); + isAgentAndEndpointUninstalledFromHost(createdHost.hostname).then((isUninstalled) => { + expect(isUninstalled).to.eql(true); + }); + }); + }); + } +); diff --git a/x-pack/plugins/security_solution/public/management/cypress/e2e/tamper_protection/enabled/unenroll_agent_from_fleet.cy.ts b/x-pack/plugins/security_solution/public/management/cypress/e2e/tamper_protection/enabled/unenroll_agent_from_fleet.cy.ts new file mode 100644 index 0000000000000..17cb52c2cb042 --- /dev/null +++ b/x-pack/plugins/security_solution/public/management/cypress/e2e/tamper_protection/enabled/unenroll_agent_from_fleet.cy.ts @@ -0,0 +1,76 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { PolicyData } from '../../../../../../common/endpoint/types'; +import type { CreateAndEnrollEndpointHostResponse } from '../../../../../../scripts/endpoint/common/endpoint_host_services'; +import { waitForEndpointListPageToBeLoaded } from '../../../tasks/response_console'; +import type { IndexedFleetEndpointPolicyResponse } from '../../../../../../common/endpoint/data_loaders/index_fleet_endpoint_policy'; +import { + getEndpointIntegrationVersion, + createAgentPolicyTask, + enableAgentTamperProtectionFeatureFlagInPolicy, + unenrollAgent, +} from '../../../tasks/fleet'; + +import { login } from '../../../tasks/login'; +import { createEndpointHost } from '../../../tasks/create_endpoint_host'; +import { deleteAllLoadedEndpointData } from '../../../tasks/delete_all_endpoint_data'; + +describe( + 'Unenroll agent from fleet when agent tamper protection is enabled', + { tags: ['@ess'] }, + () => { + let indexedPolicyWithAgentTamperEnabled: IndexedFleetEndpointPolicyResponse; + let policyWithAgentTamperProtectionEnabled: PolicyData; + let createdHost: CreateAndEnrollEndpointHostResponse; + + before(() => { + getEndpointIntegrationVersion().then((version) => { + createAgentPolicyTask(version).then((dataForProtectedPolicy) => { + indexedPolicyWithAgentTamperEnabled = dataForProtectedPolicy; + policyWithAgentTamperProtectionEnabled = + indexedPolicyWithAgentTamperEnabled.integrationPolicies[0]; + + return enableAgentTamperProtectionFeatureFlagInPolicy( + indexedPolicyWithAgentTamperEnabled.agentPolicies[0].id + ); + }); + }); + }); + + beforeEach(() => { + login(); + // Create and enroll a new Endpoint host + return createEndpointHost(policyWithAgentTamperProtectionEnabled.policy_id).then((host) => { + createdHost = host as CreateAndEnrollEndpointHostResponse; + }); + }); + + after(() => { + if (indexedPolicyWithAgentTamperEnabled) { + cy.task('deleteIndexedFleetEndpointPolicies', indexedPolicyWithAgentTamperEnabled); + } + }); + + afterEach(() => { + if (createdHost) { + cy.task('destroyEndpointHost', createdHost); + } + + if (createdHost) { + deleteAllLoadedEndpointData({ endpointAgentIds: [createdHost.agentId] }); + } + }); + + it('should unenroll from fleet without issues', () => { + waitForEndpointListPageToBeLoaded(createdHost.hostname); + unenrollAgent(createdHost.agentId).then((isUnenrolled) => { + expect(isUnenrolled).to.eql(true); + }); + }); + } +); diff --git a/x-pack/plugins/security_solution/public/management/cypress/e2e/tamper_protection/enabled/uninstall_agent_from_host.cy.ts b/x-pack/plugins/security_solution/public/management/cypress/e2e/tamper_protection/enabled/uninstall_agent_from_host.cy.ts new file mode 100644 index 0000000000000..527566bed608b --- /dev/null +++ b/x-pack/plugins/security_solution/public/management/cypress/e2e/tamper_protection/enabled/uninstall_agent_from_host.cy.ts @@ -0,0 +1,106 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { PolicyData } from '../../../../../../common/endpoint/types'; +import type { CreateAndEnrollEndpointHostResponse } from '../../../../../../scripts/endpoint/common/endpoint_host_services'; +import { waitForEndpointListPageToBeLoaded } from '../../../tasks/response_console'; +import type { IndexedFleetEndpointPolicyResponse } from '../../../../../../common/endpoint/data_loaders/index_fleet_endpoint_policy'; +import { + getEndpointIntegrationVersion, + createAgentPolicyTask, + enableAgentTamperProtectionFeatureFlagInPolicy, + getUninstallToken, + isAgentAndEndpointUninstalledFromHost, + uninstallAgentFromHost, +} from '../../../tasks/fleet'; + +import { login } from '../../../tasks/login'; +import { createEndpointHost } from '../../../tasks/create_endpoint_host'; +import { deleteAllLoadedEndpointData } from '../../../tasks/delete_all_endpoint_data'; + +describe( + 'Uninstall agent from host when agent tamper protection is enabled', + { tags: ['@ess'] }, + () => { + let indexedPolicyWithAgentTamperEnabled: IndexedFleetEndpointPolicyResponse; + let policyWithAgentTamperProtectionEnabled: PolicyData; + let createdHost: CreateAndEnrollEndpointHostResponse; + + before(() => { + getEndpointIntegrationVersion().then((version) => { + createAgentPolicyTask(version).then((dataForProtectedPolicy) => { + indexedPolicyWithAgentTamperEnabled = dataForProtectedPolicy; + policyWithAgentTamperProtectionEnabled = + indexedPolicyWithAgentTamperEnabled.integrationPolicies[0]; + + return enableAgentTamperProtectionFeatureFlagInPolicy( + indexedPolicyWithAgentTamperEnabled.agentPolicies[0].id + ); + }); + }); + }); + + beforeEach(() => { + login(); + // Create and enroll a new Endpoint host + return createEndpointHost(policyWithAgentTamperProtectionEnabled.policy_id).then((host) => { + createdHost = host as CreateAndEnrollEndpointHostResponse; + }); + }); + + after(() => { + if (indexedPolicyWithAgentTamperEnabled) { + cy.task('deleteIndexedFleetEndpointPolicies', indexedPolicyWithAgentTamperEnabled); + } + }); + + afterEach(() => { + if (createdHost) { + cy.task('destroyEndpointHost', createdHost); + } + + if (createdHost) { + deleteAllLoadedEndpointData({ endpointAgentIds: [createdHost.agentId] }); + } + }); + + it('should uninstall from host with the uninstall token', () => { + waitForEndpointListPageToBeLoaded(createdHost.hostname); + uninstallAgentFromHost(createdHost.hostname).then((withoutUninstallTokenResponse) => { + expect(withoutUninstallTokenResponse).to.match(/(.*)Invalid uninstall token(.*)/); + expect(withoutUninstallTokenResponse).to.not.match( + /(.*)Elastic Agent has been uninstalled(.*)/ + ); + isAgentAndEndpointUninstalledFromHost(createdHost.hostname).then( + (isUninstalledWithoutUninstallToken) => { + expect(isUninstalledWithoutUninstallToken).to.eql(false); + getUninstallToken(policyWithAgentTamperProtectionEnabled.policy_id).then( + (uninstallToken) => { + uninstallAgentFromHost(createdHost.hostname, uninstallToken.body.item.token).then( + (withUninstallTokenResponse) => { + expect(withUninstallTokenResponse).to.not.match( + /(.*)Invalid uninstall token(.*)/ + ); + expect(withUninstallTokenResponse).to.match( + /(.*)Elastic Agent has been uninstalled(.*)/ + ); + + isAgentAndEndpointUninstalledFromHost(createdHost.hostname).then( + (isUninstalledWithUninstallToken) => { + expect(isUninstalledWithUninstallToken).to.eql(true); + } + ); + } + ); + } + ); + } + ); + }); + }); + } +); diff --git a/x-pack/plugins/security_solution/public/management/cypress/e2e/tamper_protection/switching_policies/unenroll_agent_from_fleet_changing_policy_from_disabled_to_enabled.cy.ts b/x-pack/plugins/security_solution/public/management/cypress/e2e/tamper_protection/switching_policies/unenroll_agent_from_fleet_changing_policy_from_disabled_to_enabled.cy.ts new file mode 100644 index 0000000000000..d30345d8d5486 --- /dev/null +++ b/x-pack/plugins/security_solution/public/management/cypress/e2e/tamper_protection/switching_policies/unenroll_agent_from_fleet_changing_policy_from_disabled_to_enabled.cy.ts @@ -0,0 +1,94 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { PolicyData } from '../../../../../../common/endpoint/types'; +import type { CreateAndEnrollEndpointHostResponse } from '../../../../../../scripts/endpoint/common/endpoint_host_services'; +import { waitForEndpointListPageToBeLoaded } from '../../../tasks/response_console'; +import type { IndexedFleetEndpointPolicyResponse } from '../../../../../../common/endpoint/data_loaders/index_fleet_endpoint_policy'; +import { + getEndpointIntegrationVersion, + createAgentPolicyTask, + enableAgentTamperProtectionFeatureFlagInPolicy, + unenrollAgent, + changeAgentPolicy, +} from '../../../tasks/fleet'; + +import { login } from '../../../tasks/login'; +import { enableAllPolicyProtections } from '../../../tasks/endpoint_policy'; +import { createEndpointHost } from '../../../tasks/create_endpoint_host'; +import { deleteAllLoadedEndpointData } from '../../../tasks/delete_all_endpoint_data'; + +describe( + 'Unenroll agent from fleet when agent tamper protection is disabled but then is switched to a policy with it enabled', + { tags: ['@ess'] }, + () => { + let indexedPolicy: IndexedFleetEndpointPolicyResponse; + let policy: PolicyData; + let indexedPolicyWithAgentTamperEnabled: IndexedFleetEndpointPolicyResponse; + let policyWithAgentTamperProtectionEnabled: PolicyData; + let createdHost: CreateAndEnrollEndpointHostResponse; + + before(() => { + getEndpointIntegrationVersion().then((version) => { + createAgentPolicyTask(version).then((data) => { + indexedPolicy = data; + policy = indexedPolicy.integrationPolicies[0]; + return enableAllPolicyProtections(policy.id); + }); + createAgentPolicyTask(version).then((dataForProtectedPolicy) => { + indexedPolicyWithAgentTamperEnabled = dataForProtectedPolicy; + policyWithAgentTamperProtectionEnabled = + indexedPolicyWithAgentTamperEnabled.integrationPolicies[0]; + + return enableAgentTamperProtectionFeatureFlagInPolicy( + indexedPolicyWithAgentTamperEnabled.agentPolicies[0].id + ); + }); + }); + }); + + beforeEach(() => { + login(); + // Create and enroll a new Endpoint host + return createEndpointHost(policy.policy_id).then((host) => { + createdHost = host as CreateAndEnrollEndpointHostResponse; + }); + }); + + after(() => { + if (indexedPolicy) { + cy.task('deleteIndexedFleetEndpointPolicies', indexedPolicy); + cy.task('deleteIndexedFleetEndpointPolicies', indexedPolicyWithAgentTamperEnabled); + } + }); + + afterEach(() => { + if (createdHost) { + cy.task('destroyEndpointHost', createdHost); + } + + if (createdHost) { + deleteAllLoadedEndpointData({ endpointAgentIds: [createdHost.agentId] }); + } + }); + + it('should unenroll from fleet without issues', () => { + waitForEndpointListPageToBeLoaded(createdHost.hostname); + // Change agent policy and wait for action to be completed + changeAgentPolicy( + createdHost.agentId, + policyWithAgentTamperProtectionEnabled.policy_id, + 3 + ).then((hasChanged) => { + expect(hasChanged).to.eql(true); + unenrollAgent(createdHost.agentId).then((isUnenrolled) => { + expect(isUnenrolled).to.eql(true); + }); + }); + }); + } +); diff --git a/x-pack/plugins/security_solution/public/management/cypress/e2e/tamper_protection/switching_policies/unenroll_agent_from_fleet_changing_policy_from_enabled_to_disabled.cy.ts b/x-pack/plugins/security_solution/public/management/cypress/e2e/tamper_protection/switching_policies/unenroll_agent_from_fleet_changing_policy_from_enabled_to_disabled.cy.ts new file mode 100644 index 0000000000000..59c70d85118dd --- /dev/null +++ b/x-pack/plugins/security_solution/public/management/cypress/e2e/tamper_protection/switching_policies/unenroll_agent_from_fleet_changing_policy_from_enabled_to_disabled.cy.ts @@ -0,0 +1,90 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { PolicyData } from '../../../../../../common/endpoint/types'; +import type { CreateAndEnrollEndpointHostResponse } from '../../../../../../scripts/endpoint/common/endpoint_host_services'; +import { waitForEndpointListPageToBeLoaded } from '../../../tasks/response_console'; +import type { IndexedFleetEndpointPolicyResponse } from '../../../../../../common/endpoint/data_loaders/index_fleet_endpoint_policy'; +import { + getEndpointIntegrationVersion, + createAgentPolicyTask, + enableAgentTamperProtectionFeatureFlagInPolicy, + unenrollAgent, + changeAgentPolicy, +} from '../../../tasks/fleet'; + +import { login } from '../../../tasks/login'; +import { enableAllPolicyProtections } from '../../../tasks/endpoint_policy'; +import { createEndpointHost } from '../../../tasks/create_endpoint_host'; +import { deleteAllLoadedEndpointData } from '../../../tasks/delete_all_endpoint_data'; + +describe( + 'Unenroll agent from fleet changing when agent tamper protection is enabled but then is switched to a policy with it disabled', + { tags: ['@ess'] }, + () => { + let indexedPolicy: IndexedFleetEndpointPolicyResponse; + let policy: PolicyData; + let indexedPolicyWithAgentTamperEnabled: IndexedFleetEndpointPolicyResponse; + let policyWithAgentTamperProtectionEnabled: PolicyData; + let createdHost: CreateAndEnrollEndpointHostResponse; + + before(() => { + getEndpointIntegrationVersion().then((version) => { + createAgentPolicyTask(version).then((data) => { + indexedPolicy = data; + policy = indexedPolicy.integrationPolicies[0]; + return enableAllPolicyProtections(policy.id); + }); + createAgentPolicyTask(version).then((dataForProtectedPolicy) => { + indexedPolicyWithAgentTamperEnabled = dataForProtectedPolicy; + policyWithAgentTamperProtectionEnabled = + indexedPolicyWithAgentTamperEnabled.integrationPolicies[0]; + + return enableAgentTamperProtectionFeatureFlagInPolicy( + indexedPolicyWithAgentTamperEnabled.agentPolicies[0].id + ); + }); + }); + }); + + beforeEach(() => { + login(); + // Create and enroll a new Endpoint host + return createEndpointHost(policyWithAgentTamperProtectionEnabled.policy_id).then((host) => { + createdHost = host as CreateAndEnrollEndpointHostResponse; + }); + }); + + after(() => { + if (indexedPolicy) { + cy.task('deleteIndexedFleetEndpointPolicies', indexedPolicy); + cy.task('deleteIndexedFleetEndpointPolicies', indexedPolicyWithAgentTamperEnabled); + } + }); + + afterEach(() => { + if (createdHost) { + cy.task('destroyEndpointHost', createdHost); + } + + if (createdHost) { + deleteAllLoadedEndpointData({ endpointAgentIds: [createdHost.agentId] }); + } + }); + + it('should unenroll from fleet without issues', () => { + waitForEndpointListPageToBeLoaded(createdHost.hostname); + // Change agent policy and wait for action to be completed + changeAgentPolicy(createdHost.agentId, policy.policy_id, 3).then((hasChanged) => { + expect(hasChanged).to.eql(true); + unenrollAgent(createdHost.agentId).then((isUnenrolled) => { + expect(isUnenrolled).to.eql(true); + }); + }); + }); + } +); diff --git a/x-pack/plugins/security_solution/public/management/cypress/e2e/tamper_protection/switching_policies/unenroll_agent_from_fleet_changing_policy_from_enabled_to_enabled.cy.ts b/x-pack/plugins/security_solution/public/management/cypress/e2e/tamper_protection/switching_policies/unenroll_agent_from_fleet_changing_policy_from_enabled_to_enabled.cy.ts new file mode 100644 index 0000000000000..3a897bc544ea8 --- /dev/null +++ b/x-pack/plugins/security_solution/public/management/cypress/e2e/tamper_protection/switching_policies/unenroll_agent_from_fleet_changing_policy_from_enabled_to_enabled.cy.ts @@ -0,0 +1,96 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { PolicyData } from '../../../../../../common/endpoint/types'; +import type { CreateAndEnrollEndpointHostResponse } from '../../../../../../scripts/endpoint/common/endpoint_host_services'; +import { waitForEndpointListPageToBeLoaded } from '../../../tasks/response_console'; +import type { IndexedFleetEndpointPolicyResponse } from '../../../../../../common/endpoint/data_loaders/index_fleet_endpoint_policy'; +import { + getEndpointIntegrationVersion, + createAgentPolicyTask, + enableAgentTamperProtectionFeatureFlagInPolicy, + unenrollAgent, + changeAgentPolicy, +} from '../../../tasks/fleet'; + +import { login } from '../../../tasks/login'; +import { createEndpointHost } from '../../../tasks/create_endpoint_host'; +import { deleteAllLoadedEndpointData } from '../../../tasks/delete_all_endpoint_data'; + +describe( + 'Unenroll agent from fleet changing agent policy when agent tamper protection is enabled but then is switched to a policy with it also enabled', + { tags: ['@ess'] }, + () => { + let indexedPolicyWithAgentTamperEnabled: IndexedFleetEndpointPolicyResponse; + let policyWithAgentTamperProtectionEnabled: PolicyData; + let secondIndexedPolicyWithAgentTamperEnabled: IndexedFleetEndpointPolicyResponse; + let secondPolicyWithAgentTamperProtectionEnabled: PolicyData; + let createdHost: CreateAndEnrollEndpointHostResponse; + + before(() => { + getEndpointIntegrationVersion().then((version) => { + createAgentPolicyTask(version).then((dataForProtectedPolicy) => { + indexedPolicyWithAgentTamperEnabled = dataForProtectedPolicy; + policyWithAgentTamperProtectionEnabled = + indexedPolicyWithAgentTamperEnabled.integrationPolicies[0]; + + return enableAgentTamperProtectionFeatureFlagInPolicy( + indexedPolicyWithAgentTamperEnabled.agentPolicies[0].id + ); + }); + createAgentPolicyTask(version).then((dataForProtectedPolicy) => { + secondIndexedPolicyWithAgentTamperEnabled = dataForProtectedPolicy; + secondPolicyWithAgentTamperProtectionEnabled = + secondIndexedPolicyWithAgentTamperEnabled.integrationPolicies[0]; + + return enableAgentTamperProtectionFeatureFlagInPolicy( + secondIndexedPolicyWithAgentTamperEnabled.agentPolicies[0].id + ); + }); + }); + }); + beforeEach(() => { + login(); + // Create and enroll a new Endpoint host + return createEndpointHost(policyWithAgentTamperProtectionEnabled.policy_id).then((host) => { + createdHost = host as CreateAndEnrollEndpointHostResponse; + }); + }); + + after(() => { + if (indexedPolicyWithAgentTamperEnabled) { + cy.task('deleteIndexedFleetEndpointPolicies', indexedPolicyWithAgentTamperEnabled); + cy.task('deleteIndexedFleetEndpointPolicies', secondIndexedPolicyWithAgentTamperEnabled); + } + }); + + afterEach(() => { + if (createdHost) { + cy.task('destroyEndpointHost', createdHost); + } + + if (createdHost) { + deleteAllLoadedEndpointData({ endpointAgentIds: [createdHost.agentId] }); + } + }); + + it('should unenroll from fleet without issues', () => { + waitForEndpointListPageToBeLoaded(createdHost.hostname); + // Change agent policy and wait for action to be completed + changeAgentPolicy( + createdHost.agentId, + secondPolicyWithAgentTamperProtectionEnabled.policy_id, + 3 + ).then((hasChanged) => { + expect(hasChanged).to.eql(true); + unenrollAgent(createdHost.agentId).then((isUnenrolled) => { + expect(isUnenrolled).to.eql(true); + }); + }); + }); + } +); diff --git a/x-pack/plugins/security_solution/public/management/cypress/e2e/tamper_protection/switching_policies/uninstall_agent_from_host_changing_policy_from_disabled_to_enabled.cy.ts b/x-pack/plugins/security_solution/public/management/cypress/e2e/tamper_protection/switching_policies/uninstall_agent_from_host_changing_policy_from_disabled_to_enabled.cy.ts new file mode 100644 index 0000000000000..5950288f2313e --- /dev/null +++ b/x-pack/plugins/security_solution/public/management/cypress/e2e/tamper_protection/switching_policies/uninstall_agent_from_host_changing_policy_from_disabled_to_enabled.cy.ts @@ -0,0 +1,126 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license 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 { PolicyData } from '../../../../../../common/endpoint/types'; +import type { CreateAndEnrollEndpointHostResponse } from '../../../../../../scripts/endpoint/common/endpoint_host_services'; +import { waitForEndpointListPageToBeLoaded } from '../../../tasks/response_console'; +import type { IndexedFleetEndpointPolicyResponse } from '../../../../../../common/endpoint/data_loaders/index_fleet_endpoint_policy'; +import { + getEndpointIntegrationVersion, + createAgentPolicyTask, + enableAgentTamperProtectionFeatureFlagInPolicy, + getUninstallToken, + changeAgentPolicy, + isAgentAndEndpointUninstalledFromHost, + uninstallAgentFromHost, +} from '../../../tasks/fleet'; + +import { login } from '../../../tasks/login'; +import { enableAllPolicyProtections } from '../../../tasks/endpoint_policy'; +import { createEndpointHost } from '../../../tasks/create_endpoint_host'; +import { deleteAllLoadedEndpointData } from '../../../tasks/delete_all_endpoint_data'; + +describe( + 'Uninstall agent from host changing agent policy when agent tamper protection is disabled but then is switched to a policy with it enabled', + { tags: ['@ess'] }, + () => { + let indexedPolicy: IndexedFleetEndpointPolicyResponse; + let policy: PolicyData; + let indexedPolicyWithAgentTamperEnabled: IndexedFleetEndpointPolicyResponse; + let policyWithAgentTamperProtectionEnabled: PolicyData; + let createdHost: CreateAndEnrollEndpointHostResponse; + + before(() => { + getEndpointIntegrationVersion().then((version) => { + createAgentPolicyTask(version).then((data) => { + indexedPolicy = data; + policy = indexedPolicy.integrationPolicies[0]; + return enableAllPolicyProtections(policy.id); + }); + createAgentPolicyTask(version).then((dataForProtectedPolicy) => { + indexedPolicyWithAgentTamperEnabled = dataForProtectedPolicy; + policyWithAgentTamperProtectionEnabled = + indexedPolicyWithAgentTamperEnabled.integrationPolicies[0]; + + return enableAgentTamperProtectionFeatureFlagInPolicy( + indexedPolicyWithAgentTamperEnabled.agentPolicies[0].id + ); + }); + }); + }); + + beforeEach(() => { + login(); + // Create and enroll a new Endpoint host + return createEndpointHost(policy.policy_id).then((host) => { + createdHost = host as CreateAndEnrollEndpointHostResponse; + }); + }); + + after(() => { + if (indexedPolicy) { + cy.task('deleteIndexedFleetEndpointPolicies', indexedPolicy); + cy.task('deleteIndexedFleetEndpointPolicies', indexedPolicyWithAgentTamperEnabled); + } + }); + + afterEach(() => { + if (createdHost) { + cy.task('destroyEndpointHost', createdHost); + } + + if (createdHost) { + deleteAllLoadedEndpointData({ endpointAgentIds: [createdHost.agentId] }); + } + }); + + it('should uninstall from host without issues', () => { + waitForEndpointListPageToBeLoaded(createdHost.hostname); + + // Change agent policy and wait for action to be completed + changeAgentPolicy( + createdHost.agentId, + policyWithAgentTamperProtectionEnabled.policy_id, + 3 + ).then((hasChanged) => { + expect(hasChanged).to.eql(true); + + // Try to uninstall agent from host without the uninstall token + uninstallAgentFromHost(createdHost.hostname).then((responseWithoutToken) => { + expect(responseWithoutToken).to.match(/(.*)Invalid uninstall token(.*)/); + expect(responseWithoutToken).to.not.match(/(.*)Elastic Agent has been uninstalled(.*)/); + isAgentAndEndpointUninstalledFromHost(createdHost.hostname).then( + (isUninstalledWithoutToken) => { + expect(isUninstalledWithoutToken).to.eql(false); + + // Get the uninstall token from that agent policy + getUninstallToken(policyWithAgentTamperProtectionEnabled.policy_id).then( + (uninstallToken) => { + // Try to uninstall agent from host using the retrieved uninstall token + uninstallAgentFromHost(createdHost.hostname, uninstallToken.body.item.token).then( + (responseWithToken) => { + expect(responseWithToken).to.not.match(/(.*)Invalid uninstall token(.*)/); + expect(responseWithToken).to.match( + /(.*)Elastic Agent has been uninstalled(.*)/ + ); + + isAgentAndEndpointUninstalledFromHost(createdHost.hostname).then( + (isUninstalledWithToken) => { + expect(isUninstalledWithToken).to.eql(true); + } + ); + } + ); + } + ); + } + ); + }); + }); + }); + } +); diff --git a/x-pack/plugins/security_solution/public/management/cypress/e2e/tamper_protection/switching_policies/uninstall_agent_from_host_changing_policy_from_enabled_to_disabled.cy.ts b/x-pack/plugins/security_solution/public/management/cypress/e2e/tamper_protection/switching_policies/uninstall_agent_from_host_changing_policy_from_enabled_to_disabled.cy.ts new file mode 100644 index 0000000000000..e55872351aef0 --- /dev/null +++ b/x-pack/plugins/security_solution/public/management/cypress/e2e/tamper_protection/switching_policies/uninstall_agent_from_host_changing_policy_from_enabled_to_disabled.cy.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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { PolicyData } from '../../../../../../common/endpoint/types'; +import type { CreateAndEnrollEndpointHostResponse } from '../../../../../../scripts/endpoint/common/endpoint_host_services'; +import { waitForEndpointListPageToBeLoaded } from '../../../tasks/response_console'; +import type { IndexedFleetEndpointPolicyResponse } from '../../../../../../common/endpoint/data_loaders/index_fleet_endpoint_policy'; +import { + getEndpointIntegrationVersion, + createAgentPolicyTask, + enableAgentTamperProtectionFeatureFlagInPolicy, + changeAgentPolicy, + isAgentAndEndpointUninstalledFromHost, + uninstallAgentFromHost, +} from '../../../tasks/fleet'; + +import { login } from '../../../tasks/login'; +import { enableAllPolicyProtections } from '../../../tasks/endpoint_policy'; +import { createEndpointHost } from '../../../tasks/create_endpoint_host'; +import { deleteAllLoadedEndpointData } from '../../../tasks/delete_all_endpoint_data'; + +describe( + 'Uninstall agent from host changing agent policy when agent tamper protection is enabled but then is switched to a policy with it disabled', + { tags: ['@ess'] }, + () => { + let indexedPolicy: IndexedFleetEndpointPolicyResponse; + let policy: PolicyData; + let indexedPolicyWithAgentTamperEnabled: IndexedFleetEndpointPolicyResponse; + let policyWithAgentTamperProtectionEnabled: PolicyData; + let createdHost: CreateAndEnrollEndpointHostResponse; + + before(() => { + getEndpointIntegrationVersion().then((version) => { + createAgentPolicyTask(version).then((data) => { + indexedPolicy = data; + policy = indexedPolicy.integrationPolicies[0]; + return enableAllPolicyProtections(policy.id); + }); + createAgentPolicyTask(version).then((dataForProtectedPolicy) => { + indexedPolicyWithAgentTamperEnabled = dataForProtectedPolicy; + policyWithAgentTamperProtectionEnabled = + indexedPolicyWithAgentTamperEnabled.integrationPolicies[0]; + + return enableAgentTamperProtectionFeatureFlagInPolicy( + indexedPolicyWithAgentTamperEnabled.agentPolicies[0].id + ); + }); + }); + }); + + beforeEach(() => { + login(); + // Create and enroll a new Endpoint host + return createEndpointHost(policyWithAgentTamperProtectionEnabled.policy_id).then((host) => { + createdHost = host as CreateAndEnrollEndpointHostResponse; + }); + }); + + after(() => { + if (indexedPolicy) { + cy.task('deleteIndexedFleetEndpointPolicies', indexedPolicy); + cy.task('deleteIndexedFleetEndpointPolicies', indexedPolicyWithAgentTamperEnabled); + } + }); + + afterEach(() => { + if (createdHost) { + cy.task('destroyEndpointHost', createdHost); + } + + if (createdHost) { + deleteAllLoadedEndpointData({ endpointAgentIds: [createdHost.agentId] }); + } + }); + + it('should uninstall from host without issues', () => { + waitForEndpointListPageToBeLoaded(createdHost.hostname); + + changeAgentPolicy(createdHost.agentId, policy.policy_id, 3).then((hasChanged) => { + expect(hasChanged).to.eql(true); + uninstallAgentFromHost(createdHost.hostname).then((responseWithoutToken) => { + expect(responseWithoutToken).to.not.match(/(.*)Invalid uninstall token(.*)/); + expect(responseWithoutToken).to.match(/(.*)Elastic Agent has been uninstalled(.*)/); + isAgentAndEndpointUninstalledFromHost(createdHost.hostname).then( + (isUninstalledWithoutToken) => { + expect(isUninstalledWithoutToken).to.eql(true); + } + ); + }); + }); + }); + } +); diff --git a/x-pack/plugins/security_solution/public/management/cypress/e2e/tamper_protection/switching_policies/uninstall_agent_from_host_changing_policy_from_enabled_to_enabled.cy.ts b/x-pack/plugins/security_solution/public/management/cypress/e2e/tamper_protection/switching_policies/uninstall_agent_from_host_changing_policy_from_enabled_to_enabled.cy.ts new file mode 100644 index 0000000000000..15fd02ad14511 --- /dev/null +++ b/x-pack/plugins/security_solution/public/management/cypress/e2e/tamper_protection/switching_policies/uninstall_agent_from_host_changing_policy_from_enabled_to_enabled.cy.ts @@ -0,0 +1,142 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { PolicyData } from '../../../../../../common/endpoint/types'; +import type { CreateAndEnrollEndpointHostResponse } from '../../../../../../scripts/endpoint/common/endpoint_host_services'; +import { waitForEndpointListPageToBeLoaded } from '../../../tasks/response_console'; +import type { IndexedFleetEndpointPolicyResponse } from '../../../../../../common/endpoint/data_loaders/index_fleet_endpoint_policy'; +import { + getEndpointIntegrationVersion, + createAgentPolicyTask, + enableAgentTamperProtectionFeatureFlagInPolicy, + getUninstallToken, + changeAgentPolicy, + isAgentAndEndpointUninstalledFromHost, + uninstallAgentFromHost, +} from '../../../tasks/fleet'; + +import { login } from '../../../tasks/login'; +import { createEndpointHost } from '../../../tasks/create_endpoint_host'; +import { deleteAllLoadedEndpointData } from '../../../tasks/delete_all_endpoint_data'; + +describe( + 'Uninstall agent from host changing agent policy when agent tamper protection is enabled but then is switched to a policy with it also enabled', + { tags: ['@ess'] }, + () => { + let indexedPolicyWithAgentTamperEnabled: IndexedFleetEndpointPolicyResponse; + let policyWithAgentTamperProtectionEnabled: PolicyData; + let secondIndexedPolicyWithAgentTamperEnabled: IndexedFleetEndpointPolicyResponse; + let secondPolicyWithAgentTamperProtectionEnabled: PolicyData; + let createdHost: CreateAndEnrollEndpointHostResponse; + + before(() => { + getEndpointIntegrationVersion().then((version) => { + createAgentPolicyTask(version).then((dataForProtectedPolicy) => { + indexedPolicyWithAgentTamperEnabled = dataForProtectedPolicy; + policyWithAgentTamperProtectionEnabled = + indexedPolicyWithAgentTamperEnabled.integrationPolicies[0]; + + return enableAgentTamperProtectionFeatureFlagInPolicy( + indexedPolicyWithAgentTamperEnabled.agentPolicies[0].id + ); + }); + createAgentPolicyTask(version).then((dataForProtectedPolicy) => { + secondIndexedPolicyWithAgentTamperEnabled = dataForProtectedPolicy; + secondPolicyWithAgentTamperProtectionEnabled = + secondIndexedPolicyWithAgentTamperEnabled.integrationPolicies[0]; + + return enableAgentTamperProtectionFeatureFlagInPolicy( + secondIndexedPolicyWithAgentTamperEnabled.agentPolicies[0].id + ); + }); + }); + }); + + beforeEach(() => { + login(); + // Create and enroll a new Endpoint host + return createEndpointHost(policyWithAgentTamperProtectionEnabled.policy_id).then((host) => { + createdHost = host as CreateAndEnrollEndpointHostResponse; + }); + }); + + after(() => { + if (indexedPolicyWithAgentTamperEnabled) { + cy.task('deleteIndexedFleetEndpointPolicies', indexedPolicyWithAgentTamperEnabled); + cy.task('deleteIndexedFleetEndpointPolicies', secondIndexedPolicyWithAgentTamperEnabled); + } + }); + + afterEach(() => { + if (createdHost) { + cy.task('destroyEndpointHost', createdHost); + } + + if (createdHost) { + deleteAllLoadedEndpointData({ endpointAgentIds: [createdHost.agentId] }); + } + }); + + it('should uninstall from host without issues', () => { + waitForEndpointListPageToBeLoaded(createdHost.hostname); + + // Change agent policy and wait for action to be completed + changeAgentPolicy( + createdHost.agentId, + secondPolicyWithAgentTamperProtectionEnabled.policy_id, + 3 + ).then((hasChanged) => { + expect(hasChanged).to.eql(true); + + // Get the uninstall token from old agent policy + getUninstallToken(policyWithAgentTamperProtectionEnabled.policy_id).then( + (oldUninstallToken) => { + // Try to uninstall agent from host using old retrieved uninstall token + uninstallAgentFromHost(createdHost.hostname, oldUninstallToken.body.item.token).then( + (responseWithOldToken) => { + expect(responseWithOldToken).to.match(/(.*)Invalid uninstall token(.*)/); + expect(responseWithOldToken).to.not.match( + /(.*)Elastic Agent has been uninstalled(.*)/ + ); + + isAgentAndEndpointUninstalledFromHost(createdHost.hostname).then( + (isUninstalledWithOldToken) => { + expect(isUninstalledWithOldToken).to.eql(false); + + // Get the uninstall token from new agent policy + getUninstallToken(secondPolicyWithAgentTamperProtectionEnabled.policy_id).then( + (newUninstallToken) => { + // Try to uninstall agent from host using new retrieved uninstall token + uninstallAgentFromHost( + createdHost.hostname, + newUninstallToken.body.item.token + ).then((responseWithNewToken) => { + expect(responseWithNewToken).to.not.match( + /(.*)Invalid uninstall token(.*)/ + ); + expect(responseWithNewToken).to.match( + /(.*)Elastic Agent has been uninstalled(.*)/ + ); + + isAgentAndEndpointUninstalledFromHost(createdHost.hostname).then( + (isUninstalledWithNewToken) => { + expect(isUninstalledWithNewToken).to.eql(true); + } + ); + }); + } + ); + } + ); + } + ); + } + ); + }); + }); + } +); diff --git a/x-pack/plugins/security_solution/public/management/cypress/e2e/tamper_protection/unenroll_agent_from_fleet.cy.ts b/x-pack/plugins/security_solution/public/management/cypress/e2e/tamper_protection/unenroll_agent_from_fleet.cy.ts deleted file mode 100644 index cdcef05822594..0000000000000 --- a/x-pack/plugins/security_solution/public/management/cypress/e2e/tamper_protection/unenroll_agent_from_fleet.cy.ts +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import type { PolicyData } from '../../../../../common/endpoint/types'; -import type { CreateAndEnrollEndpointHostResponse } from '../../../../../scripts/endpoint/common/endpoint_host_services'; -import { waitForEndpointListPageToBeLoaded } from '../../tasks/response_console'; -import type { IndexedFleetEndpointPolicyResponse } from '../../../../../common/endpoint/data_loaders/index_fleet_endpoint_policy'; -import { - getEndpointIntegrationVersion, - createAgentPolicyTask, - enableAgentTamperProtectionFeatureFlagInPolicy, - unenrollAgent, -} from '../../tasks/fleet'; - -import { login } from '../../tasks/login'; -import { enableAllPolicyProtections } from '../../tasks/endpoint_policy'; -import { createEndpointHost } from '../../tasks/create_endpoint_host'; -import { deleteAllLoadedEndpointData } from '../../tasks/delete_all_endpoint_data'; - -describe('Unenroll agent from fleet', { tags: ['@ess'] }, () => { - let indexedPolicy: IndexedFleetEndpointPolicyResponse; - let policy: PolicyData; - let indexedPolicyWithAgentTamperEnabled: IndexedFleetEndpointPolicyResponse; - let policyWithAgentTamperProtectionEnabled: PolicyData; - - before(() => { - getEndpointIntegrationVersion().then((version) => { - createAgentPolicyTask(version).then((data) => { - indexedPolicy = data; - policy = indexedPolicy.integrationPolicies[0]; - return enableAllPolicyProtections(policy.id); - }); - createAgentPolicyTask(version).then((dataForProtectedPolicy) => { - indexedPolicyWithAgentTamperEnabled = dataForProtectedPolicy; - policyWithAgentTamperProtectionEnabled = - indexedPolicyWithAgentTamperEnabled.integrationPolicies[0]; - - return enableAgentTamperProtectionFeatureFlagInPolicy( - indexedPolicyWithAgentTamperEnabled.agentPolicies[0].id - ); - }); - }); - }); - beforeEach(() => { - login(); - }); - - after(() => { - if (indexedPolicy) { - cy.task('deleteIndexedFleetEndpointPolicies', indexedPolicy); - cy.task('deleteIndexedFleetEndpointPolicies', indexedPolicyWithAgentTamperEnabled); - } - }); - - describe('When agent tamper protection is disabled', () => { - let createdHost: CreateAndEnrollEndpointHostResponse; - - beforeEach(() => { - // Create and enroll a new Endpoint host - return createEndpointHost(policy.policy_id).then((host) => { - createdHost = host as CreateAndEnrollEndpointHostResponse; - }); - }); - - afterEach(() => { - if (createdHost) { - cy.task('destroyEndpointHost', createdHost); - } - - if (createdHost) { - deleteAllLoadedEndpointData({ endpointAgentIds: [createdHost.agentId] }); - } - }); - - it('should unenroll from fleet without issues', () => { - waitForEndpointListPageToBeLoaded(createdHost.hostname); - unenrollAgent(createdHost.agentId).then((isUnenrolled) => { - expect(isUnenrolled).to.eql(true); - }); - }); - }); - - describe('When agent tamper protection is enabled', () => { - let createdHost: CreateAndEnrollEndpointHostResponse; - - beforeEach(() => { - // Create and enroll a new Endpoint host - return createEndpointHost(policyWithAgentTamperProtectionEnabled.policy_id).then((host) => { - createdHost = host as CreateAndEnrollEndpointHostResponse; - }); - }); - - afterEach(() => { - if (createdHost) { - cy.task('destroyEndpointHost', createdHost); - } - - if (createdHost) { - deleteAllLoadedEndpointData({ endpointAgentIds: [createdHost.agentId] }); - } - }); - - it('should unenroll from fleet without issues', () => { - waitForEndpointListPageToBeLoaded(createdHost.hostname); - unenrollAgent(createdHost.agentId).then((isUnenrolled) => { - expect(isUnenrolled).to.eql(true); - }); - }); - }); -}); diff --git a/x-pack/plugins/security_solution/public/management/cypress/e2e/tamper_protection/unenroll_agent_from_fleet_changing_policy.cy.ts b/x-pack/plugins/security_solution/public/management/cypress/e2e/tamper_protection/unenroll_agent_from_fleet_changing_policy.cy.ts deleted file mode 100644 index e4157f7b7eea7..0000000000000 --- a/x-pack/plugins/security_solution/public/management/cypress/e2e/tamper_protection/unenroll_agent_from_fleet_changing_policy.cy.ts +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import type { PolicyData } from '../../../../../common/endpoint/types'; -import type { CreateAndEnrollEndpointHostResponse } from '../../../../../scripts/endpoint/common/endpoint_host_services'; -import { waitForEndpointListPageToBeLoaded } from '../../tasks/response_console'; -import type { IndexedFleetEndpointPolicyResponse } from '../../../../../common/endpoint/data_loaders/index_fleet_endpoint_policy'; -import { - getEndpointIntegrationVersion, - createAgentPolicyTask, - enableAgentTamperProtectionFeatureFlagInPolicy, - unenrollAgent, - changeAgentPolicy, -} from '../../tasks/fleet'; - -import { login } from '../../tasks/login'; -import { enableAllPolicyProtections } from '../../tasks/endpoint_policy'; -import { createEndpointHost } from '../../tasks/create_endpoint_host'; -import { deleteAllLoadedEndpointData } from '../../tasks/delete_all_endpoint_data'; - -describe('Unenroll agent from fleet changing agent policy', { tags: ['@ess'] }, () => { - let indexedPolicy: IndexedFleetEndpointPolicyResponse; - let policy: PolicyData; - let indexedPolicyWithAgentTamperEnabled: IndexedFleetEndpointPolicyResponse; - let policyWithAgentTamperProtectionEnabled: PolicyData; - let secondIndexedPolicyWithAgentTamperEnabled: IndexedFleetEndpointPolicyResponse; - let secondPolicyWithAgentTamperProtectionEnabled: PolicyData; - - before(() => { - getEndpointIntegrationVersion().then((version) => { - createAgentPolicyTask(version).then((data) => { - indexedPolicy = data; - policy = indexedPolicy.integrationPolicies[0]; - return enableAllPolicyProtections(policy.id); - }); - createAgentPolicyTask(version).then((dataForProtectedPolicy) => { - indexedPolicyWithAgentTamperEnabled = dataForProtectedPolicy; - policyWithAgentTamperProtectionEnabled = - indexedPolicyWithAgentTamperEnabled.integrationPolicies[0]; - - return enableAgentTamperProtectionFeatureFlagInPolicy( - indexedPolicyWithAgentTamperEnabled.agentPolicies[0].id - ); - }); - createAgentPolicyTask(version).then((dataForProtectedPolicy) => { - secondIndexedPolicyWithAgentTamperEnabled = dataForProtectedPolicy; - secondPolicyWithAgentTamperProtectionEnabled = - secondIndexedPolicyWithAgentTamperEnabled.integrationPolicies[0]; - - return enableAgentTamperProtectionFeatureFlagInPolicy( - secondIndexedPolicyWithAgentTamperEnabled.agentPolicies[0].id - ); - }); - }); - }); - beforeEach(() => { - login(); - }); - - after(() => { - if (indexedPolicy) { - cy.task('deleteIndexedFleetEndpointPolicies', indexedPolicy); - cy.task('deleteIndexedFleetEndpointPolicies', indexedPolicyWithAgentTamperEnabled); - cy.task('deleteIndexedFleetEndpointPolicies', secondIndexedPolicyWithAgentTamperEnabled); - } - }); - - describe('When agent tamper protection is disabled but then is switched to a policy with it enabled', () => { - let createdHost: CreateAndEnrollEndpointHostResponse; - - beforeEach(() => { - // Create and enroll a new Endpoint host - return createEndpointHost(policy.policy_id).then((host) => { - createdHost = host as CreateAndEnrollEndpointHostResponse; - }); - }); - - afterEach(() => { - if (createdHost) { - cy.task('destroyEndpointHost', createdHost); - } - - if (createdHost) { - deleteAllLoadedEndpointData({ endpointAgentIds: [createdHost.agentId] }); - } - }); - - it('should unenroll from fleet without issues', () => { - waitForEndpointListPageToBeLoaded(createdHost.hostname); - // Change agent policy and wait for action to be completed - changeAgentPolicy( - createdHost.agentId, - policyWithAgentTamperProtectionEnabled.policy_id, - 3 - ).then((hasChanged) => { - expect(hasChanged).to.eql(true); - unenrollAgent(createdHost.agentId).then((isUnenrolled) => { - expect(isUnenrolled).to.eql(true); - }); - }); - }); - }); - - describe('When agent tamper protection is enabled but then is switched to a policy with it disabled', () => { - let createdHost: CreateAndEnrollEndpointHostResponse; - - beforeEach(() => { - // Create and enroll a new Endpoint host - return createEndpointHost(policyWithAgentTamperProtectionEnabled.policy_id).then((host) => { - createdHost = host as CreateAndEnrollEndpointHostResponse; - }); - }); - - afterEach(() => { - if (createdHost) { - cy.task('destroyEndpointHost', createdHost); - } - - if (createdHost) { - deleteAllLoadedEndpointData({ endpointAgentIds: [createdHost.agentId] }); - } - }); - - it('should unenroll from fleet without issues', () => { - waitForEndpointListPageToBeLoaded(createdHost.hostname); - // Change agent policy and wait for action to be completed - changeAgentPolicy(createdHost.agentId, policy.policy_id, 3).then((hasChanged) => { - expect(hasChanged).to.eql(true); - unenrollAgent(createdHost.agentId).then((isUnenrolled) => { - expect(isUnenrolled).to.eql(true); - }); - }); - }); - }); - - describe('When agent tamper protection is enabled but then is switched to a policy with it also enabled', () => { - let createdHost: CreateAndEnrollEndpointHostResponse; - - beforeEach(() => { - // Create and enroll a new Endpoint host - return createEndpointHost(policyWithAgentTamperProtectionEnabled.policy_id).then((host) => { - createdHost = host as CreateAndEnrollEndpointHostResponse; - }); - }); - - afterEach(() => { - if (createdHost) { - cy.task('destroyEndpointHost', createdHost); - } - - if (createdHost) { - deleteAllLoadedEndpointData({ endpointAgentIds: [createdHost.agentId] }); - } - }); - - it('should unenroll from fleet without issues', () => { - waitForEndpointListPageToBeLoaded(createdHost.hostname); - // Change agent policy and wait for action to be completed - changeAgentPolicy( - createdHost.agentId, - secondPolicyWithAgentTamperProtectionEnabled.policy_id, - 3 - ).then((hasChanged) => { - expect(hasChanged).to.eql(true); - unenrollAgent(createdHost.agentId).then((isUnenrolled) => { - expect(isUnenrolled).to.eql(true); - }); - }); - }); - }); -}); diff --git a/x-pack/plugins/security_solution/public/management/cypress/e2e/tamper_protection/uninstall_agent_from_host.cy.ts b/x-pack/plugins/security_solution/public/management/cypress/e2e/tamper_protection/uninstall_agent_from_host.cy.ts deleted file mode 100644 index 778cc510e2a37..0000000000000 --- a/x-pack/plugins/security_solution/public/management/cypress/e2e/tamper_protection/uninstall_agent_from_host.cy.ts +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import type { PolicyData } from '../../../../../common/endpoint/types'; -import type { CreateAndEnrollEndpointHostResponse } from '../../../../../scripts/endpoint/common/endpoint_host_services'; -import { waitForEndpointListPageToBeLoaded } from '../../tasks/response_console'; -import type { IndexedFleetEndpointPolicyResponse } from '../../../../../common/endpoint/data_loaders/index_fleet_endpoint_policy'; -import { - getEndpointIntegrationVersion, - createAgentPolicyTask, - enableAgentTamperProtectionFeatureFlagInPolicy, - getUninstallToken, - isAgentAndEndpointUninstalledFromHost, - uninstallAgentFromHost, -} from '../../tasks/fleet'; - -import { login } from '../../tasks/login'; -import { enableAllPolicyProtections } from '../../tasks/endpoint_policy'; -import { createEndpointHost } from '../../tasks/create_endpoint_host'; -import { deleteAllLoadedEndpointData } from '../../tasks/delete_all_endpoint_data'; - -describe('Uninstall agent from host', { tags: ['@ess'] }, () => { - let indexedPolicy: IndexedFleetEndpointPolicyResponse; - let policy: PolicyData; - let indexedPolicyWithAgentTamperEnabled: IndexedFleetEndpointPolicyResponse; - let policyWithAgentTamperProtectionEnabled: PolicyData; - - before(() => { - getEndpointIntegrationVersion().then((version) => { - createAgentPolicyTask(version).then((data) => { - indexedPolicy = data; - policy = indexedPolicy.integrationPolicies[0]; - return enableAllPolicyProtections(policy.id); - }); - createAgentPolicyTask(version).then((dataForProtectedPolicy) => { - indexedPolicyWithAgentTamperEnabled = dataForProtectedPolicy; - policyWithAgentTamperProtectionEnabled = - indexedPolicyWithAgentTamperEnabled.integrationPolicies[0]; - - return enableAgentTamperProtectionFeatureFlagInPolicy( - indexedPolicyWithAgentTamperEnabled.agentPolicies[0].id - ); - }); - }); - }); - beforeEach(() => { - login(); - }); - - after(() => { - if (indexedPolicy) { - cy.task('deleteIndexedFleetEndpointPolicies', indexedPolicy); - cy.task('deleteIndexedFleetEndpointPolicies', indexedPolicyWithAgentTamperEnabled); - } - }); - - describe('When agent tamper protection is disabled', () => { - let createdHost: CreateAndEnrollEndpointHostResponse; - - beforeEach(() => { - // Create and enroll a new Endpoint host - return createEndpointHost(policy.policy_id).then((host) => { - createdHost = host as CreateAndEnrollEndpointHostResponse; - }); - }); - - afterEach(() => { - if (createdHost) { - cy.task('destroyEndpointHost', createdHost); - } - - if (createdHost) { - deleteAllLoadedEndpointData({ endpointAgentIds: [createdHost.agentId] }); - } - }); - - it('should uninstall from host without issues', () => { - waitForEndpointListPageToBeLoaded(createdHost.hostname); - uninstallAgentFromHost(createdHost.hostname).then((response) => { - expect(response).to.not.match(/(.*)Invalid uninstall token(.*)/); - expect(response).to.match(/(.*)Elastic Agent has been uninstalled(.*)/); - isAgentAndEndpointUninstalledFromHost(createdHost.hostname).then((isUninstalled) => { - expect(isUninstalled).to.eql(true); - }); - }); - }); - }); - - describe('When agent tamper protection is enabled', () => { - let createdHost: CreateAndEnrollEndpointHostResponse; - - beforeEach(() => { - // Create and enroll a new Endpoint host - return createEndpointHost(policyWithAgentTamperProtectionEnabled.policy_id).then((host) => { - createdHost = host as CreateAndEnrollEndpointHostResponse; - }); - }); - - afterEach(() => { - if (createdHost) { - cy.task('destroyEndpointHost', createdHost); - } - - if (createdHost) { - deleteAllLoadedEndpointData({ endpointAgentIds: [createdHost.agentId] }); - } - }); - - it('should not uninstall from host without the uninstall token', () => { - waitForEndpointListPageToBeLoaded(createdHost.hostname); - uninstallAgentFromHost(createdHost.hostname).then((response) => { - expect(response).to.match(/(.*)Invalid uninstall token(.*)/); - expect(response).to.not.match(/(.*)Elastic Agent has been uninstalled(.*)/); - isAgentAndEndpointUninstalledFromHost(createdHost.hostname).then((isUninstalled) => { - expect(isUninstalled).to.eql(false); - }); - }); - }); - - it('should uninstall from host with the uninstall token', () => { - waitForEndpointListPageToBeLoaded(createdHost.hostname); - getUninstallToken(policyWithAgentTamperProtectionEnabled.policy_id).then((uninstallToken) => { - uninstallAgentFromHost(createdHost.hostname, uninstallToken.body.item.token).then( - (response) => { - expect(response).to.not.match(/(.*)Invalid uninstall token(.*)/); - expect(response).to.match(/(.*)Elastic Agent has been uninstalled(.*)/); - - isAgentAndEndpointUninstalledFromHost(createdHost.hostname).then((isUninstalled) => { - expect(isUninstalled).to.eql(true); - }); - } - ); - }); - }); - }); -}); diff --git a/x-pack/plugins/security_solution/public/management/cypress/e2e/tamper_protection/uninstall_agent_from_host_changing_policy.cy.ts b/x-pack/plugins/security_solution/public/management/cypress/e2e/tamper_protection/uninstall_agent_from_host_changing_policy.cy.ts deleted file mode 100644 index 84a15051bd3c9..0000000000000 --- a/x-pack/plugins/security_solution/public/management/cypress/e2e/tamper_protection/uninstall_agent_from_host_changing_policy.cy.ts +++ /dev/null @@ -1,256 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import type { PolicyData } from '../../../../../common/endpoint/types'; -import type { CreateAndEnrollEndpointHostResponse } from '../../../../../scripts/endpoint/common/endpoint_host_services'; -import { waitForEndpointListPageToBeLoaded } from '../../tasks/response_console'; -import type { IndexedFleetEndpointPolicyResponse } from '../../../../../common/endpoint/data_loaders/index_fleet_endpoint_policy'; -import { - getEndpointIntegrationVersion, - createAgentPolicyTask, - enableAgentTamperProtectionFeatureFlagInPolicy, - getUninstallToken, - changeAgentPolicy, - isAgentAndEndpointUninstalledFromHost, - uninstallAgentFromHost, -} from '../../tasks/fleet'; - -import { login } from '../../tasks/login'; -import { enableAllPolicyProtections } from '../../tasks/endpoint_policy'; -import { createEndpointHost } from '../../tasks/create_endpoint_host'; -import { deleteAllLoadedEndpointData } from '../../tasks/delete_all_endpoint_data'; - -describe('Uninstall agent from host changing agent policy', { tags: ['@ess'] }, () => { - let indexedPolicy: IndexedFleetEndpointPolicyResponse; - let policy: PolicyData; - let indexedPolicyWithAgentTamperEnabled: IndexedFleetEndpointPolicyResponse; - let policyWithAgentTamperProtectionEnabled: PolicyData; - let secondIndexedPolicyWithAgentTamperEnabled: IndexedFleetEndpointPolicyResponse; - let secondPolicyWithAgentTamperProtectionEnabled: PolicyData; - - before(() => { - getEndpointIntegrationVersion().then((version) => { - createAgentPolicyTask(version).then((data) => { - indexedPolicy = data; - policy = indexedPolicy.integrationPolicies[0]; - return enableAllPolicyProtections(policy.id); - }); - createAgentPolicyTask(version).then((dataForProtectedPolicy) => { - indexedPolicyWithAgentTamperEnabled = dataForProtectedPolicy; - policyWithAgentTamperProtectionEnabled = - indexedPolicyWithAgentTamperEnabled.integrationPolicies[0]; - - return enableAgentTamperProtectionFeatureFlagInPolicy( - indexedPolicyWithAgentTamperEnabled.agentPolicies[0].id - ); - }); - createAgentPolicyTask(version).then((dataForProtectedPolicy) => { - secondIndexedPolicyWithAgentTamperEnabled = dataForProtectedPolicy; - secondPolicyWithAgentTamperProtectionEnabled = - secondIndexedPolicyWithAgentTamperEnabled.integrationPolicies[0]; - - return enableAgentTamperProtectionFeatureFlagInPolicy( - secondIndexedPolicyWithAgentTamperEnabled.agentPolicies[0].id - ); - }); - }); - }); - beforeEach(() => { - login(); - }); - - after(() => { - if (indexedPolicy) { - cy.task('deleteIndexedFleetEndpointPolicies', indexedPolicy); - cy.task('deleteIndexedFleetEndpointPolicies', indexedPolicyWithAgentTamperEnabled); - cy.task('deleteIndexedFleetEndpointPolicies', secondIndexedPolicyWithAgentTamperEnabled); - } - }); - - describe('When agent tamper protection is disabled but then is switched to a policy with it enabled', () => { - let createdHost: CreateAndEnrollEndpointHostResponse; - - beforeEach(() => { - // Create and enroll a new Endpoint host - return createEndpointHost(policy.policy_id).then((host) => { - createdHost = host as CreateAndEnrollEndpointHostResponse; - }); - }); - - afterEach(() => { - if (createdHost) { - cy.task('destroyEndpointHost', createdHost); - } - - if (createdHost) { - deleteAllLoadedEndpointData({ endpointAgentIds: [createdHost.agentId] }); - } - }); - - it('should uninstall from host without issues', () => { - waitForEndpointListPageToBeLoaded(createdHost.hostname); - - // Change agent policy and wait for action to be completed - changeAgentPolicy( - createdHost.agentId, - policyWithAgentTamperProtectionEnabled.policy_id, - 3 - ).then((hasChanged) => { - expect(hasChanged).to.eql(true); - - // Try to uninstall agent from host without the uninstall token - uninstallAgentFromHost(createdHost.hostname).then((responseWithoutToken) => { - expect(responseWithoutToken).to.match(/(.*)Invalid uninstall token(.*)/); - expect(responseWithoutToken).to.not.match(/(.*)Elastic Agent has been uninstalled(.*)/); - isAgentAndEndpointUninstalledFromHost(createdHost.hostname).then( - (isUninstalledWithoutToken) => { - expect(isUninstalledWithoutToken).to.eql(false); - - // Get the uninstall token from that agent policy - getUninstallToken(policyWithAgentTamperProtectionEnabled.policy_id).then( - (uninstallToken) => { - // Try to uninstall agent from host using the retrieved uninstall token - uninstallAgentFromHost(createdHost.hostname, uninstallToken.body.item.token).then( - (responseWithToken) => { - expect(responseWithToken).to.not.match(/(.*)Invalid uninstall token(.*)/); - expect(responseWithToken).to.match( - /(.*)Elastic Agent has been uninstalled(.*)/ - ); - - isAgentAndEndpointUninstalledFromHost(createdHost.hostname).then( - (isUninstalledWithToken) => { - expect(isUninstalledWithToken).to.eql(true); - } - ); - } - ); - } - ); - } - ); - }); - }); - }); - }); - - describe('When agent tamper protection is enabled but then is switched to a policy with it disabled', () => { - let createdHost: CreateAndEnrollEndpointHostResponse; - - beforeEach(() => { - // Create and enroll a new Endpoint host - return createEndpointHost(policyWithAgentTamperProtectionEnabled.policy_id).then((host) => { - createdHost = host as CreateAndEnrollEndpointHostResponse; - }); - }); - - afterEach(() => { - if (createdHost) { - cy.task('destroyEndpointHost', createdHost); - } - - if (createdHost) { - deleteAllLoadedEndpointData({ endpointAgentIds: [createdHost.agentId] }); - } - }); - - it('should uninstall from host without issues', () => { - waitForEndpointListPageToBeLoaded(createdHost.hostname); - - changeAgentPolicy(createdHost.agentId, policy.policy_id, 3).then((hasChanged) => { - expect(hasChanged).to.eql(true); - uninstallAgentFromHost(createdHost.hostname).then((responseWithoutToken) => { - expect(responseWithoutToken).to.not.match(/(.*)Invalid uninstall token(.*)/); - expect(responseWithoutToken).to.match(/(.*)Elastic Agent has been uninstalled(.*)/); - isAgentAndEndpointUninstalledFromHost(createdHost.hostname).then( - (isUninstalledWithoutToken) => { - expect(isUninstalledWithoutToken).to.eql(true); - } - ); - }); - }); - }); - }); - - describe('When agent tamper protection is enabled but then is switched to a policy with it also enabled', () => { - let createdHost: CreateAndEnrollEndpointHostResponse; - - beforeEach(() => { - // Create and enroll a new Endpoint host - return createEndpointHost(policyWithAgentTamperProtectionEnabled.policy_id).then((host) => { - createdHost = host as CreateAndEnrollEndpointHostResponse; - }); - }); - - afterEach(() => { - if (createdHost) { - cy.task('destroyEndpointHost', createdHost); - } - - if (createdHost) { - deleteAllLoadedEndpointData({ endpointAgentIds: [createdHost.agentId] }); - } - }); - - it('should uninstall from host without issues', () => { - waitForEndpointListPageToBeLoaded(createdHost.hostname); - - // Change agent policy and wait for action to be completed - changeAgentPolicy( - createdHost.agentId, - secondPolicyWithAgentTamperProtectionEnabled.policy_id, - 3 - ).then((hasChanged) => { - expect(hasChanged).to.eql(true); - - // Get the uninstall token from old agent policy - getUninstallToken(policyWithAgentTamperProtectionEnabled.policy_id).then( - (oldUninstallToken) => { - // Try to uninstall agent from host using old retrieved uninstall token - uninstallAgentFromHost(createdHost.hostname, oldUninstallToken.body.item.token).then( - (responseWithOldToken) => { - expect(responseWithOldToken).to.match(/(.*)Invalid uninstall token(.*)/); - expect(responseWithOldToken).to.not.match( - /(.*)Elastic Agent has been uninstalled(.*)/ - ); - - isAgentAndEndpointUninstalledFromHost(createdHost.hostname).then( - (isUninstalledWithOldToken) => { - expect(isUninstalledWithOldToken).to.eql(false); - - // Get the uninstall token from new agent policy - getUninstallToken(secondPolicyWithAgentTamperProtectionEnabled.policy_id).then( - (newUninstallToken) => { - // Try to uninstall agent from host using new retrieved uninstall token - uninstallAgentFromHost( - createdHost.hostname, - newUninstallToken.body.item.token - ).then((responseWithNewToken) => { - expect(responseWithNewToken).to.not.match( - /(.*)Invalid uninstall token(.*)/ - ); - expect(responseWithNewToken).to.match( - /(.*)Elastic Agent has been uninstalled(.*)/ - ); - - isAgentAndEndpointUninstalledFromHost(createdHost.hostname).then( - (isUninstalledWithNewToken) => { - expect(isUninstalledWithNewToken).to.eql(true); - } - ); - }); - } - ); - } - ); - } - ); - } - ); - }); - }); - }); -}); diff --git a/x-pack/plugins/security_solution/public/management/cypress/support/response_actions.ts b/x-pack/plugins/security_solution/public/management/cypress/support/response_actions.ts index b22e50c660d83..baaf0e12c10e2 100644 --- a/x-pack/plugins/security_solution/public/management/cypress/support/response_actions.ts +++ b/x-pack/plugins/security_solution/public/management/cypress/support/response_actions.ts @@ -48,10 +48,9 @@ export const responseActionTasks = ( const signed = get(newActionDoc, '_source.signed'); const signedDataBuffer = Buffer.from(signed.data, 'base64'); const signedDataJson = JSON.parse(signedDataBuffer.toString()); - const tamperedAgentsList = [...signedDataJson.agents, 'anotheragent']; const tamperedData = { ...signedDataJson, - agents: tamperedAgentsList, + comment: 'tampered data', }; const tamperedDataString = Buffer.from(JSON.stringify(tamperedData), 'utf8').toString( 'base64' diff --git a/x-pack/plugins/security_solution/public/management/cypress/tasks/isolate.ts b/x-pack/plugins/security_solution/public/management/cypress/tasks/isolate.ts index e13bb832adce5..10aec51af291d 100644 --- a/x-pack/plugins/security_solution/public/management/cypress/tasks/isolate.ts +++ b/x-pack/plugins/security_solution/public/management/cypress/tasks/isolate.ts @@ -41,6 +41,29 @@ export const isolateHostWithComment = (comment: string, hostname: string): void cy.getByTestSubj('host_isolation_comment').type(comment); }; +export const isolateHostFromEndpointList = (index: number = 0): void => { + // open the action menu and click isolate action + cy.getByTestSubj('endpointTableRowActions').eq(index).click(); + cy.getByTestSubj('isolateLink').click(); + // isolation form, click confirm button + cy.getByTestSubj('hostIsolateConfirmButton').click(); + // return to endpoint details + cy.getByTestSubj('hostIsolateSuccessCompleteButton').click(); + // close details flyout + cy.getByTestSubj('euiFlyoutCloseButton').click(); + + // ensure the host is isolated, wait for 3 minutes for the host to be isolated + cy.wait(18000); + + cy.getByTestSubj('endpointListTable').within(() => { + cy.get('tbody tr') + .eq(index) + .within(() => { + cy.get('td').eq(1).should('contain.text', 'Isolated'); + }); + }); +}; + export const releaseHostWithComment = (comment: string, hostname: string): void => { cy.contains(`${hostname} is currently isolated.`); cy.getByTestSubj('endpointHostIsolationForm'); diff --git a/x-pack/plugins/security_solution/public/resolver/view/panels/event_detail.tsx b/x-pack/plugins/security_solution/public/resolver/view/panels/event_detail.tsx index e5e1f88a36169..64c94f76f86a1 100644 --- a/x-pack/plugins/security_solution/public/resolver/view/panels/event_detail.tsx +++ b/x-pack/plugins/security_solution/public/resolver/view/panels/event_detail.tsx @@ -330,6 +330,9 @@ function EventDetailBreadcrumbs({ } const StyledDescriptionList = memo(styled(EuiDescriptionList)` + .euiDescriptionList__title { + word-break: normal; + } .euiDescriptionList__title, .euiDescriptionList__description { overflow-wrap: break-word; diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/tabs_content/index.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/tabs_content/index.tsx index 2109420b5d6aa..04580b1546b4c 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/tabs_content/index.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/tabs_content/index.tsx @@ -415,7 +415,7 @@ const TabsContentComponent: React.FC = ({ tooltipContent={ } /> diff --git a/x-pack/plugins/security_solution/scripts/endpoint/common/fleet_server/fleet_server_services.ts b/x-pack/plugins/security_solution/scripts/endpoint/common/fleet_server/fleet_server_services.ts index 79dcdd458d359..50384b3541f5c 100644 --- a/x-pack/plugins/security_solution/scripts/endpoint/common/fleet_server/fleet_server_services.ts +++ b/x-pack/plugins/security_solution/scripts/endpoint/common/fleet_server/fleet_server_services.ts @@ -290,7 +290,7 @@ const startFleetServerWithDocker = async ({ await updateFleetElasticsearchOutputHostNames(kbnClient, log); if (isServerless) { - log.info(`Waiting for server to register with Elasticsearch`); + log.info(`Waiting for server [${hostname}] to register with Elasticsearch`); await waitForFleetServerToRegisterWithElasticsearch(kbnClient, hostname, 120000); } else { @@ -684,7 +684,7 @@ const waitForFleetServerToRegisterWithElasticsearch = async ( .then((response) => response.data) .catch(catchAxiosErrorFormatAndThrow); - return (fleetServerRecord.hits.total as estypes.SearchTotalHits).value === 1; + return ((fleetServerRecord?.hits?.total as estypes.SearchTotalHits)?.value ?? 0) === 1; }, RETRYABLE_TRANSIENT_ERRORS); if (!found) { diff --git a/x-pack/plugins/security_solution/scripts/endpoint/common/roles_users/serverless/es_serverless_resources/roles.yml b/x-pack/plugins/security_solution/scripts/endpoint/common/roles_users/serverless/es_serverless_resources/roles.yml index ace64c7570aa2..050e6db921095 100644 --- a/x-pack/plugins/security_solution/scripts/endpoint/common/roles_users/serverless/es_serverless_resources/roles.yml +++ b/x-pack/plugins/security_solution/scripts/endpoint/common/roles_users/serverless/es_serverless_resources/roles.yml @@ -11,7 +11,6 @@ system_indices_superuser: resources: ['*'] run_as: ['*'] - #-------------------------------------------------------------------------------------------------- # # FILE SOURCE AT: @@ -26,84 +25,129 @@ viewer: cluster: [] indices: - names: - - "/~(([.]|ilm-history-).*)/" + - '.siem-signals*' + - '.lists-*' + - '.items-*' privileges: - - "read" - - "view_index_metadata" + - 'read' + - 'view_index_metadata' allow_restricted_indices: false - names: - - ".siem-signals*" - - ".lists-*" - - ".items-*" + - '.alerts*' + - '.preview.alerts*' privileges: - - "read" - - "view_index_metadata" + - 'read' + - 'view_index_metadata' allow_restricted_indices: false - names: - - ".alerts*" - - ".preview.alerts*" + - apm-*-transaction* + - traces-apm* + - auditbeat-* + - endgame-* + - filebeat-* + - logs-* + - packetbeat-* + - winlogbeat-* + - metrics-endpoint.metadata_current_* + - '.fleet-agents*' + - '.fleet-actions*' + - 'risk-score.risk-score-*' privileges: - - "read" - - "view_index_metadata" - allow_restricted_indices: false + - read applications: - - application: "kibana-.kibana" + - application: 'kibana-.kibana' privileges: - - "read" - resources: - - "*" + - feature_ml.read + - feature_siem.read + - feature_siem.read_alerts + - feature_siem.endpoint_list_read + - feature_securitySolutionCases.read + - feature_actions.read + - feature_builtInAlerts.read + - feature_osquery.read + - feature_discover.all + - feature_dashboard.all + - feature_canvas.all + - feature_graph.all + - feature_maps.all + - feature_visualize.all + resources: '*' run_as: [] + +# modeled after t3_analyst editor: cluster: [] indices: - names: - - "/~(([.]|ilm-history-).*)/" - privileges: - - "read" - - "view_index_metadata" - allow_restricted_indices: false - - names: - - "observability-annotations" + - '.siem-signals*' + - '.lists-*' + - '.items-*' privileges: - - "read" - - "view_index_metadata" - - "write" + - 'read' + - 'view_index_metadata' + - 'write' + - 'maintenance' allow_restricted_indices: false - names: - - ".siem-signals*" - - ".lists-*" - - ".items-*" + - apm-*-transaction* + - traces-apm* + - auditbeat-* + - endgame-* + - filebeat-* + - logs-* + - packetbeat-* + - winlogbeat-* privileges: - - "read" - - "view_index_metadata" - - "write" - - "maintenance" - allow_restricted_indices: false + - read + - write - names: - - ".internal.alerts*" - - ".alerts*" - - ".internal.preview.alerts*" - - ".preview.alerts*" + - '.internal.alerts*' + - '.alerts*' + - '.internal.preview.alerts*' + - '.preview.alerts*' + - 'risk-score.risk-score-*' privileges: - - "read" - - "view_index_metadata" - - "write" - - "maintenance" + - 'read' + - 'view_index_metadata' + - 'write' + - 'maintenance' allow_restricted_indices: false applications: - - application: "kibana-.kibana" + - application: 'kibana-.kibana' privileges: - - "all" - resources: - - "*" + - feature_ml.read + - feature_siem.all + - feature_siem.read_alerts + - feature_siem.crud_alerts + - feature_siem.endpoint_list_all + - feature_siem.trusted_applications_all + - feature_siem.event_filters_all + - feature_siem.host_isolation_exceptions_all + - feature_siem.blocklist_all + - feature_siem.policy_management_read # Elastic Defend Policy Management + - feature_siem.host_isolation_all + - feature_siem.process_operations_all + - feature_siem.actions_log_management_all # Response actions history + - feature_siem.file_operations_all + - feature_securitySolutionCases.all + - feature_actions.read + - feature_builtInAlerts.all + - feature_osquery.all + - feature_discover.all + - feature_dashboard.all + - feature_canvas.all + - feature_graph.all + - feature_maps.all + - feature_visualize.all + resources: '*' run_as: [] t1_analyst: cluster: indices: - names: - - ".alerts-security*" - - ".siem-signals-*" + - '.alerts-security*' + - '.siem-signals-*' privileges: - read - write @@ -118,23 +162,31 @@ t1_analyst: - packetbeat-* - winlogbeat-* - metrics-endpoint.metadata_current_* - - ".fleet-agents*" - - ".fleet-actions*" + - '.fleet-agents*' + - '.fleet-actions*' + - risk-score.risk-score-* privileges: - read applications: - - application: "kibana-.kibana" + - application: 'kibana-.kibana' privileges: - feature_ml.read - feature_siem.read - feature_siem.read_alerts - feature_siem.endpoint_list_read - feature_securitySolutionCases.read + - feature_securitySolutionAssistant.all - feature_actions.read - feature_builtInAlerts.read - feature_osquery.read - feature_osquery.run_saved_queries - resources: "*" + - feature_discover.all + - feature_dashboard.all + - feature_canvas.all + - feature_graph.all + - feature_maps.all + - feature_visualize.all + resources: '*' t2_analyst: cluster: @@ -160,21 +212,29 @@ t2_analyst: - metrics-endpoint.metadata_current_* - .fleet-agents* - .fleet-actions* + - risk-score.risk-score-* privileges: - read applications: - - application: "kibana-.kibana" + - application: 'kibana-.kibana' privileges: - feature_ml.read - feature_siem.read - feature_siem.read_alerts - feature_siem.endpoint_list_read - feature_securitySolutionCases.all + - feature_securitySolutionAssistant.all - feature_actions.read - feature_builtInAlerts.read - feature_osquery.read - feature_osquery.run_saved_queries - resources: "*" + - feature_discover.all + - feature_dashboard.all + - feature_canvas.all + - feature_graph.all + - feature_maps.all + - feature_visualize.all + resources: '*' t3_analyst: cluster: @@ -207,10 +267,11 @@ t3_analyst: - metrics-endpoint.metadata_current_* - .fleet-agents* - .fleet-actions* + - risk-score.risk-score-* privileges: - read applications: - - application: "kibana-.kibana" + - application: 'kibana-.kibana' privileges: - feature_ml.read - feature_siem.all @@ -227,10 +288,17 @@ t3_analyst: - feature_siem.actions_log_management_all # Response actions history - feature_siem.file_operations_all - feature_securitySolutionCases.all + - feature_securitySolutionAssistant.all - feature_actions.read - feature_builtInAlerts.all - feature_osquery.all - resources: "*" + - feature_discover.all + - feature_dashboard.all + - feature_canvas.all + - feature_graph.all + - feature_maps.all + - feature_visualize.all + resources: '*' threat_intelligence_analyst: cluster: @@ -259,10 +327,11 @@ threat_intelligence_analyst: - metrics-endpoint.metadata_current_* - .fleet-agents* - .fleet-actions* + - risk-score.risk-score-* privileges: - read applications: - - application: "kibana-.kibana" + - application: 'kibana-.kibana' privileges: - feature_ml.read - feature_siem.read @@ -270,10 +339,17 @@ threat_intelligence_analyst: - feature_siem.endpoint_list_read - feature_siem.blocklist_all - feature_securitySolutionCases.all + - feature_securitySolutionAssistant.all - feature_actions.read - feature_builtInAlerts.read - feature_osquery.all - resources: "*" + - feature_discover.all + - feature_dashboard.all + - feature_canvas.all + - feature_graph.all + - feature_maps.all + - feature_visualize.all + resources: '*' rule_author: cluster: @@ -310,10 +386,11 @@ rule_author: - metrics-endpoint.metadata_current_* - .fleet-agents* - .fleet-actions* + - risk-score.risk-score-* privileges: - read applications: - - application: "kibana-.kibana" + - application: 'kibana-.kibana' privileges: - feature_ml.read - feature_siem.all @@ -327,10 +404,17 @@ rule_author: - feature_siem.blocklist_all # Elastic Defend Policy Management - feature_siem.actions_log_management_read - feature_securitySolutionCases.all + - feature_securitySolutionAssistant.all - feature_actions.read - feature_builtInAlerts.all - feature_osquery.all - resources: "*" + - feature_discover.all + - feature_dashboard.all + - feature_canvas.all + - feature_graph.all + - feature_maps.all + - feature_visualize.all + resources: '*' soc_manager: cluster: @@ -366,10 +450,11 @@ soc_manager: - metrics-endpoint.metadata_current_* - .fleet-agents* - .fleet-actions* + - risk-score.risk-score-* privileges: - read applications: - - application: "kibana-.kibana" + - application: 'kibana-.kibana' privileges: - feature_ml.read - feature_siem.all @@ -387,14 +472,21 @@ soc_manager: - feature_siem.file_operations_all - feature_siem.execute_operations_all - feature_securitySolutionCases.all + - feature_securitySolutionAssistant.all - feature_actions.all - feature_builtInAlerts.all - feature_osquery.all - - feature_indexPatterns.all # Detections Data Views - resources: "*" + - feature_indexPatterns.all + - feature_discover.all + - feature_dashboard.all + - feature_canvas.all + - feature_graph.all + - feature_maps.all + - feature_visualize.all + resources: '*' detections_admin: - cluster: + cluster: ['manage_index_templates', 'manage_transform'] indices: - names: - apm-*-transaction* @@ -421,18 +513,29 @@ detections_admin: - .fleet-actions* privileges: - read + - names: + - risk-score.risk-score-* + privileges: + - all applications: - - application: "kibana-.kibana" + - application: 'kibana-.kibana' privileges: - feature_ml.all - feature_siem.all - feature_siem.read_alerts - feature_siem.crud_alerts - feature_securitySolutionCases.all + - feature_securitySolutionAssistant.all - feature_actions.all - feature_builtInAlerts.all - feature_dev_tools.all - resources: "*" + - feature_discover.all + - feature_dashboard.all + - feature_canvas.all + - feature_graph.all + - feature_maps.all + - feature_visualize.all + resources: '*' platform_engineer: cluster: @@ -453,10 +556,11 @@ platform_engineer: - .siem-signals-* - .preview.alerts-security* - .internal.preview.alerts-security* + - risk-score.risk-score-* privileges: - all applications: - - application: "kibana-.kibana" + - application: 'kibana-.kibana' privileges: - feature_ml.all - feature_siem.all @@ -470,13 +574,20 @@ platform_engineer: - feature_siem.blocklist_all # Elastic Defend Policy Management - feature_siem.actions_log_management_read - feature_securitySolutionCases.all + - feature_securitySolutionAssistant.all - feature_actions.all - feature_builtInAlerts.all - feature_fleet.all - feature_fleetv2.all - feature_osquery.all - - feature_indexPatterns.all # Detections Data Views - resources: "*" + - feature_indexPatterns.all + - feature_discover.all + - feature_dashboard.all + - feature_canvas.all + - feature_graph.all + - feature_maps.all + - feature_visualize.all + resources: '*' endpoint_operations_analyst: cluster: @@ -498,6 +609,7 @@ endpoint_operations_analyst: - winlogbeat-* - .lists* - .items* + - risk-score.risk-score-* privileges: - read - names: @@ -509,7 +621,7 @@ endpoint_operations_analyst: - read - write applications: - - application: "kibana-.kibana" + - application: 'kibana-.kibana' privileges: - feature_ml.read - feature_siem.all @@ -526,12 +638,19 @@ endpoint_operations_analyst: - feature_siem.file_operations_all - feature_siem.execute_operations_all # Execute - feature_securitySolutionCases.all + - feature_securitySolutionAssistant.all - feature_actions.all - feature_builtInAlerts.all - feature_osquery.all - feature_fleet.all - feature_fleetv2.all - resources: "*" + - feature_discover.all + - feature_dashboard.all + - feature_canvas.all + - feature_graph.all + - feature_maps.all + - feature_visualize.all + resources: '*' endpoint_policy_manager: cluster: @@ -553,6 +672,7 @@ endpoint_policy_manager: - winlogbeat-* - .lists* - .items* + - risk-score.risk-score-* privileges: - read - names: @@ -565,7 +685,7 @@ endpoint_policy_manager: - write - manage applications: - - application: "kibana-.kibana" + - application: 'kibana-.kibana' privileges: - feature_ml.all - feature_siem.all @@ -578,9 +698,16 @@ endpoint_policy_manager: - feature_siem.host_isolation_exceptions_all - feature_siem.blocklist_all # Elastic Defend Policy Management - feature_securitySolutionCases.all + - feature_securitySolutionAssistant.all - feature_actions.all - feature_builtInAlerts.all - feature_osquery.all - feature_fleet.all - feature_fleetv2.all - resources: "*" + - feature_discover.all + - feature_dashboard.all + - feature_canvas.all + - feature_graph.all + - feature_maps.all + - feature_visualize.all + resources: '*' diff --git a/x-pack/plugins/security_solution/scripts/endpoint/common/stack_services.ts b/x-pack/plugins/security_solution/scripts/endpoint/common/stack_services.ts index a783b1fc73113..13fc2a1a0ffba 100644 --- a/x-pack/plugins/security_solution/scripts/endpoint/common/stack_services.ts +++ b/x-pack/plugins/security_solution/scripts/endpoint/common/stack_services.ts @@ -337,7 +337,7 @@ export const isServerlessKibanaFlavor = async (client: KbnClient | Client): Prom // If we don't have status for plugins, then error // the Status API will always return something (its an open API), but if auth was successful, // it will also return more data. - if (!kbnStatus.status.plugins) { + if (!kbnStatus?.status?.plugins) { throw new Error( `Unable to retrieve Kibana plugins status (likely an auth issue with the username being used for kibana)` ); diff --git a/x-pack/plugins/security_solution/scripts/run_cypress/parallel.ts b/x-pack/plugins/security_solution/scripts/run_cypress/parallel.ts index 1882fba6e3884..19eeafaecfcdc 100644 --- a/x-pack/plugins/security_solution/scripts/run_cypress/parallel.ts +++ b/x-pack/plugins/security_solution/scripts/run_cypress/parallel.ts @@ -81,7 +81,8 @@ export const cli = () => { } return acc; }, {} as Record) - ); + ) + .boolean('inspect'); log.info(` ---------------------------------------------- @@ -319,6 +320,7 @@ ${JSON.stringify( ? [] : ['--dev', '--no-dev-config', '--no-dev-credentials'], onEarlyExit, + inspect: argv.inspect, }); await providers.loadAll(); diff --git a/x-pack/plugins/security_solution/server/lib/telemetry/filterlists/prebuilt_rules_alerts.ts b/x-pack/plugins/security_solution/server/lib/telemetry/filterlists/prebuilt_rules_alerts.ts index 1b4a8819c12b8..c08c66a572245 100644 --- a/x-pack/plugins/security_solution/server/lib/telemetry/filterlists/prebuilt_rules_alerts.ts +++ b/x-pack/plugins/security_solution/server/lib/telemetry/filterlists/prebuilt_rules_alerts.ts @@ -352,21 +352,452 @@ export const prebuiltRuleAllowlistFields: AllowlistFields = { }, // Google/GCP google_workspace: { + actor: { + type: true, + }, + etag: true, + event: { + name: true, + type: true, + }, + id: { + application_name: true, + customer: { + id: true, + }, + time: true, + unique_qualifier: true, + }, + kind: true, + organization: { + domain: true, + }, admin: { + application: { + edition: true, + enabled: true, + licences_order_number: true, + licences_purchased: true, + id: true, + asp_id: true, + package_id: true, + }, + group: { + priorities: true, + allowed_list: true, + }, new_value: true, + old_value: true, + org_unit: { + name: true, + full: true, + }, setting: { name: true, + description: true, }, - application: { + user_defined_setting: { + name: true, + }, + domain: { + alias: true, + name: true, + secondary_name: true, + }, + managed_configuration: true, + non_featured_services_selection: true, + field: true, + resource: { + id: true, + }, + gateway: { + name: true, + }, + chrome_os: { + session_type: true, + }, + device: { + type: true, + command_details: true, + }, + print_server: { + name: true, + }, + printer: { name: true, }, - old_value: true, role: { + id: true, + name: true, + }, + privilege: { + name: true, + }, + service: { + name: true, + }, + url: { + name: true, + }, + product: { + name: true, + sku: true, + }, + bulk_upload: { + failed: true, + total: true, + }, + email: { + quarantine_name: true, + log_search_filter: { + message_id: true, + start_date: true, + end_date: true, + }, + }, + oauth2: { + service: { + name: true, + }, + application: { + id: true, + name: true, + type: true, + }, + }, + verification_method: true, + alert: { + name: true, + }, + rule: { name: true, }, + api: { + client: { + name: true, + }, + scopes: true, + }, + mdm: { + token: true, + vendor: true, + }, + info_type: true, + email_monitor: { + level: { + incoming: true, + outgoing: true, + }, + }, + email_dump: { + include_deleted: true, + package_content: true, + query: true, + }, + request: { + id: true, + }, }, - event: { + alert: { + create_time: true, + customer: { + id: true, + }, + data: { + action: { + name: true, + }, + alert_details: true, + appeal_window: true, + attachment: { + data: { + csv: { + data_rows: { + entries: true, + }, + }, + }, + }, + create_time: true, + description: true, + display: { + name: true, + }, + domain: true, + domain_id: { + customer_primary_domain: true, + }, + events: { + device_compromised_state: true, + device: { + property: true, + model: true, + type: true, + }, + new_value: true, + old_value: true, + resource: { + id: true, + }, + }, + event_time: true, + header: true, + is_internal: true, + malicious_entity: { + display_name: true, + entity: { + display_name: true, + }, + from_header: true, + }, + messages: { + attachments_sha256_hash: true, + date: true, + id: true, + message_body_snippet: true, + md5: { + hash: { + message_body: true, + subject: true, + }, + }, + subject_text: true, + }, + name: true, + next_update_time: true, + primary: { + admin: { + changed_event: { + domain: true, + }, + }, + }, + products: true, + query: true, + resolution_time: true, + rule: { + violation_info: { + data: { + source: true, + }, + match_info: { + predefined_detector: { + name: true, + }, + user_defined_detector: { + display: { + name: true, + }, + resource: { + name: true, + }, + }, + }, + resource_info: { + document: { + id: true, + }, + resource: { + title: true, + }, + }, + rule_info: { + display: { + name: true, + }, + resource: { + name: true, + }, + }, + trigger: { + value: true, + }, + }, + }, + rule_description: true, + state: true, + status: true, + system_action_type: true, + title: true, + trigger: { + source: true, + }, + type: true, + update_time: true, + }, + deleted: true, + end_time: true, + etag: true, + source: true, + start_time: true, + type: true, + update_time: true, + }, + context_aware_access: { + access_level: { + applied: true, + satisfied: true, + unsatisfied: true, + }, + application: true, + device: { + state: true, + }, + }, + device: { + account_state: true, + action: { + execution_status: true, + type: true, + }, + apk_sha256_hash: true, + application: { + message: true, + report: { + key: true, + severity: true, + timestamp: true, + }, + state: true, + }, + basic_integrity: true, + compliance: true, + compromised_state: true, + cts_profile_match: true, + deactivation_reason: true, + failed_passwd_attempts: true, + id: true, + model: true, + new_device_id: true, + new_value: true, + old_value: true, + os: { + edition: true, + property: true, + version: true, + }, + ownership: true, + policy: { + name: true, + sync: { + result: true, + type: true, + }, + }, + property: true, + register_privilege: true, + resource: { + id: true, + }, + risk_signal: true, + security: { + event_id: true, + patch_level: true, + }, + setting: true, + status_on_apple_portal: true, + type: true, + value: true, + windows_syncml_policy_status_code: true, + }, + drive: { + source_folder_id: true, + source_folder_title: true, + destination_folder_id: true, + destination_folder_title: true, + file: { + id: true, + type: true, + owner: { + is_shared_drive: true, + }, + }, + originating_app_id: true, + primary_event: true, + shared_drive_id: true, + visibility: true, + new_value: true, + old_value: true, + sheets_import_range_recipient_doc: true, + old_visibility: true, + visibility_change: true, + target_domain: true, + added_role: true, + membership_change_type: true, + shared_drive_settings_change_type: true, + removed_role: true, + target: true, + }, + login: { + challenge_method: true, + failure_type: true, + challenge_status: true, + timestamp: true, type: true, + is_second_factor: true, + is_suspicious: true, + }, + rules: { + actions: true, + application: true, + conference_id: true, + data_source: true, + device: { + type: true, + }, + drive_shared_drive_id: true, + evaluation_context: true, + has_alert: true, + has_content_match: true, + id: true, + matched: { + detectors: true, + templates: true, + threshold: true, + trigger: true, + }, + mobile_device_type: true, + mobile_ios_vendor_id: true, + name: true, + resource_name: true, + resource: { + id: true, + name: true, + recipients_omitted_count: true, + title: true, + type: true, + }, + scan_type: true, + severity: true, + space: { + id: true, + type: true, + }, + suppressed_actions: true, + triggered_actions: true, + type: true, + update_time_usec: true, + }, + saml: { + application_name: true, + failure_type: true, + initiated_by: true, + orgunit_path: true, + status_code: true, + second_level_status_code: true, + }, + token: { + api_name: true, + app_name: true, + client: { + type: true, + }, + method_name: true, + num_response_bytes: true, + scope: { + data: true, + value: true, + }, }, }, // kubernetes @@ -467,6 +898,81 @@ export const prebuiltRuleAllowlistFields: AllowlistFields = { }, }, }, + // okta + okta: { + actor: { + alternate_id: true, + id: true, + type: true, + }, + client: { + device: true, + id: true, + user_agent: { + raw_user_agent: true, + }, + zone: true, + }, + device: { + device_integrator: true, + disk_encryption_type: true, + id: true, + managed: true, + name: true, + os_platform: true, + os_version: true, + registered: true, + screen_lock_type: true, + secure_hardware_present: true, + }, + outcome: { + reason: true, + result: true, + }, + transaction: { + id: true, + type: true, + }, + debug_context: { + debug_data: { + device_fingerprint: true, + dt_hash: true, + factor: true, + request_id: true, + request_uri: true, + threat_suspected: true, + risk_behaviors: true, + risk_level: true, + risk_reasons: true, + url: true, + }, + }, + authentication_context: { + authentication_provider: true, + authentication_step: true, + credential_provider: true, + credential_type: true, + external_session_id: true, + interface: true, + }, + security_context: { + as: { + autonomous_system_number: true, + organization: { + name: true, + }, + }, + domain: true, + is_proxy: true, + isp: true, + }, + uuid: true, + version: true, + severity: true, + display_message: true, + target: true, + event_type: true, + }, // winlog winlog: { api: true, diff --git a/x-pack/plugins/security_solution_serverless/public/get_started/welcome_panel/change_plan_link.test.tsx b/x-pack/plugins/security_solution_serverless/public/get_started/welcome_panel/change_plan_link.test.tsx index ef9429dfe97d5..52f3fb4f1a8ee 100644 --- a/x-pack/plugins/security_solution_serverless/public/get_started/welcome_panel/change_plan_link.test.tsx +++ b/x-pack/plugins/security_solution_serverless/public/get_started/welcome_panel/change_plan_link.test.tsx @@ -39,7 +39,7 @@ describe('ChangePlanLink', () => { expect(badge).toBeInTheDocument(); expect(link).toBeInTheDocument(); expect(link.getAttribute('href')).toEqual( - 'https://cloud.elastic.co/projects/security/test-project-id' + 'https://cloud.elastic.co/projects/security/test-project-id?open=securityProjectFeatures' ); }); diff --git a/x-pack/plugins/security_solution_serverless/public/get_started/welcome_panel/change_plan_link.tsx b/x-pack/plugins/security_solution_serverless/public/get_started/welcome_panel/change_plan_link.tsx index fcdc5a0729290..b40e1987999b8 100644 --- a/x-pack/plugins/security_solution_serverless/public/get_started/welcome_panel/change_plan_link.tsx +++ b/x-pack/plugins/security_solution_serverless/public/get_started/welcome_panel/change_plan_link.tsx @@ -18,7 +18,7 @@ import { css } from '@emotion/react'; import type { ProductTier } from '../../../common/product'; import { ProductTierBadge } from './product_tier_badge'; import { WELCOME_PANEL_PROJECT_CREATED_CHANGE_PLAN_TITLE } from './translations'; -import { getProjectDetailsUrl } from '../../navigation/links/util'; +import { getProjectFeaturesUrl } from '../../navigation/links/util'; import { useKibana } from '../../common/services'; const ChangePlanLinkComponent = ({ productTier }: { productTier: ProductTier | undefined }) => { @@ -46,7 +46,7 @@ const ChangePlanLinkComponent = ({ productTier }: { productTier: ProductTier | u color: ${euiTheme.colors.primaryText}; padding-left: ${euiTheme.size.m}; `} - href={getProjectDetailsUrl(cloud)} + href={getProjectFeaturesUrl(cloud)} target="_blank" external={false} > diff --git a/x-pack/plugins/security_solution_serverless/public/navigation/links/util.test.ts b/x-pack/plugins/security_solution_serverless/public/navigation/links/util.test.ts new file mode 100644 index 0000000000000..fd03f6f2ecdf3 --- /dev/null +++ b/x-pack/plugins/security_solution_serverless/public/navigation/links/util.test.ts @@ -0,0 +1,36 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { getProjectFeaturesUrl } from './util'; +import type { CloudStart } from '@kbn/cloud-plugin/public'; + +const cloud = { + serverless: { + projectId: '1234', + }, + projectsUrl: 'https://cloud.elastic.co/projects', +} as CloudStart; + +describe('util', () => { + describe('getProductFeaturesUrl', () => { + it('should return undefined if the projectId is not present', () => { + expect(getProjectFeaturesUrl({ ...cloud, serverless: { projectId: undefined } })).toBe( + undefined + ); + }); + + it('should return undefined if the projectsUrl is not present', () => { + expect(getProjectFeaturesUrl({ ...cloud, projectsUrl: undefined })).toBe(undefined); + }); + + it('should return the correct url', () => { + expect(getProjectFeaturesUrl(cloud)).toBe( + `${cloud.projectsUrl}/security/${cloud.serverless?.projectId}?open=securityProjectFeatures` + ); + }); + }); +}); diff --git a/x-pack/plugins/security_solution_serverless/public/navigation/links/util.ts b/x-pack/plugins/security_solution_serverless/public/navigation/links/util.ts index 6ddacc2a1e021..6d48f5b09f77b 100644 --- a/x-pack/plugins/security_solution_serverless/public/navigation/links/util.ts +++ b/x-pack/plugins/security_solution_serverless/public/navigation/links/util.ts @@ -25,13 +25,6 @@ export const getProjectPageNameFromNavLinkId = (navLinkId: string): ProjectPageN export const isCloudLink = (linkId: string): boolean => linkId.startsWith('cloud:'); export const getCloudLinkKey = (linkId: string): string => linkId.replace('cloud:', ''); -export const getProjectDetails = (cloud: CloudStart) => cloud.serverless; -export const getProjectDetailsUrl = (cloud: CloudStart) => { - const projectId = cloud.serverless?.projectId; - return projectId - ? `${getCloudUrl('projects', cloud)}/${SECURITY_PROJECT_TYPE}/${projectId}` - : undefined; -}; export const getCloudUrl: GetCloudUrl = (cloudUrlKey, cloud) => { switch (cloudUrlKey) { @@ -54,6 +47,16 @@ export const getCloudUrl: GetCloudUrl = (cloudUrlKey, cloud) => { } }; +export const getProjectDetails = (cloud: CloudStart) => cloud.serverless; +export const getProjectFeaturesUrl = (cloud: CloudStart): string | undefined => { + const projectsBaseUrl = getCloudUrl('projects', cloud); + const projectId = getProjectDetails(cloud)?.projectId; + if (!projectsBaseUrl || !projectId) { + return undefined; + } + return `${projectsBaseUrl}/${SECURITY_PROJECT_TYPE}/${projectId}?open=securityProjectFeatures`; +}; + /** * Defines the navigation items that should be in the footer of the side navigation. * @todo Make it a new property in the `NavigationLink` type `position?: 'top' | 'bottom' (default: 'top')` diff --git a/x-pack/plugins/stack_alerts/public/rule_types/es_query/expression/query_form_type_chooser.tsx b/x-pack/plugins/stack_alerts/public/rule_types/es_query/expression/query_form_type_chooser.tsx index 0077a035d1e8d..f551d078314b6 100644 --- a/x-pack/plugins/stack_alerts/public/rule_types/es_query/expression/query_form_type_chooser.tsx +++ b/x-pack/plugins/stack_alerts/public/rule_types/es_query/expression/query_form_type_chooser.tsx @@ -32,7 +32,7 @@ export const ExperimentalBadge = React.memo(() => ( 'xpack.stackAlerts.esQuery.ui.selectQueryFormType.experimentalDescription', { defaultMessage: - 'This functionality is in technical preview and may be changed or removed completely in a future release. Elastic will take a best effort approach to fix any issues, but features in technical preview are not subject to the support SLA of official GA features.', + 'This functionality is in technical preview and may be changed or removed completely in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features.', } )} tooltipPosition="bottom" diff --git a/x-pack/plugins/stack_alerts/server/plugin.ts b/x-pack/plugins/stack_alerts/server/plugin.ts index b4b25bb983195..f8ea52d1dcf47 100644 --- a/x-pack/plugins/stack_alerts/server/plugin.ts +++ b/x-pack/plugins/stack_alerts/server/plugin.ts @@ -22,7 +22,6 @@ export class AlertingBuiltinsPlugin public setup(core: CoreSetup, { alerting, features }: StackAlertsDeps) { features.registerKibanaFeature(BUILT_IN_ALERTS_FEATURE); - registerBuiltInRuleTypes({ logger: this.logger, data: core diff --git a/x-pack/plugins/stack_alerts/server/rule_types/es_query/rule_type_params.test.ts b/x-pack/plugins/stack_alerts/server/rule_types/es_query/rule_type_params.test.ts index b6011e72bbcc7..128fd339f001b 100644 --- a/x-pack/plugins/stack_alerts/server/rule_types/es_query/rule_type_params.test.ts +++ b/x-pack/plugins/stack_alerts/server/rule_types/es_query/rule_type_params.test.ts @@ -354,6 +354,31 @@ describe('ruleType Params validate()', () => { expect(onValidate()).not.toThrow(); }); + describe('esqlQuery search type', () => { + beforeEach(() => { + params = { ...DefaultParams, searchType: 'esqlQuery', esqlQuery: { esql: 'from test' } }; + delete params.esQuery; + delete params.index; + }); + + it('fails for invalid thresholdComparator', async () => { + params.thresholdComparator = Comparator.LT; + expect(onValidate()).toThrowErrorMatchingInlineSnapshot( + `"[thresholdComparator]: is required to be greater than"` + ); + }); + + it('fails for invalid threshold', async () => { + params.threshold = [7]; + expect(onValidate()).toThrowErrorMatchingInlineSnapshot(`"[threshold]: is required to be 0"`); + }); + + it('fails for undefined timeField', async () => { + params.timeField = undefined; + expect(onValidate()).toThrowErrorMatchingInlineSnapshot(`"[timeField]: is required"`); + }); + }); + function onValidate(): () => void { return () => validate(); } diff --git a/x-pack/plugins/stack_alerts/server/rule_types/es_query/rule_type_params.ts b/x-pack/plugins/stack_alerts/server/rule_types/es_query/rule_type_params.ts index 5469c6fa60247..d1f99b4e97b93 100644 --- a/x-pack/plugins/stack_alerts/server/rule_types/es_query/rule_type_params.ts +++ b/x-pack/plugins/stack_alerts/server/rule_types/es_query/rule_type_params.ts @@ -159,7 +159,28 @@ function validateParams(anyParams: unknown): string | undefined { } } - if (isSearchSourceRule(searchType) || isEsqlQueryRule(searchType)) { + if (isSearchSourceRule(searchType)) { + return; + } + + if (isEsqlQueryRule(searchType)) { + const { timeField } = anyParams as EsQueryRuleParams; + + if (!timeField) { + return i18n.translate('xpack.stackAlerts.esQuery.esqlTimeFieldErrorMessage', { + defaultMessage: '[timeField]: is required', + }); + } + if (thresholdComparator !== Comparator.GT) { + return i18n.translate('xpack.stackAlerts.esQuery.esqlThresholdComparatorErrorMessage', { + defaultMessage: '[thresholdComparator]: is required to be greater than', + }); + } + if (threshold && threshold[0] !== 0) { + return i18n.translate('xpack.stackAlerts.esQuery.esqlThresholdErrorMessage', { + defaultMessage: '[threshold]: is required to be 0', + }); + } return; } diff --git a/x-pack/plugins/stack_connectors/common/experimental_features.ts b/x-pack/plugins/stack_connectors/common/experimental_features.ts index 61b63cff732a6..4ac02dd9f06db 100644 --- a/x-pack/plugins/stack_connectors/common/experimental_features.ts +++ b/x-pack/plugins/stack_connectors/common/experimental_features.ts @@ -13,12 +13,12 @@ export type ExperimentalFeatures = typeof allowedExperimentalValues; */ export const allowedExperimentalValues = Object.freeze({ isMustacheAutocompleteOn: false, + sentinelOneConnectorOn: false, }); type ExperimentalConfigKeys = Array; type Mutable = { -readonly [P in keyof T]: T[P] }; -const InvalidExperimentalValue = class extends Error {}; const allowedKeys = Object.keys(allowedExperimentalValues) as Readonly; /** @@ -26,17 +26,15 @@ const allowedKeys = Object.keys(allowedExperimentalValues) as Readonly { const enabledFeatures: Mutable> = {}; for (const value of configValue) { - if (!isValidExperimentalValue(value)) { - throw new InvalidExperimentalValue(`[${value}] is not valid.`); + if (isValidExperimentalValue(value)) { + // @ts-expect-error ts upgrade v4.7.4 + enabledFeatures[value as keyof ExperimentalFeatures] = true; } - // @ts-expect-error ts upgrade v4.7.4 - enabledFeatures[value as keyof ExperimentalFeatures] = true; } return { diff --git a/x-pack/plugins/stack_connectors/public/connector_types/bedrock/bedrock.test.tsx b/x-pack/plugins/stack_connectors/public/connector_types/bedrock/bedrock.test.tsx index a37762487a822..311c731df76df 100644 --- a/x-pack/plugins/stack_connectors/public/connector_types/bedrock/bedrock.test.tsx +++ b/x-pack/plugins/stack_connectors/public/connector_types/bedrock/bedrock.test.tsx @@ -8,14 +8,16 @@ import { TypeRegistry } from '@kbn/triggers-actions-ui-plugin/public/application/type_registry'; import { registerConnectorTypes } from '..'; import type { ActionTypeModel } from '@kbn/triggers-actions-ui-plugin/public/types'; -import { registrationServicesMock } from '../../mocks'; +import { experimentalFeaturesMock, registrationServicesMock } from '../../mocks'; import { SUB_ACTION } from '../../../common/bedrock/constants'; +import { ExperimentalFeaturesService } from '../../common/experimental_features_service'; const ACTION_TYPE_ID = '.bedrock'; let actionTypeModel: ActionTypeModel; beforeAll(() => { const connectorTypeRegistry = new TypeRegistry(); + ExperimentalFeaturesService.init({ experimentalFeatures: experimentalFeaturesMock }); registerConnectorTypes({ connectorTypeRegistry, services: registrationServicesMock }); const getResult = connectorTypeRegistry.get(ACTION_TYPE_ID); if (getResult !== null) { diff --git a/x-pack/plugins/stack_connectors/public/connector_types/cases_webhook/webhook.test.tsx b/x-pack/plugins/stack_connectors/public/connector_types/cases_webhook/webhook.test.tsx index df76aef8f9001..2e53fd28248c0 100644 --- a/x-pack/plugins/stack_connectors/public/connector_types/cases_webhook/webhook.test.tsx +++ b/x-pack/plugins/stack_connectors/public/connector_types/cases_webhook/webhook.test.tsx @@ -8,13 +8,15 @@ import { TypeRegistry } from '@kbn/triggers-actions-ui-plugin/public/application/type_registry'; import { registerConnectorTypes } from '..'; import type { ActionTypeModel as ConnectorTypeModel } from '@kbn/triggers-actions-ui-plugin/public/types'; -import { registrationServicesMock } from '../../mocks'; +import { experimentalFeaturesMock, registrationServicesMock } from '../../mocks'; +import { ExperimentalFeaturesService } from '../../common/experimental_features_service'; const CONNECTOR_TYPE_ID = '.cases-webhook'; let connectorTypeModel: ConnectorTypeModel; beforeAll(() => { const connectorTypeRegistry = new TypeRegistry(); + ExperimentalFeaturesService.init({ experimentalFeatures: experimentalFeaturesMock }); registerConnectorTypes({ connectorTypeRegistry, services: registrationServicesMock }); const getResult = connectorTypeRegistry.get(CONNECTOR_TYPE_ID); if (getResult !== null) { diff --git a/x-pack/plugins/stack_connectors/public/connector_types/d3security/d3security.test.tsx b/x-pack/plugins/stack_connectors/public/connector_types/d3security/d3security.test.tsx index 09ee10aa29254..8e384bddbcafe 100644 --- a/x-pack/plugins/stack_connectors/public/connector_types/d3security/d3security.test.tsx +++ b/x-pack/plugins/stack_connectors/public/connector_types/d3security/d3security.test.tsx @@ -8,13 +8,15 @@ import { TypeRegistry } from '@kbn/triggers-actions-ui-plugin/public/application/type_registry'; import { registerConnectorTypes } from '..'; import { ActionTypeModel as ConnectorTypeModel } from '@kbn/triggers-actions-ui-plugin/public/types'; -import { registrationServicesMock } from '../../mocks'; +import { experimentalFeaturesMock, registrationServicesMock } from '../../mocks'; import { SUB_ACTION } from '../../../common/d3security/constants'; +import { ExperimentalFeaturesService } from '../../common/experimental_features_service'; const CONNECTOR_TYPE_ID = '.d3security'; let connectorTypeModel: ConnectorTypeModel; beforeAll(() => { const connectorTypeRegistry = new TypeRegistry(); + ExperimentalFeaturesService.init({ experimentalFeatures: experimentalFeaturesMock }); registerConnectorTypes({ connectorTypeRegistry, services: registrationServicesMock }); const getResult = connectorTypeRegistry.get(CONNECTOR_TYPE_ID); if (getResult !== null) { diff --git a/x-pack/plugins/stack_connectors/public/connector_types/email/email.test.tsx b/x-pack/plugins/stack_connectors/public/connector_types/email/email.test.tsx index 85921dbb6deef..34b141296b315 100644 --- a/x-pack/plugins/stack_connectors/public/connector_types/email/email.test.tsx +++ b/x-pack/plugins/stack_connectors/public/connector_types/email/email.test.tsx @@ -15,6 +15,8 @@ import { ValidateEmailAddressesOptions, MustacheInEmailRegExp, } from '@kbn/actions-plugin/common'; +import { experimentalFeaturesMock } from '../../mocks'; +import { ExperimentalFeaturesService } from '../../common/experimental_features_service'; const CONNECTOR_TYPE_ID = '.email'; let connectorTypeModel: ConnectorTypeModel; @@ -45,6 +47,7 @@ beforeEach(() => { }); beforeAll(() => { + ExperimentalFeaturesService.init({ experimentalFeatures: experimentalFeaturesMock }); const connectorTypeRegistry = new TypeRegistry(); registerConnectorTypes({ connectorTypeRegistry, services: RegistrationServices }); const getResult = connectorTypeRegistry.get(CONNECTOR_TYPE_ID); diff --git a/x-pack/plugins/stack_connectors/public/connector_types/es_index/es_index.test.tsx b/x-pack/plugins/stack_connectors/public/connector_types/es_index/es_index.test.tsx index f85f4e540e372..2f22adf45da44 100644 --- a/x-pack/plugins/stack_connectors/public/connector_types/es_index/es_index.test.tsx +++ b/x-pack/plugins/stack_connectors/public/connector_types/es_index/es_index.test.tsx @@ -8,13 +8,15 @@ import { TypeRegistry } from '@kbn/triggers-actions-ui-plugin/public/application/type_registry'; import { registerConnectorTypes } from '..'; import type { ActionTypeModel as ConnectorTypeModel } from '@kbn/triggers-actions-ui-plugin/public/types'; -import { registrationServicesMock } from '../../mocks'; +import { experimentalFeaturesMock, registrationServicesMock } from '../../mocks'; +import { ExperimentalFeaturesService } from '../../common/experimental_features_service'; const CONNECTOR_TYPE_ID = '.index'; let connectorTypeModel: ConnectorTypeModel; beforeAll(() => { const connectorTypeRegistry = new TypeRegistry(); + ExperimentalFeaturesService.init({ experimentalFeatures: experimentalFeaturesMock }); registerConnectorTypes({ connectorTypeRegistry, services: registrationServicesMock }); const getResult = connectorTypeRegistry.get(CONNECTOR_TYPE_ID); if (getResult !== null) { diff --git a/x-pack/plugins/stack_connectors/public/connector_types/index.ts b/x-pack/plugins/stack_connectors/public/connector_types/index.ts index 0c024870133dc..a2297dac9d6bf 100644 --- a/x-pack/plugins/stack_connectors/public/connector_types/index.ts +++ b/x-pack/plugins/stack_connectors/public/connector_types/index.ts @@ -29,6 +29,8 @@ import { getTorqConnectorType } from './torq'; import { getWebhookConnectorType } from './webhook'; import { getXmattersConnectorType } from './xmatters'; import { getD3SecurityConnectorType } from './d3security'; +import { ExperimentalFeaturesService } from '../common/experimental_features_service'; +import { getSentinelOneConnectorType } from './sentinelone'; export interface RegistrationServices { validateEmailAddresses: ( @@ -66,4 +68,8 @@ export function registerConnectorTypes({ connectorTypeRegistry.register(getTorqConnectorType()); connectorTypeRegistry.register(getTinesConnectorType()); connectorTypeRegistry.register(getD3SecurityConnectorType()); + + if (ExperimentalFeaturesService.get().sentinelOneConnectorOn) { + connectorTypeRegistry.register(getSentinelOneConnectorType()); + } } diff --git a/x-pack/plugins/stack_connectors/public/connector_types/jira/jira.test.tsx b/x-pack/plugins/stack_connectors/public/connector_types/jira/jira.test.tsx index 83401d691b3b3..ee01f2e21c26c 100644 --- a/x-pack/plugins/stack_connectors/public/connector_types/jira/jira.test.tsx +++ b/x-pack/plugins/stack_connectors/public/connector_types/jira/jira.test.tsx @@ -8,13 +8,15 @@ import { TypeRegistry } from '@kbn/triggers-actions-ui-plugin/public/application/type_registry'; import { registerConnectorTypes } from '..'; import type { ActionTypeModel as ConnectorTypeModel } from '@kbn/triggers-actions-ui-plugin/public/types'; -import { registrationServicesMock } from '../../mocks'; +import { experimentalFeaturesMock, registrationServicesMock } from '../../mocks'; +import { ExperimentalFeaturesService } from '../../common/experimental_features_service'; const CONNECTOR_TYPE_ID = '.jira'; let connectorTypeModel: ConnectorTypeModel; beforeAll(() => { const connectorTypeRegistry = new TypeRegistry(); + ExperimentalFeaturesService.init({ experimentalFeatures: experimentalFeaturesMock }); registerConnectorTypes({ connectorTypeRegistry, services: registrationServicesMock }); const getResult = connectorTypeRegistry.get(CONNECTOR_TYPE_ID); if (getResult !== null) { diff --git a/x-pack/plugins/stack_connectors/public/connector_types/openai/openai.test.tsx b/x-pack/plugins/stack_connectors/public/connector_types/openai/openai.test.tsx index 89a53c3327c28..1cb30b5a6505e 100644 --- a/x-pack/plugins/stack_connectors/public/connector_types/openai/openai.test.tsx +++ b/x-pack/plugins/stack_connectors/public/connector_types/openai/openai.test.tsx @@ -8,14 +8,16 @@ import { TypeRegistry } from '@kbn/triggers-actions-ui-plugin/public/application/type_registry'; import { registerConnectorTypes } from '..'; import type { ActionTypeModel } from '@kbn/triggers-actions-ui-plugin/public/types'; -import { registrationServicesMock } from '../../mocks'; +import { experimentalFeaturesMock, registrationServicesMock } from '../../mocks'; import { SUB_ACTION } from '../../../common/openai/constants'; +import { ExperimentalFeaturesService } from '../../common/experimental_features_service'; const ACTION_TYPE_ID = '.gen-ai'; let actionTypeModel: ActionTypeModel; beforeAll(() => { const connectorTypeRegistry = new TypeRegistry(); + ExperimentalFeaturesService.init({ experimentalFeatures: experimentalFeaturesMock }); registerConnectorTypes({ connectorTypeRegistry, services: registrationServicesMock }); const getResult = connectorTypeRegistry.get(ACTION_TYPE_ID); if (getResult !== null) { diff --git a/x-pack/plugins/stack_connectors/public/connector_types/opsgenie/model.test.tsx b/x-pack/plugins/stack_connectors/public/connector_types/opsgenie/model.test.tsx index 4dc91b501c36c..5bc13a0eb3a02 100644 --- a/x-pack/plugins/stack_connectors/public/connector_types/opsgenie/model.test.tsx +++ b/x-pack/plugins/stack_connectors/public/connector_types/opsgenie/model.test.tsx @@ -8,13 +8,15 @@ import { TypeRegistry } from '@kbn/triggers-actions-ui-plugin/public/application/type_registry'; import { registerConnectorTypes } from '..'; import type { ActionTypeModel as ConnectorTypeModel } from '@kbn/triggers-actions-ui-plugin/public/types'; -import { registrationServicesMock } from '../../mocks'; +import { experimentalFeaturesMock, registrationServicesMock } from '../../mocks'; import { OpsgenieConnectorTypeId, OpsgenieSubActions } from '../../../common'; +import { ExperimentalFeaturesService } from '../../common/experimental_features_service'; let connectorTypeModel: ConnectorTypeModel; beforeAll(() => { const connectorTypeRegistry = new TypeRegistry(); + ExperimentalFeaturesService.init({ experimentalFeatures: experimentalFeaturesMock }); registerConnectorTypes({ connectorTypeRegistry, services: registrationServicesMock }); const getResult = connectorTypeRegistry.get(OpsgenieConnectorTypeId); if (getResult !== null) { diff --git a/x-pack/plugins/stack_connectors/public/connector_types/pagerduty/pagerduty.test.tsx b/x-pack/plugins/stack_connectors/public/connector_types/pagerduty/pagerduty.test.tsx index 0464e37e78c3b..311d4bfac8679 100644 --- a/x-pack/plugins/stack_connectors/public/connector_types/pagerduty/pagerduty.test.tsx +++ b/x-pack/plugins/stack_connectors/public/connector_types/pagerduty/pagerduty.test.tsx @@ -8,13 +8,15 @@ import { TypeRegistry } from '@kbn/triggers-actions-ui-plugin/public/application/type_registry'; import { registerConnectorTypes } from '..'; import type { ActionTypeModel as ConnectorTypeModel } from '@kbn/triggers-actions-ui-plugin/public/types'; -import { registrationServicesMock } from '../../mocks'; +import { experimentalFeaturesMock, registrationServicesMock } from '../../mocks'; +import { ExperimentalFeaturesService } from '../../common/experimental_features_service'; const CONNECTOR_TYPE_ID = '.pagerduty'; let connectorTypeModel: ConnectorTypeModel; beforeAll(() => { const connectorTypeRegistry = new TypeRegistry(); + ExperimentalFeaturesService.init({ experimentalFeatures: experimentalFeaturesMock }); registerConnectorTypes({ connectorTypeRegistry, services: registrationServicesMock }); const getResult = connectorTypeRegistry.get(CONNECTOR_TYPE_ID); if (getResult !== null) { diff --git a/x-pack/plugins/stack_connectors/public/connector_types/resilient/resilient.test.tsx b/x-pack/plugins/stack_connectors/public/connector_types/resilient/resilient.test.tsx index f4aef9e8dc020..a462ad6dc2a53 100644 --- a/x-pack/plugins/stack_connectors/public/connector_types/resilient/resilient.test.tsx +++ b/x-pack/plugins/stack_connectors/public/connector_types/resilient/resilient.test.tsx @@ -8,13 +8,15 @@ import { TypeRegistry } from '@kbn/triggers-actions-ui-plugin/public/application/type_registry'; import { registerConnectorTypes } from '..'; import type { ActionTypeModel as ConnectorTypeModel } from '@kbn/triggers-actions-ui-plugin/public/types'; -import { registrationServicesMock } from '../../mocks'; +import { experimentalFeaturesMock, registrationServicesMock } from '../../mocks'; +import { ExperimentalFeaturesService } from '../../common/experimental_features_service'; const CONNECTOR_TYPE_ID = '.resilient'; let connectorTypeModel: ConnectorTypeModel; beforeAll(() => { const connectorTypeRegistry = new TypeRegistry(); + ExperimentalFeaturesService.init({ experimentalFeatures: experimentalFeaturesMock }); registerConnectorTypes({ connectorTypeRegistry, services: registrationServicesMock }); const getResult = connectorTypeRegistry.get(CONNECTOR_TYPE_ID); if (getResult !== null) { diff --git a/x-pack/plugins/stack_connectors/public/connector_types/server_log/server_log.test.tsx b/x-pack/plugins/stack_connectors/public/connector_types/server_log/server_log.test.tsx index 505079a858102..a8a775bebdafa 100644 --- a/x-pack/plugins/stack_connectors/public/connector_types/server_log/server_log.test.tsx +++ b/x-pack/plugins/stack_connectors/public/connector_types/server_log/server_log.test.tsx @@ -8,13 +8,15 @@ import { TypeRegistry } from '@kbn/triggers-actions-ui-plugin/public/application/type_registry'; import { registerConnectorTypes } from '..'; import type { ActionTypeModel as ConnectorTypeModel } from '@kbn/triggers-actions-ui-plugin/public/types'; -import { registrationServicesMock } from '../../mocks'; +import { experimentalFeaturesMock, registrationServicesMock } from '../../mocks'; +import { ExperimentalFeaturesService } from '../../common/experimental_features_service'; const CONNECTOR_TYPE_ID = '.server-log'; let connectorTypeModel: ConnectorTypeModel; beforeAll(() => { const connectorTypeRegistry = new TypeRegistry(); + ExperimentalFeaturesService.init({ experimentalFeatures: experimentalFeaturesMock }); registerConnectorTypes({ connectorTypeRegistry, services: registrationServicesMock }); const getResult = connectorTypeRegistry.get(CONNECTOR_TYPE_ID); if (getResult !== null) { diff --git a/x-pack/plugins/stack_connectors/public/connector_types/servicenow_itom/servicenow_itom.test.tsx b/x-pack/plugins/stack_connectors/public/connector_types/servicenow_itom/servicenow_itom.test.tsx index 2ebffea39da25..7673f4caf588e 100644 --- a/x-pack/plugins/stack_connectors/public/connector_types/servicenow_itom/servicenow_itom.test.tsx +++ b/x-pack/plugins/stack_connectors/public/connector_types/servicenow_itom/servicenow_itom.test.tsx @@ -8,13 +8,15 @@ import { TypeRegistry } from '@kbn/triggers-actions-ui-plugin/public/application/type_registry'; import { registerConnectorTypes } from '..'; import type { ActionTypeModel as ConnectorTypeModel } from '@kbn/triggers-actions-ui-plugin/public/types'; -import { registrationServicesMock } from '../../mocks'; +import { experimentalFeaturesMock, registrationServicesMock } from '../../mocks'; +import { ExperimentalFeaturesService } from '../../common/experimental_features_service'; const SERVICENOW_ITOM_CONNECTOR_TYPE_ID = '.servicenow-itom'; let connectorTypeRegistry: TypeRegistry; beforeAll(() => { connectorTypeRegistry = new TypeRegistry(); + ExperimentalFeaturesService.init({ experimentalFeatures: experimentalFeaturesMock }); registerConnectorTypes({ connectorTypeRegistry, services: registrationServicesMock }); }); diff --git a/x-pack/plugins/stack_connectors/public/connector_types/servicenow_itsm/servicenow_itsm.test.tsx b/x-pack/plugins/stack_connectors/public/connector_types/servicenow_itsm/servicenow_itsm.test.tsx index 1a2db4a4142f1..ea7497bde2837 100644 --- a/x-pack/plugins/stack_connectors/public/connector_types/servicenow_itsm/servicenow_itsm.test.tsx +++ b/x-pack/plugins/stack_connectors/public/connector_types/servicenow_itsm/servicenow_itsm.test.tsx @@ -8,13 +8,15 @@ import { TypeRegistry } from '@kbn/triggers-actions-ui-plugin/public/application/type_registry'; import { registerConnectorTypes } from '..'; import type { ActionTypeModel as ConnectorTypeModel } from '@kbn/triggers-actions-ui-plugin/public/types'; -import { registrationServicesMock } from '../../mocks'; +import { experimentalFeaturesMock, registrationServicesMock } from '../../mocks'; +import { ExperimentalFeaturesService } from '../../common/experimental_features_service'; const SERVICENOW_ITSM_CONNECTOR_TYPE_ID = '.servicenow'; let connectorTypeRegistry: TypeRegistry; beforeAll(() => { connectorTypeRegistry = new TypeRegistry(); + ExperimentalFeaturesService.init({ experimentalFeatures: experimentalFeaturesMock }); registerConnectorTypes({ connectorTypeRegistry, services: registrationServicesMock }); }); diff --git a/x-pack/plugins/stack_connectors/public/connector_types/servicenow_sir/servicenow_sir.test.tsx b/x-pack/plugins/stack_connectors/public/connector_types/servicenow_sir/servicenow_sir.test.tsx index 60ddf15b62dee..b2cfd79447ff8 100644 --- a/x-pack/plugins/stack_connectors/public/connector_types/servicenow_sir/servicenow_sir.test.tsx +++ b/x-pack/plugins/stack_connectors/public/connector_types/servicenow_sir/servicenow_sir.test.tsx @@ -8,13 +8,15 @@ import { TypeRegistry } from '@kbn/triggers-actions-ui-plugin/public/application/type_registry'; import { registerConnectorTypes } from '..'; import type { ActionTypeModel as ConnectorTypeModel } from '@kbn/triggers-actions-ui-plugin/public/types'; -import { registrationServicesMock } from '../../mocks'; +import { experimentalFeaturesMock, registrationServicesMock } from '../../mocks'; +import { ExperimentalFeaturesService } from '../../common/experimental_features_service'; const SERVICENOW_SIR_CONNECTOR_TYPE_ID = '.servicenow-sir'; let connectorTypeRegistry: TypeRegistry; beforeAll(() => { connectorTypeRegistry = new TypeRegistry(); + ExperimentalFeaturesService.init({ experimentalFeatures: experimentalFeaturesMock }); registerConnectorTypes({ connectorTypeRegistry, services: registrationServicesMock }); }); diff --git a/x-pack/plugins/stack_connectors/public/connector_types/slack/slack.test.tsx b/x-pack/plugins/stack_connectors/public/connector_types/slack/slack.test.tsx index 40ff4a6240ba3..0dc0bad57b4b5 100644 --- a/x-pack/plugins/stack_connectors/public/connector_types/slack/slack.test.tsx +++ b/x-pack/plugins/stack_connectors/public/connector_types/slack/slack.test.tsx @@ -8,13 +8,15 @@ import { TypeRegistry } from '@kbn/triggers-actions-ui-plugin/public/application/type_registry'; import { registerConnectorTypes } from '..'; import type { ActionTypeModel as ConnectorTypeModel } from '@kbn/triggers-actions-ui-plugin/public/types'; -import { registrationServicesMock } from '../../mocks'; +import { experimentalFeaturesMock, registrationServicesMock } from '../../mocks'; +import { ExperimentalFeaturesService } from '../../common/experimental_features_service'; const CONNECTOR_TYPE_ID = '.slack'; let connectorTypeModel: ConnectorTypeModel; beforeAll(async () => { const connectorTypeRegistry = new TypeRegistry(); + ExperimentalFeaturesService.init({ experimentalFeatures: experimentalFeaturesMock }); registerConnectorTypes({ connectorTypeRegistry, services: registrationServicesMock }); const getResult = connectorTypeRegistry.get(CONNECTOR_TYPE_ID); if (getResult !== null) { diff --git a/x-pack/plugins/stack_connectors/public/connector_types/slack_api/slack_api.test.tsx b/x-pack/plugins/stack_connectors/public/connector_types/slack_api/slack_api.test.tsx index d8c49ef12d9b5..33fad281654e8 100644 --- a/x-pack/plugins/stack_connectors/public/connector_types/slack_api/slack_api.test.tsx +++ b/x-pack/plugins/stack_connectors/public/connector_types/slack_api/slack_api.test.tsx @@ -8,13 +8,15 @@ import { TypeRegistry } from '@kbn/triggers-actions-ui-plugin/public/application/type_registry'; import type { ActionTypeModel as ConnectorTypeModel } from '@kbn/triggers-actions-ui-plugin/public/types'; import { registerConnectorTypes } from '..'; -import { registrationServicesMock } from '../../mocks'; +import { experimentalFeaturesMock, registrationServicesMock } from '../../mocks'; import { SLACK_API_CONNECTOR_ID } from '../../../common/slack_api/constants'; +import { ExperimentalFeaturesService } from '../../common/experimental_features_service'; let connectorTypeModel: ConnectorTypeModel; beforeAll(async () => { const connectorTypeRegistry = new TypeRegistry(); + ExperimentalFeaturesService.init({ experimentalFeatures: experimentalFeaturesMock }); registerConnectorTypes({ connectorTypeRegistry, services: registrationServicesMock }); const getResult = connectorTypeRegistry.get(SLACK_API_CONNECTOR_ID); if (getResult !== null) { diff --git a/x-pack/plugins/stack_connectors/public/connector_types/swimlane/swimlane.test.tsx b/x-pack/plugins/stack_connectors/public/connector_types/swimlane/swimlane.test.tsx index 18da58e6b9bf0..5b0cad26c394f 100644 --- a/x-pack/plugins/stack_connectors/public/connector_types/swimlane/swimlane.test.tsx +++ b/x-pack/plugins/stack_connectors/public/connector_types/swimlane/swimlane.test.tsx @@ -8,13 +8,15 @@ import { TypeRegistry } from '@kbn/triggers-actions-ui-plugin/public/application/type_registry'; import { registerConnectorTypes } from '..'; import type { ActionTypeModel as ConnectorTypeModel } from '@kbn/triggers-actions-ui-plugin/public/types'; -import { registrationServicesMock } from '../../mocks'; +import { experimentalFeaturesMock, registrationServicesMock } from '../../mocks'; +import { ExperimentalFeaturesService } from '../../common/experimental_features_service'; const CONNECTOR_TYPE_ID = '.swimlane'; let connectorTypeModel: ConnectorTypeModel; beforeAll(() => { const connectorTypeRegistry = new TypeRegistry(); + ExperimentalFeaturesService.init({ experimentalFeatures: experimentalFeaturesMock }); registerConnectorTypes({ connectorTypeRegistry, services: registrationServicesMock }); const getResult = connectorTypeRegistry.get(CONNECTOR_TYPE_ID); if (getResult !== null) { diff --git a/x-pack/plugins/stack_connectors/public/connector_types/teams/teams.test.tsx b/x-pack/plugins/stack_connectors/public/connector_types/teams/teams.test.tsx index d7ceabda2be02..f3ce70b74f6ef 100644 --- a/x-pack/plugins/stack_connectors/public/connector_types/teams/teams.test.tsx +++ b/x-pack/plugins/stack_connectors/public/connector_types/teams/teams.test.tsx @@ -8,13 +8,15 @@ import { TypeRegistry } from '@kbn/triggers-actions-ui-plugin/public/application/type_registry'; import { registerConnectorTypes } from '..'; import type { ActionTypeModel as ConnectorTypeModel } from '@kbn/triggers-actions-ui-plugin/public/types'; -import { registrationServicesMock } from '../../mocks'; +import { experimentalFeaturesMock, registrationServicesMock } from '../../mocks'; +import { ExperimentalFeaturesService } from '../../common/experimental_features_service'; const CONNECTOR_TYPE_ID = '.teams'; let connectorTypeModel: ConnectorTypeModel; beforeAll(async () => { const connectorTypeRegistry = new TypeRegistry(); + ExperimentalFeaturesService.init({ experimentalFeatures: experimentalFeaturesMock }); registerConnectorTypes({ connectorTypeRegistry, services: registrationServicesMock }); const getResult = connectorTypeRegistry.get(CONNECTOR_TYPE_ID); if (getResult !== null) { diff --git a/x-pack/plugins/stack_connectors/public/connector_types/tines/tines.test.ts b/x-pack/plugins/stack_connectors/public/connector_types/tines/tines.test.ts index 0306967176012..be647b3f4a704 100644 --- a/x-pack/plugins/stack_connectors/public/connector_types/tines/tines.test.ts +++ b/x-pack/plugins/stack_connectors/public/connector_types/tines/tines.test.ts @@ -8,9 +8,10 @@ import { TypeRegistry } from '@kbn/triggers-actions-ui-plugin/public/application/type_registry'; import { registerConnectorTypes } from '..'; import type { ActionTypeModel as ConnectorTypeModel } from '@kbn/triggers-actions-ui-plugin/public/types'; -import { registrationServicesMock } from '../../mocks'; +import { experimentalFeaturesMock, registrationServicesMock } from '../../mocks'; import { TinesExecuteActionParams } from './types'; import { SUB_ACTION, TINES_CONNECTOR_ID, TINES_TITLE } from '../../../common/tines/constants'; +import { ExperimentalFeaturesService } from '../../common/experimental_features_service'; let actionTypeModel: ConnectorTypeModel; @@ -35,6 +36,7 @@ const defaultValidationErrors = { beforeAll(() => { const connectorTypeRegistry = new TypeRegistry(); + ExperimentalFeaturesService.init({ experimentalFeatures: experimentalFeaturesMock }); registerConnectorTypes({ connectorTypeRegistry, services: registrationServicesMock }); const getResult = connectorTypeRegistry.get(TINES_CONNECTOR_ID); if (getResult !== null) { diff --git a/x-pack/plugins/stack_connectors/public/connector_types/torq/torq.test.tsx b/x-pack/plugins/stack_connectors/public/connector_types/torq/torq.test.tsx index 09bb5a210a333..2ce9f48ae1731 100644 --- a/x-pack/plugins/stack_connectors/public/connector_types/torq/torq.test.tsx +++ b/x-pack/plugins/stack_connectors/public/connector_types/torq/torq.test.tsx @@ -8,13 +8,15 @@ import { ActionTypeModel } from '@kbn/triggers-actions-ui-plugin/public'; import { TypeRegistry } from '@kbn/triggers-actions-ui-plugin/public/application/type_registry'; import { registerConnectorTypes } from '..'; -import { registrationServicesMock } from '../../mocks'; +import { experimentalFeaturesMock, registrationServicesMock } from '../../mocks'; +import { ExperimentalFeaturesService } from '../../common/experimental_features_service'; const ACTION_TYPE_ID = '.torq'; let actionTypeModel: ActionTypeModel; beforeAll(() => { const connectorTypeRegistry = new TypeRegistry(); + ExperimentalFeaturesService.init({ experimentalFeatures: experimentalFeaturesMock }); registerConnectorTypes({ connectorTypeRegistry, services: registrationServicesMock }); const getResult = connectorTypeRegistry.get(ACTION_TYPE_ID); if (getResult !== null) { diff --git a/x-pack/plugins/stack_connectors/public/connector_types/webhook/webhook.test.tsx b/x-pack/plugins/stack_connectors/public/connector_types/webhook/webhook.test.tsx index 2f345031b25c7..62052bb56171f 100644 --- a/x-pack/plugins/stack_connectors/public/connector_types/webhook/webhook.test.tsx +++ b/x-pack/plugins/stack_connectors/public/connector_types/webhook/webhook.test.tsx @@ -8,13 +8,15 @@ import { TypeRegistry } from '@kbn/triggers-actions-ui-plugin/public/application/type_registry'; import { registerConnectorTypes } from '..'; import type { ActionTypeModel as ConnectorTypeModel } from '@kbn/triggers-actions-ui-plugin/public/types'; -import { registrationServicesMock } from '../../mocks'; +import { experimentalFeaturesMock, registrationServicesMock } from '../../mocks'; +import { ExperimentalFeaturesService } from '../../common/experimental_features_service'; const CONNECTOR_TYPE_ID = '.webhook'; let connectorTypeModel: ConnectorTypeModel; beforeAll(() => { const connectorTypeRegistry = new TypeRegistry(); + ExperimentalFeaturesService.init({ experimentalFeatures: experimentalFeaturesMock }); registerConnectorTypes({ connectorTypeRegistry, services: registrationServicesMock }); const getResult = connectorTypeRegistry.get(CONNECTOR_TYPE_ID); if (getResult !== null) { diff --git a/x-pack/plugins/stack_connectors/public/connector_types/xmatters/xmatters.test.tsx b/x-pack/plugins/stack_connectors/public/connector_types/xmatters/xmatters.test.tsx index e2e03465d57b2..a38ea1d8eb41c 100644 --- a/x-pack/plugins/stack_connectors/public/connector_types/xmatters/xmatters.test.tsx +++ b/x-pack/plugins/stack_connectors/public/connector_types/xmatters/xmatters.test.tsx @@ -8,13 +8,15 @@ import { TypeRegistry } from '@kbn/triggers-actions-ui-plugin/public/application/type_registry'; import { registerConnectorTypes } from '..'; import type { ActionTypeModel as ConnectorTypeModel } from '@kbn/triggers-actions-ui-plugin/public/types'; -import { registrationServicesMock } from '../../mocks'; +import { experimentalFeaturesMock, registrationServicesMock } from '../../mocks'; +import { ExperimentalFeaturesService } from '../../common/experimental_features_service'; const CONNECTOR_TYPE_ID = '.xmatters'; let connectorTypeModel: ConnectorTypeModel; beforeAll(() => { const connectorTypeRegistry = new TypeRegistry(); + ExperimentalFeaturesService.init({ experimentalFeatures: experimentalFeaturesMock }); registerConnectorTypes({ connectorTypeRegistry, services: registrationServicesMock }); const getResult = connectorTypeRegistry.get(CONNECTOR_TYPE_ID); if (getResult !== null) { diff --git a/x-pack/plugins/stack_connectors/public/mocks.ts b/x-pack/plugins/stack_connectors/public/mocks.ts index 9e087c3cee6eb..93a81d93730d9 100644 --- a/x-pack/plugins/stack_connectors/public/mocks.ts +++ b/x-pack/plugins/stack_connectors/public/mocks.ts @@ -7,9 +7,12 @@ import { ValidatedEmail } from '@kbn/actions-plugin/common'; import { RegistrationServices } from './connector_types'; +import { allowedExperimentalValues, ExperimentalFeatures } from '../common/experimental_features'; function validateEmailAddresses(addresses: string[]): ValidatedEmail[] { return addresses.map((address) => ({ address, valid: true })); } export const registrationServicesMock: RegistrationServices = { validateEmailAddresses }; + +export const experimentalFeaturesMock: ExperimentalFeatures = allowedExperimentalValues; diff --git a/x-pack/plugins/stack_connectors/public/plugin.ts b/x-pack/plugins/stack_connectors/public/plugin.ts index 3c153d0de2573..4946268506fdf 100644 --- a/x-pack/plugins/stack_connectors/public/plugin.ts +++ b/x-pack/plugins/stack_connectors/public/plugin.ts @@ -35,13 +35,13 @@ export class StackConnectorsPublicPlugin this.experimentalFeatures = parseExperimentalConfigValue(this.config.enableExperimental || []); } public setup(core: CoreSetup, { triggersActionsUi, actions }: StackConnectorsPublicSetupDeps) { + ExperimentalFeaturesService.init({ experimentalFeatures: this.experimentalFeatures }); registerConnectorTypes({ connectorTypeRegistry: triggersActionsUi.actionTypeRegistry, services: { validateEmailAddresses: actions.validateEmailAddresses, }, }); - ExperimentalFeaturesService.init({ experimentalFeatures: this.experimentalFeatures }); } public start() {} diff --git a/x-pack/plugins/stack_connectors/server/connector_types/index.test.ts b/x-pack/plugins/stack_connectors/server/connector_types/index.test.ts index c2aaf7c7ea5d8..428e4a4c92835 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/index.test.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/index.test.ts @@ -5,6 +5,7 @@ * 2.0. */ +import { allowedExperimentalValues } from '../../common/experimental_features'; import { registerConnectorTypes } from '.'; import { actionsMock } from '@kbn/actions-plugin/server/mocks'; @@ -31,6 +32,7 @@ describe('registers connectors', () => { test('calls registerType with expected connector types', () => { registerConnectorTypes({ actions: mockedActions, + experimentalFeatures: allowedExperimentalValues, }); ACTION_TYPE_IDS.forEach((id) => expect(mockedActions.registerType).toHaveBeenCalledWith( diff --git a/x-pack/plugins/stack_connectors/server/connector_types/index.ts b/x-pack/plugins/stack_connectors/server/connector_types/index.ts index 0117a9d1a7a2a..540f2746516b5 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/index.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/index.ts @@ -31,6 +31,8 @@ import { getConnectorType as getD3SecurityConnectorType } from './d3security'; import { getOpsgenieConnectorType } from './opsgenie'; import type { ActionParamsType as ServiceNowITSMActionParams } from './servicenow_itsm'; import type { ActionParamsType as ServiceNowSIRActionParams } from './servicenow_sir'; +import { getSentinelOneConnectorType } from './sentinelone'; +import { ExperimentalFeatures } from '../../common/experimental_features'; export { ConnectorTypeId as CasesWebhookConnectorTypeId } from './cases_webhook'; export type { ActionParamsType as CasesWebhookActionParams } from './cases_webhook'; @@ -77,9 +79,11 @@ export { getConnectorType as getSwimlaneConnectorType } from './swimlane'; export function registerConnectorTypes({ actions, publicBaseUrl, + experimentalFeatures, }: { actions: ActionsPluginSetupContract; publicBaseUrl?: string; + experimentalFeatures: ExperimentalFeatures; }) { actions.registerType(getEmailConnectorType({ publicBaseUrl })); actions.registerType(getIndexConnectorType()); @@ -104,4 +108,8 @@ export function registerConnectorTypes({ actions.registerSubActionConnectorType(getOpenAIConnectorType()); actions.registerSubActionConnectorType(getBedrockConnectorType()); actions.registerSubActionConnectorType(getD3SecurityConnectorType()); + + if (experimentalFeatures.sentinelOneConnectorOn) { + actions.registerSubActionConnectorType(getSentinelOneConnectorType()); + } } diff --git a/x-pack/plugins/stack_connectors/server/plugin.ts b/x-pack/plugins/stack_connectors/server/plugin.ts index 8e74b3c88395c..aee84d963043d 100644 --- a/x-pack/plugins/stack_connectors/server/plugin.ts +++ b/x-pack/plugins/stack_connectors/server/plugin.ts @@ -9,6 +9,11 @@ import { PluginInitializerContext, Plugin, CoreSetup, Logger } from '@kbn/core/s import { PluginSetupContract as ActionsPluginSetupContract } from '@kbn/actions-plugin/server'; import { registerConnectorTypes } from './connector_types'; import { validSlackApiChannelsRoute, getWellKnownEmailServiceRoute } from './routes'; +import { + ExperimentalFeatures, + parseExperimentalConfigValue, +} from '../common/experimental_features'; +import { StackConnectorsConfigType } from '../common/types'; export interface ConnectorsPluginsSetup { actions: ActionsPluginSetupContract; } @@ -19,9 +24,13 @@ export interface ConnectorsPluginsStart { export class StackConnectorsPlugin implements Plugin { private readonly logger: Logger; + private config: StackConnectorsConfigType; + readonly experimentalFeatures: ExperimentalFeatures; constructor(context: PluginInitializerContext) { this.logger = context.logger.get(); + this.config = context.config.get(); + this.experimentalFeatures = parseExperimentalConfigValue(this.config.enableExperimental || []); } public setup(core: CoreSetup, plugins: ConnectorsPluginsSetup) { @@ -34,6 +43,7 @@ export class StackConnectorsPlugin implements Plugin { registerConnectorTypes({ actions, publicBaseUrl: core.http.basePath.publicBaseUrl, + experimentalFeatures: this.experimentalFeatures, }); } diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json index b32b2d085fb78..5a073b4ae0b4c 100644 --- a/x-pack/plugins/translations/translations/fr-FR.json +++ b/x-pack/plugins/translations/translations/fr-FR.json @@ -4728,9 +4728,6 @@ "kibana-react.dualRangeControl.minInputAriaLabel": "Minimum de la plage", "kibana-react.dualRangeControl.mustSetBothErrorMessage": "Les valeurs inférieure et supérieure doivent être définies.", "kibana-react.dualRangeControl.upperValidErrorMessage": "La valeur supérieure doit être supérieure ou égale à la valeur inférieure.", - "kibana-react.exitFullScreenButton.exitFullScreenModeButtonAriaLabel": "Quitter le mode Plein écran", - "kibana-react.exitFullScreenButton.exitFullScreenModeButtonText": "Quitter le plein écran", - "kibana-react.exitFullScreenButton.fullScreenModeDescription": "En mode Plein écran, appuyez sur Échap pour quitter.", "kibana-react.kbnOverviewPageHeader.addIntegrationsButtonLabel": "Ajouter des intégrations", "kibana-react.kbnOverviewPageHeader.devToolsButtonLabel": "Outils de développement", "kibana-react.kbnOverviewPageHeader.stackManagementButtonLabel": "Gérer", @@ -16283,7 +16280,6 @@ "xpack.fleet.fleetServerSetup.cloudDeploymentLink": "Modifier le déploiement", "xpack.fleet.fleetServerSetup.cloudSetupTitle": "Activer un serveur Fleet", "xpack.fleet.fleetServerSetup.errorAddingFleetServerHostTitle": "Erreur lors de l'ajout de l'hôte du serveur Fleet", - "xpack.fleet.fleetServerSetup.errorGeneratingTokenTitleText": "Erreur lors de la génération du jeton", "xpack.fleet.fleetServerSetup.errorRefreshingFleetServerStatus": "Erreur lors de l'actualisation du statut du serveur Fleet", "xpack.fleet.fleetServerSetup.fleetServerHostsInputPlaceholder": "Indiquer l’URL de l’hôte", "xpack.fleet.fleetServerSetup.fleetServerHostsLabel": "Hôtes du serveur Fleet", @@ -18630,21 +18626,6 @@ "xpack.infra.infra.nodeDetails.apmTabLabel": "APM", "xpack.infra.infra.nodeDetails.openAsPage": "Ouvrir en tant que page", "xpack.infra.inventory.alerting.groupActionVariableDescription": "Nom des données de reporting du groupe", - "xpack.infra.inventoryModel.container.displayName": "Conteneurs Docker", - "xpack.infra.inventoryModel.container.singularDisplayName": "Conteneur Docker", - "xpack.infra.inventoryModel.host.displayName": "Hôtes", - "xpack.infra.inventoryModel.pod.displayName": "Pods Kubernetes", - "xpack.infra.inventoryModels.awsEC2.displayName": "Instances EC2", - "xpack.infra.inventoryModels.awsEC2.singularDisplayName": "Instance EC2", - "xpack.infra.inventoryModels.awsRDS.displayName": "Bases de données RDS", - "xpack.infra.inventoryModels.awsRDS.singularDisplayName": "Base de données RDS", - "xpack.infra.inventoryModels.awsS3.displayName": "Compartiments S3", - "xpack.infra.inventoryModels.awsS3.singularDisplayName": "Compartiment S3", - "xpack.infra.inventoryModels.awsSQS.displayName": "Files d'attente SQS", - "xpack.infra.inventoryModels.awsSQS.singularDisplayName": "File d'attente SQS", - "xpack.infra.inventoryModels.findInventoryModel.error": "Le modèle d'inventaire que vous recherchez n'existe pas", - "xpack.infra.inventoryModels.host.singularDisplayName": "Hôte", - "xpack.infra.inventoryModels.pod.singularDisplayName": "Pod Kubernetes", "xpack.infra.inventoryTimeline.checkNewDataButtonLabel": "Rechercher de nouvelles données", "xpack.infra.inventoryTimeline.errorTitle": "Impossible d'afficher les données historiques.", "xpack.infra.inventoryTimeline.legend.anomalyLabel": "Anomalie détectée", @@ -19140,31 +19121,6 @@ "xpack.infra.metricsExplorer.noMetrics.title": "Indicateur manquant", "xpack.infra.metricsExplorer.openInTSVB": "Ouvrir dans Visualize", "xpack.infra.metricsHeaderAddDataButtonLabel": "Ajouter des données", - "xpack.infra.metricsTable.container.averageCpuUsagePercentColumnHeader": "Utilisation CPU (moy.)", - "xpack.infra.metricsTable.container.averageMemoryUsageMegabytesColumnHeader": "Utilisation de la mémoire (moy.)", - "xpack.infra.metricsTable.container.idColumnHeader": "Id", - "xpack.infra.metricsTable.container.paginationAriaLabel": "Pagination des indicateurs de conteneur", - "xpack.infra.metricsTable.container.tableCaption": "Indicateurs d’infrastructure pour les conteneurs", - "xpack.infra.metricsTable.emptyIndicesPromptQueryHintDescription": "Essayez de rechercher une autre combinaison de termes.", - "xpack.infra.metricsTable.emptyIndicesPromptQueryHintTitle": "Modifiez la requête.", - "xpack.infra.metricsTable.emptyIndicesPromptTimeRangeHintDescription": "Essayez de rechercher sur une période plus longue.", - "xpack.infra.metricsTable.emptyIndicesPromptTimeRangeHintTitle": "Étendre la plage temporelle", - "xpack.infra.metricsTable.emptyIndicesPromptTitle": "Aucun résultat ne correspond à vos critères de recherche.", - "xpack.infra.metricsTable.host.averageCpuUsagePercentColumnHeader": "Utilisation CPU (moy.)", - "xpack.infra.metricsTable.host.averageMemoryUsagePercentColumnHeader": "Utilisation de la mémoire (moy.)", - "xpack.infra.metricsTable.host.CpuCountColumnHeader": "Nombre de processeurs", - "xpack.infra.metricsTable.host.nameColumnHeader": "Nom", - "xpack.infra.metricsTable.host.paginationAriaLabel": "Pagination des indicateurs de l’hôte", - "xpack.infra.metricsTable.host.tableCaption": "Indicateurs d’infrastructure pour les hôtes", - "xpack.infra.metricsTable.host.totalMemoryMegabytesColumnHeader": "Total de la mémoire", - "xpack.infra.metricsTable.loadingContentTitle": "Chargement des indicateurs", - "xpack.infra.metricsTable.noResultsIllustrationAlternativeText": "Une loupe avec un point d'exclamation", - "xpack.infra.metricsTable.numberCell.metricNotAvailableLabel": "S. O.", - "xpack.infra.metricsTable.pod.averageCpuUsagePercentColumnHeader": "Utilisation CPU (moy.)", - "xpack.infra.metricsTable.pod.averageMemoryUsageMegabytesColumnHeader": "Utilisation de la mémoire (moy.)", - "xpack.infra.metricsTable.pod.nameColumnHeader": "Nom", - "xpack.infra.metricsTable.pod.paginationAriaLabel": "Pagination des indicateurs du pod", - "xpack.infra.metricsTable.pod.tableCaption": "Indicateurs d’infrastructure pour les pods", "xpack.infra.ml.anomalyDetectionButton": "Détection des anomalies", "xpack.infra.ml.anomalyFlyout.actions.openActionMenu": "Ouvrir", "xpack.infra.ml.anomalyFlyout.actions.openInAnomalyExplorer": "Ouvrir dans Anomaly Explorer", diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 7a8949da3a233..27b287f489a85 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -4744,9 +4744,6 @@ "kibana-react.dualRangeControl.minInputAriaLabel": "範囲最小", "kibana-react.dualRangeControl.mustSetBothErrorMessage": "下と上の値の両方を設定する必要があります", "kibana-react.dualRangeControl.upperValidErrorMessage": "上の値は下の値以上でなければなりません", - "kibana-react.exitFullScreenButton.exitFullScreenModeButtonAriaLabel": "全画面モードを終了", - "kibana-react.exitFullScreenButton.exitFullScreenModeButtonText": "全画面を終了", - "kibana-react.exitFullScreenButton.fullScreenModeDescription": "ESC キーで全画面モードを終了します。", "kibana-react.kbnOverviewPageHeader.addIntegrationsButtonLabel": "統合の追加", "kibana-react.kbnOverviewPageHeader.devToolsButtonLabel": "開発ツール", "kibana-react.kbnOverviewPageHeader.stackManagementButtonLabel": "管理", @@ -16297,7 +16294,6 @@ "xpack.fleet.fleetServerSetup.cloudDeploymentLink": "デプロイを編集", "xpack.fleet.fleetServerSetup.cloudSetupTitle": "Fleetサーバーを有効にする", "xpack.fleet.fleetServerSetup.errorAddingFleetServerHostTitle": "Fleetサーバーホストの追加エラー", - "xpack.fleet.fleetServerSetup.errorGeneratingTokenTitleText": "トークン生成エラー", "xpack.fleet.fleetServerSetup.errorRefreshingFleetServerStatus": "Fleetサーバーステータスの更新エラー", "xpack.fleet.fleetServerSetup.fleetServerHostsInputPlaceholder": "ホストURLを指定", "xpack.fleet.fleetServerSetup.fleetServerHostsLabel": "Fleetサーバーホスト", @@ -18644,21 +18640,6 @@ "xpack.infra.infra.nodeDetails.apmTabLabel": "APM", "xpack.infra.infra.nodeDetails.openAsPage": "ページとして開く", "xpack.infra.inventory.alerting.groupActionVariableDescription": "データを報告するグループの名前", - "xpack.infra.inventoryModel.container.displayName": "Dockerコンテナー", - "xpack.infra.inventoryModel.container.singularDisplayName": "Docker コンテナー", - "xpack.infra.inventoryModel.host.displayName": "ホスト", - "xpack.infra.inventoryModel.pod.displayName": "Kubernetesポッド", - "xpack.infra.inventoryModels.awsEC2.displayName": "EC2インスタンス", - "xpack.infra.inventoryModels.awsEC2.singularDisplayName": "EC2 インスタンス", - "xpack.infra.inventoryModels.awsRDS.displayName": "RDSデータベース", - "xpack.infra.inventoryModels.awsRDS.singularDisplayName": "RDS データベース", - "xpack.infra.inventoryModels.awsS3.displayName": "S3バケット", - "xpack.infra.inventoryModels.awsS3.singularDisplayName": "S3 バケット", - "xpack.infra.inventoryModels.awsSQS.displayName": "SQSキュー", - "xpack.infra.inventoryModels.awsSQS.singularDisplayName": "SQS キュー", - "xpack.infra.inventoryModels.findInventoryModel.error": "検索しようとしたインベントリモデルは存在しません", - "xpack.infra.inventoryModels.host.singularDisplayName": "ホスト", - "xpack.infra.inventoryModels.pod.singularDisplayName": "Kubernetes ポッド", "xpack.infra.inventoryTimeline.checkNewDataButtonLabel": "新規データを確認", "xpack.infra.inventoryTimeline.errorTitle": "履歴データを表示できません。", "xpack.infra.inventoryTimeline.legend.anomalyLabel": "異常が検知されました", @@ -19154,31 +19135,6 @@ "xpack.infra.metricsExplorer.noMetrics.title": "不足しているメトリック", "xpack.infra.metricsExplorer.openInTSVB": "ビジュアライザーで開く", "xpack.infra.metricsHeaderAddDataButtonLabel": "データの追加", - "xpack.infra.metricsTable.container.averageCpuUsagePercentColumnHeader": "CPU使用状況(平均)", - "xpack.infra.metricsTable.container.averageMemoryUsageMegabytesColumnHeader": "メモリー使用状況(平均)", - "xpack.infra.metricsTable.container.idColumnHeader": "Id", - "xpack.infra.metricsTable.container.paginationAriaLabel": "コンテナーメトリックページネーション", - "xpack.infra.metricsTable.container.tableCaption": "コンテナーのインフラストラクチャーメトリック", - "xpack.infra.metricsTable.emptyIndicesPromptQueryHintDescription": "別の用語の組み合わせを検索してください。", - "xpack.infra.metricsTable.emptyIndicesPromptQueryHintTitle": "クエリを調整", - "xpack.infra.metricsTable.emptyIndicesPromptTimeRangeHintDescription": "期間を長くして検索を試してください。", - "xpack.infra.metricsTable.emptyIndicesPromptTimeRangeHintTitle": "時間範囲を拡大", - "xpack.infra.metricsTable.emptyIndicesPromptTitle": "検索条件と一致する結果がありません。", - "xpack.infra.metricsTable.host.averageCpuUsagePercentColumnHeader": "CPU使用状況(平均)", - "xpack.infra.metricsTable.host.averageMemoryUsagePercentColumnHeader": "メモリー使用状況(平均)", - "xpack.infra.metricsTable.host.CpuCountColumnHeader": "CPU数", - "xpack.infra.metricsTable.host.nameColumnHeader": "名前", - "xpack.infra.metricsTable.host.paginationAriaLabel": "ホストメトリックページネーション", - "xpack.infra.metricsTable.host.tableCaption": "ホストのインフラストラクチャーメトリック", - "xpack.infra.metricsTable.host.totalMemoryMegabytesColumnHeader": "メモリ合計", - "xpack.infra.metricsTable.loadingContentTitle": "メトリックを読み込んでいます", - "xpack.infra.metricsTable.noResultsIllustrationAlternativeText": "感嘆符が付いた虫眼鏡", - "xpack.infra.metricsTable.numberCell.metricNotAvailableLabel": "N/A", - "xpack.infra.metricsTable.pod.averageCpuUsagePercentColumnHeader": "CPU使用状況(平均)", - "xpack.infra.metricsTable.pod.averageMemoryUsageMegabytesColumnHeader": "メモリー使用状況(平均)", - "xpack.infra.metricsTable.pod.nameColumnHeader": "名前", - "xpack.infra.metricsTable.pod.paginationAriaLabel": "ポッドメトリックページネーション", - "xpack.infra.metricsTable.pod.tableCaption": "ポッドのインフラストラクチャーメトリック", "xpack.infra.ml.anomalyDetectionButton": "異常検知", "xpack.infra.ml.anomalyFlyout.actions.openActionMenu": "開く", "xpack.infra.ml.anomalyFlyout.actions.openInAnomalyExplorer": "異常エクスプローラーで開く", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 21fddc2d98547..e7e7a54f7f5a2 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -4743,9 +4743,6 @@ "kibana-react.dualRangeControl.minInputAriaLabel": "范围最小值", "kibana-react.dualRangeControl.mustSetBothErrorMessage": "下限值和上限值都须设置", "kibana-react.dualRangeControl.upperValidErrorMessage": "上限值必须大于或等于下限值", - "kibana-react.exitFullScreenButton.exitFullScreenModeButtonAriaLabel": "退出全屏模式", - "kibana-react.exitFullScreenButton.exitFullScreenModeButtonText": "退出全屏", - "kibana-react.exitFullScreenButton.fullScreenModeDescription": "在全屏模式下,按 ESC 键可退出。", "kibana-react.kbnOverviewPageHeader.addIntegrationsButtonLabel": "添加集成", "kibana-react.kbnOverviewPageHeader.devToolsButtonLabel": "开发工具", "kibana-react.kbnOverviewPageHeader.stackManagementButtonLabel": "管理", @@ -16297,7 +16294,6 @@ "xpack.fleet.fleetServerSetup.cloudDeploymentLink": "编辑部署", "xpack.fleet.fleetServerSetup.cloudSetupTitle": "启用 Fleet 服务器", "xpack.fleet.fleetServerSetup.errorAddingFleetServerHostTitle": "添加 Fleet 服务器主机时出错", - "xpack.fleet.fleetServerSetup.errorGeneratingTokenTitleText": "生成令牌时出错", "xpack.fleet.fleetServerSetup.errorRefreshingFleetServerStatus": "刷新 Fleet 服务器状态时出错", "xpack.fleet.fleetServerSetup.fleetServerHostsInputPlaceholder": "指定主机 URL", "xpack.fleet.fleetServerSetup.fleetServerHostsLabel": "Fleet 服务器主机", @@ -18644,21 +18640,6 @@ "xpack.infra.infra.nodeDetails.apmTabLabel": "APM", "xpack.infra.infra.nodeDetails.openAsPage": "以页面形式打开", "xpack.infra.inventory.alerting.groupActionVariableDescription": "报告数据的组名称", - "xpack.infra.inventoryModel.container.displayName": "Docker 容器", - "xpack.infra.inventoryModel.container.singularDisplayName": "Docker 容器", - "xpack.infra.inventoryModel.host.displayName": "主机", - "xpack.infra.inventoryModel.pod.displayName": "Kubernetes Pod", - "xpack.infra.inventoryModels.awsEC2.displayName": "EC2 实例", - "xpack.infra.inventoryModels.awsEC2.singularDisplayName": "EC2 实例", - "xpack.infra.inventoryModels.awsRDS.displayName": "RDS 数据库", - "xpack.infra.inventoryModels.awsRDS.singularDisplayName": "RDS 数据库", - "xpack.infra.inventoryModels.awsS3.displayName": "S3 存储桶", - "xpack.infra.inventoryModels.awsS3.singularDisplayName": "S3 存储桶", - "xpack.infra.inventoryModels.awsSQS.displayName": "SQS 队列", - "xpack.infra.inventoryModels.awsSQS.singularDisplayName": "SQS 队列", - "xpack.infra.inventoryModels.findInventoryModel.error": "您尝试查找的库存模型不存在", - "xpack.infra.inventoryModels.host.singularDisplayName": "主机", - "xpack.infra.inventoryModels.pod.singularDisplayName": "Kubernetes Pod", "xpack.infra.inventoryTimeline.checkNewDataButtonLabel": "检查新数据", "xpack.infra.inventoryTimeline.errorTitle": "无法显示历史数据。", "xpack.infra.inventoryTimeline.legend.anomalyLabel": "检测到异常", @@ -19154,31 +19135,6 @@ "xpack.infra.metricsExplorer.noMetrics.title": "缺失指标", "xpack.infra.metricsExplorer.openInTSVB": "在 Visualize 中打开", "xpack.infra.metricsHeaderAddDataButtonLabel": "添加数据", - "xpack.infra.metricsTable.container.averageCpuUsagePercentColumnHeader": "CPU 使用率(平均值)", - "xpack.infra.metricsTable.container.averageMemoryUsageMegabytesColumnHeader": "内存使用率(平均值)", - "xpack.infra.metricsTable.container.idColumnHeader": "ID", - "xpack.infra.metricsTable.container.paginationAriaLabel": "容器指标分页", - "xpack.infra.metricsTable.container.tableCaption": "容器的基础架构指标", - "xpack.infra.metricsTable.emptyIndicesPromptQueryHintDescription": "尝试搜索不同的词组合。", - "xpack.infra.metricsTable.emptyIndicesPromptQueryHintTitle": "调整您的查询", - "xpack.infra.metricsTable.emptyIndicesPromptTimeRangeHintDescription": "尝试搜索更长的时间段。", - "xpack.infra.metricsTable.emptyIndicesPromptTimeRangeHintTitle": "展开时间范围", - "xpack.infra.metricsTable.emptyIndicesPromptTitle": "没有任何结果匹配您的搜索条件", - "xpack.infra.metricsTable.host.averageCpuUsagePercentColumnHeader": "CPU 使用率(平均值)", - "xpack.infra.metricsTable.host.averageMemoryUsagePercentColumnHeader": "内存使用率(平均值)", - "xpack.infra.metricsTable.host.CpuCountColumnHeader": "# 个 CPU", - "xpack.infra.metricsTable.host.nameColumnHeader": "名称", - "xpack.infra.metricsTable.host.paginationAriaLabel": "主机指标分页", - "xpack.infra.metricsTable.host.tableCaption": "主机的基础架构指标", - "xpack.infra.metricsTable.host.totalMemoryMegabytesColumnHeader": "内存合计", - "xpack.infra.metricsTable.loadingContentTitle": "正在加载指标", - "xpack.infra.metricsTable.noResultsIllustrationAlternativeText": "带有惊叹号的放大镜", - "xpack.infra.metricsTable.numberCell.metricNotAvailableLabel": "不可用", - "xpack.infra.metricsTable.pod.averageCpuUsagePercentColumnHeader": "CPU 使用率(平均值)", - "xpack.infra.metricsTable.pod.averageMemoryUsageMegabytesColumnHeader": "内存使用率(平均值)", - "xpack.infra.metricsTable.pod.nameColumnHeader": "名称", - "xpack.infra.metricsTable.pod.paginationAriaLabel": "Pod 指标分页", - "xpack.infra.metricsTable.pod.tableCaption": "Pod 的基础架构指标", "xpack.infra.ml.anomalyDetectionButton": "异常检测", "xpack.infra.ml.anomalyFlyout.actions.openActionMenu": "打开", "xpack.infra.ml.anomalyFlyout.actions.openInAnomalyExplorer": "在 Anomaly Explorer 中打开", diff --git a/x-pack/plugins/triggers_actions_ui/kibana.jsonc b/x-pack/plugins/triggers_actions_ui/kibana.jsonc index eb660c0bbe383..feb178135d805 100644 --- a/x-pack/plugins/triggers_actions_ui/kibana.jsonc +++ b/x-pack/plugins/triggers_actions_ui/kibana.jsonc @@ -30,7 +30,8 @@ "cloud", "features", "home", - "spaces" + "spaces", + "serverless", ], "requiredBundles": [ "alerting", diff --git a/x-pack/plugins/triggers_actions_ui/public/application/app.tsx b/x-pack/plugins/triggers_actions_ui/public/application/app.tsx index a8d58e2e627f3..ac0fd6a6d92a3 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/app.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/app.tsx @@ -72,6 +72,7 @@ export interface TriggersAndActionsUiServices extends CoreStart { unifiedSearch: UnifiedSearchPublicPluginStart; licensing: LicensingPluginStart; expressions: ExpressionsStart; + isServerless: boolean; } export const renderApp = (deps: TriggersAndActionsUiServices) => { diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/rules_setting/rules_settings_modal.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/components/rules_setting/rules_settings_modal.test.tsx index f33178ad4f6b0..8eaf283cab0ba 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/rules_setting/rules_settings_modal.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/rules_setting/rules_settings_modal.test.tsx @@ -140,6 +140,8 @@ describe('rules_settings_modal', () => { addWarning: jest.fn(), } as unknown as IToasts; + useKibanaMock().services.isServerless = true; + getFlappingSettingsMock.mockResolvedValue(mockFlappingSetting); updateFlappingSettingsMock.mockResolvedValue(mockFlappingSetting); getQueryDelaySettingsMock.mockResolvedValue(mockQueryDelaySetting); @@ -436,4 +438,11 @@ describe('rules_settings_modal', () => { expect(result.queryByTestId('rulesSettingsQueryDelaySection')).toBe(null); }); + + test('hides query delay settings when not serverless', async () => { + useKibanaMock().services.isServerless = false; + const result = render(); + await waitForModalLoad({ queryDelaySection: false }); + expect(result.queryByTestId('rulesSettingsQueryDelaySection')).not.toBeInTheDocument(); + }); }); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/rules_setting/rules_settings_modal.tsx b/x-pack/plugins/triggers_actions_ui/public/application/components/rules_setting/rules_settings_modal.tsx index a75a7139c1189..c9b6ea19dec5b 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/rules_setting/rules_settings_modal.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/rules_setting/rules_settings_modal.tsx @@ -92,6 +92,7 @@ export const RulesSettingsModal = memo((props: RulesSettingsModalProps) => { const { application: { capabilities }, + isServerless, } = useKibana().services; const { rulesSettings: { @@ -229,7 +230,7 @@ export const RulesSettingsModal = memo((props: RulesSettingsModalProps) => { hasError={hasFlappingError} /> )} - {queryDelaySettings && ( + {isServerless && queryDelaySettings && ( <> - rule.consumer === ALERTS_FEATURE_ID + .filter((item) => { + return rule.consumer === ALERTS_FEATURE_ID ? !item.ruleTypeModel.requiresAppContext - : item.ruleType!.producer === rule.consumer - ); + : item.ruleType!.producer === rule.consumer; + }); const availableRuleTypesResult = getAvailableRuleTypes(ruleTypes); setAvailableRuleTypes(availableRuleTypesResult); @@ -274,9 +275,13 @@ export const RuleForm = ({ }, new Map() ); - setSolutions( - new Map([...solutionsResult.entries()].sort(([, a], [, b]) => a.localeCompare(b))) - ); + const solutionsEntries = [...solutionsResult.entries()]; + const isOnlyO11y = + availableRuleTypesResult.length === 1 && + availableRuleTypesResult.every((rt) => rt.ruleType.producer === AlertConsumers.OBSERVABILITY); + if (!isOnlyO11y) { + setSolutions(new Map(solutionsEntries.sort(([, a], [, b]) => a.localeCompare(b)))); + } // eslint-disable-next-line react-hooks/exhaustive-deps }, [ ruleTypes, @@ -400,6 +405,16 @@ export const RuleForm = ({ // eslint-disable-next-line react-hooks/exhaustive-deps }, [ruleTypeRegistry, availableRuleTypes, searchText, JSON.stringify(solutionsFilter)]); + useEffect(() => { + if (ruleTypeModel) { + const ruleType = ruleTypes.find((rt) => rt.id === ruleTypeModel.id); + if (ruleType && useRuleProducer && !MULTI_CONSUMER_RULE_TYPE_IDS.includes(ruleType.id)) { + setConsumer(ruleType.producer as RuleCreationValidConsumer); + } + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [ruleTypeModel, ruleTypes]); + const authorizedConsumers = useMemo(() => { // If the app context provides a consumer, we assume that consumer is // is what we set for all rules that is created in that context diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_form/rule_form_consumer_selection.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_form/rule_form_consumer_selection.test.tsx index ee7af0446c9ec..34724e8d745bf 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_form/rule_form_consumer_selection.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_form/rule_form_consumer_selection.test.tsx @@ -80,4 +80,17 @@ describe('RuleFormConsumerSelectionModal', () => { expect(mockOnChange).toHaveBeenLastCalledWith('stackAlerts'); expect(screen.queryByTestId('ruleFormConsumerSelect')).not.toBeInTheDocument(); }); + + it('should display nothing if observability is one of the consumer', () => { + render( + + ); + + expect(mockOnChange).toHaveBeenLastCalledWith('observability'); + expect(screen.queryByTestId('ruleFormConsumerSelect')).not.toBeInTheDocument(); + }); }); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_form/rule_form_consumer_selection.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_form/rule_form_consumer_selection.tsx index f5f92c72fa521..58ce0c4cc3062 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_form/rule_form_consumer_selection.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rule_form/rule_form_consumer_selection.tsx @@ -14,7 +14,7 @@ import { IErrorObject, RuleCreationValidConsumer } from '../../../types'; const SELECT_LABEL: string = i18n.translate( 'xpack.triggersActionsUI.sections.ruleFormConsumerSelectionModal.selectLabel', { - defaultMessage: 'Select role visibility', + defaultMessage: 'Role visibility', } ); @@ -121,13 +121,15 @@ export const RuleFormConsumerSelection = (props: RuleFormConsumerSelectionProps) }, []); useEffect(() => { - if (formattedSelectOptions.length === 1) { - onChange(formattedSelectOptions[0].value as RuleCreationValidConsumer); + if (consumers.length === 1) { + onChange(consumers[0] as RuleCreationValidConsumer); + } else if (consumers.includes(AlertConsumers.OBSERVABILITY)) { + onChange(AlertConsumers.OBSERVABILITY as RuleCreationValidConsumer); } // eslint-disable-next-line react-hooks/exhaustive-deps - }, [formattedSelectOptions]); + }, [consumers]); - if (formattedSelectOptions.length <= 1) { + if (consumers.length <= 1 || consumers.includes(AlertConsumers.OBSERVABILITY)) { return null; } return ( diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/notify_badge/notify_badge.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/notify_badge/notify_badge.tsx index 8ddb44d0c6c67..e09892471419b 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/notify_badge/notify_badge.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/rules_list/components/notify_badge/notify_badge.tsx @@ -199,7 +199,6 @@ export const RulesListNotifyBadge: React.FunctionComponent { - // TODO: Implement scheduled snooze button return ( { theme$: themeServiceMock.createTheme$(), licensing: licensingPluginMock, expressions: expressionsPluginMock.createStartContract(), + isServerless: false, } as TriggersAndActionsUiServices; }; diff --git a/x-pack/plugins/triggers_actions_ui/public/plugin.ts b/x-pack/plugins/triggers_actions_ui/public/plugin.ts index c300ea02e1601..f81a0ae5f30eb 100644 --- a/x-pack/plugins/triggers_actions_ui/public/plugin.ts +++ b/x-pack/plugins/triggers_actions_ui/public/plugin.ts @@ -27,6 +27,7 @@ import { triggersActionsRoute } from '@kbn/rule-data-utils'; import { DashboardStart } from '@kbn/dashboard-plugin/public'; import type { LicensingPluginStart } from '@kbn/licensing-plugin/public'; import { ExpressionsStart } from '@kbn/expressions-plugin/public'; +import { ServerlessPluginStart } from '@kbn/serverless/public'; import type { AlertsSearchBarProps } from './application/sections/alerts_search_bar'; import { TypeRegistry } from './application/type_registry'; @@ -165,6 +166,7 @@ interface PluginsStart { expressions: ExpressionsStart; unifiedSearch: UnifiedSearchPublicPluginStart; licensing: LicensingPluginStart; + serverless?: ServerlessPluginStart; } export class Plugin @@ -290,6 +292,7 @@ export class Plugin kibanaFeatures, licensing: pluginsStart.licensing, expressions: pluginsStart.expressions, + isServerless: !!pluginsStart.serverless, }); }, }); diff --git a/x-pack/plugins/triggers_actions_ui/public/types.ts b/x-pack/plugins/triggers_actions_ui/public/types.ts index dd65104407247..9c9f08bc77b98 100644 --- a/x-pack/plugins/triggers_actions_ui/public/types.ts +++ b/x-pack/plugins/triggers_actions_ui/public/types.ts @@ -838,4 +838,5 @@ export interface NotifyWhenSelectOptions { export type RuleCreationValidConsumer = | typeof AlertConsumers.LOGS | typeof AlertConsumers.INFRASTRUCTURE + | typeof AlertConsumers.OBSERVABILITY | typeof STACK_ALERTS_FEATURE_ID; diff --git a/x-pack/plugins/triggers_actions_ui/tsconfig.json b/x-pack/plugins/triggers_actions_ui/tsconfig.json index 3bfe7239fac2c..d2d91cca3486b 100644 --- a/x-pack/plugins/triggers_actions_ui/tsconfig.json +++ b/x-pack/plugins/triggers_actions_ui/tsconfig.json @@ -55,6 +55,7 @@ "@kbn/dashboard-plugin", "@kbn/licensing-plugin", "@kbn/expressions-plugin", + "@kbn/serverless", ], "exclude": ["target/**/*"] } diff --git a/x-pack/test/alerting_api_integration/observability/custom_threshold_rule/avg_pct_fired.ts b/x-pack/test/alerting_api_integration/observability/custom_threshold_rule/avg_pct_fired.ts index 4c67a7fcb3495..2af99f85887b0 100644 --- a/x-pack/test/alerting_api_integration/observability/custom_threshold_rule/avg_pct_fired.ts +++ b/x-pack/test/alerting_api_integration/observability/custom_threshold_rule/avg_pct_fired.ts @@ -37,6 +37,7 @@ export default function ({ getService }: FtrProviderContext) { // DATE_VIEW should match the index template: // x-pack/packages/kbn-infra-forge/src/data_sources/composable/template.json const DATE_VIEW = 'kbn-data-forge-fake_hosts'; + const DATE_VIEW_NAME = 'data-view-name'; const DATA_VIEW_ID = 'data-view-id'; let infraDataIndex: string; let actionId: string; @@ -48,7 +49,7 @@ export default function ({ getService }: FtrProviderContext) { infraDataIndex = await generate({ esClient, lookback: 'now-15m', logger }); await createDataView({ supertest, - name: DATE_VIEW, + name: DATE_VIEW_NAME, id: DATA_VIEW_ID, title: DATE_VIEW, }); @@ -213,7 +214,7 @@ export default function ({ getService }: FtrProviderContext) { `https://localhost:5601/app/observability/alerts?_a=(kuery:%27kibana.alert.uuid:%20%22${alertId}%22%27%2CrangeFrom:%27${rangeFrom}%27%2CrangeTo:now%2Cstatus:all)` ); expect(resp.hits.hits[0]._source?.reason).eql( - `Average system.cpu.user.pct is 250%, above the threshold of 50%. (duration: 5 mins, data view: ${DATE_VIEW})` + `Average system.cpu.user.pct is 250%, above the threshold of 50%. (duration: 5 mins, data view: ${DATE_VIEW_NAME})` ); expect(resp.hits.hits[0]._source?.value).eql('250%'); }); diff --git a/x-pack/test/alerting_api_integration/observability/custom_threshold_rule/avg_pct_no_data.ts b/x-pack/test/alerting_api_integration/observability/custom_threshold_rule/avg_pct_no_data.ts index d984e01fead57..e2ea6264a1233 100644 --- a/x-pack/test/alerting_api_integration/observability/custom_threshold_rule/avg_pct_no_data.ts +++ b/x-pack/test/alerting_api_integration/observability/custom_threshold_rule/avg_pct_no_data.ts @@ -33,6 +33,7 @@ export default function ({ getService }: FtrProviderContext) { describe('Custom Threshold rule - AVG - PCT - NoData', () => { const CUSTOM_THRESHOLD_RULE_ALERT_INDEX = '.alerts-observability.threshold.alerts-default'; const ALERT_ACTION_INDEX = 'alert-action-threshold'; + const DATA_VIEW = 'no-data-pattern'; const DATA_VIEW_ID = 'data-view-id-no-data'; let actionId: string; let ruleId: string; @@ -42,9 +43,9 @@ export default function ({ getService }: FtrProviderContext) { before(async () => { await createDataView({ supertest, - name: 'no-data-pattern', + name: DATA_VIEW, id: DATA_VIEW_ID, - title: 'no-data-pattern', + title: DATA_VIEW, }); }); diff --git a/x-pack/test/alerting_api_integration/observability/custom_threshold_rule/avg_us_fired.ts b/x-pack/test/alerting_api_integration/observability/custom_threshold_rule/avg_us_fired.ts index 4e2f547828f60..18a8fb4b4708c 100644 --- a/x-pack/test/alerting_api_integration/observability/custom_threshold_rule/avg_us_fired.ts +++ b/x-pack/test/alerting_api_integration/observability/custom_threshold_rule/avg_us_fired.ts @@ -42,6 +42,7 @@ export default function ({ getService }: FtrProviderContext) { const ALERT_ACTION_INDEX = 'alert-action-threshold'; const DATE_VIEW = 'traces-apm*,metrics-apm*,logs-apm*'; const DATA_VIEW_ID = 'data-view-id'; + const DATA_VIEW_NAME = 'test-data-view-name'; let synthtraceEsClient: ApmSynthtraceEsClient; let actionId: string; @@ -54,7 +55,7 @@ export default function ({ getService }: FtrProviderContext) { await generateData({ synthtraceEsClient, start, end }); await createDataView({ supertest, - name: 'test-data-view', + name: DATA_VIEW_NAME, id: DATA_VIEW_ID, title: DATE_VIEW, }); @@ -218,7 +219,7 @@ export default function ({ getService }: FtrProviderContext) { `https://localhost:5601/app/observability/alerts?_a=(kuery:%27kibana.alert.uuid:%20%22${alertId}%22%27%2CrangeFrom:%27${rangeFrom}%27%2CrangeTo:now%2Cstatus:all)` ); expect(resp.hits.hits[0]._source?.reason).eql( - `Average span.self_time.sum.us is 10,000,000, above the threshold of 7,500,000. (duration: 5 mins, data view: ${DATE_VIEW})` + `Average span.self_time.sum.us is 10,000,000, above the threshold of 7,500,000. (duration: 5 mins, data view: ${DATA_VIEW_NAME})` ); expect(resp.hits.hits[0]._source?.value).eql('10,000,000'); }); diff --git a/x-pack/test/alerting_api_integration/observability/custom_threshold_rule/documents_count_fired.ts b/x-pack/test/alerting_api_integration/observability/custom_threshold_rule/documents_count_fired.ts index db18cd4e899ed..fbebf8f95fed2 100644 --- a/x-pack/test/alerting_api_integration/observability/custom_threshold_rule/documents_count_fired.ts +++ b/x-pack/test/alerting_api_integration/observability/custom_threshold_rule/documents_count_fired.ts @@ -38,6 +38,7 @@ export default function ({ getService }: FtrProviderContext) { // x-pack/packages/kbn-infra-forge/src/data_sources/composable/template.json const DATE_VIEW = 'kbn-data-forge-fake_hosts'; const DATA_VIEW_ID = 'data-view-id'; + const DATE_VIEW_NAME = 'data-view-name'; let infraDataIndex: string; let actionId: string; let ruleId: string; @@ -48,7 +49,7 @@ export default function ({ getService }: FtrProviderContext) { infraDataIndex = await generate({ esClient, lookback: 'now-15m', logger }); await createDataView({ supertest, - name: DATE_VIEW, + name: DATE_VIEW_NAME, id: DATA_VIEW_ID, title: DATE_VIEW, }); @@ -212,7 +213,7 @@ export default function ({ getService }: FtrProviderContext) { `https://localhost:5601/app/observability/alerts?_a=(kuery:%27kibana.alert.uuid:%20%22${alertId}%22%27%2CrangeFrom:%27${rangeFrom}%27%2CrangeTo:now%2Cstatus:all)` ); expect(resp.hits.hits[0]._source?.reason).eql( - `Document count is 3, above the threshold of 2. (duration: 1 min, data view: ${DATE_VIEW})` + `Document count is 3, above the threshold of 2. (duration: 1 min, data view: ${DATE_VIEW_NAME})` ); expect(resp.hits.hits[0]._source?.value).eql('3'); }); diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/get_global_execution_kpi.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/get_global_execution_kpi.ts index 531e60097732a..d31213a144eb6 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/get_global_execution_kpi.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/get_global_execution_kpi.ts @@ -17,8 +17,7 @@ export default function getGlobalExecutionKpiTests({ getService }: FtrProviderCo const retry = getService('retry'); - // FLAKY: https://github.com/elastic/kibana/issues/153112 - describe.skip('getGlobalExecutionKpi', () => { + describe('getGlobalExecutionKpi', () => { const objectRemover = new ObjectRemover(supertest); afterEach(() => objectRemover.removeAll()); @@ -298,7 +297,7 @@ export default function getGlobalExecutionKpiTests({ getService }: FtrProviderCo 'triggeredActions', ]); expect(kpiLogs.success).to.be.above(1); - expect(kpiLogs.failure).to.be.above(2); + expect(kpiLogs.failure).to.be.above(1); }); }); } diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group3/tests/alerting/get_query_delay_settings.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group3/tests/alerting/get_query_delay_settings.ts index ce56b6e6690bc..34e9a8b68c485 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group3/tests/alerting/get_query_delay_settings.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group3/tests/alerting/get_query_delay_settings.ts @@ -39,6 +39,8 @@ export default function getQueryDelaySettingsTests({ getService }: FtrProviderCo case 'space_1_all at space2': case 'space_1_all_with_restricted_fixture at space1': case 'space_1_all_alerts_none_actions at space1': + case 'global_read at space1': + case 'space_1_all at space1': expect(response.statusCode).to.eql(403); expect(response.body).to.eql({ error: 'Forbidden', @@ -46,9 +48,7 @@ export default function getQueryDelaySettingsTests({ getService }: FtrProviderCo statusCode: 403, }); break; - case 'global_read at space1': case 'superuser at space1': - case 'space_1_all at space1': expect(response.statusCode).to.eql(200); expect(response.body.delay).to.eql(DEFAULT_QUERY_DELAY_SETTINGS.delay); expect(response.body.updated_by).to.be.a('string'); diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group3/tests/alerting/update_query_delay_settings.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group3/tests/alerting/update_query_delay_settings.ts index 7f7fcaa844691..293e906de9c77 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group3/tests/alerting/update_query_delay_settings.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group3/tests/alerting/update_query_delay_settings.ts @@ -39,6 +39,7 @@ export default function updateQueryDelaySettingsTest({ getService }: FtrProvider case 'space_1_all at space2': case 'space_1_all_with_restricted_fixture at space1': case 'space_1_all_alerts_none_actions at space1': + case 'space_1_all at space1': expect(response.statusCode).to.eql(403); expect(response.body).to.eql({ error: 'Forbidden', @@ -47,7 +48,6 @@ export default function updateQueryDelaySettingsTest({ getService }: FtrProvider }); break; case 'superuser at space1': - case 'space_1_all at space1': expect(response.statusCode).to.eql(200); expect(response.body.delay).to.eql(20); expect(response.body.updated_by).to.eql(user.username); diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group3/builtin_alert_types/es_query/esql_only.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group3/builtin_alert_types/es_query/esql_only.ts index 5996a28a4f976..18f451bbabd9e 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group3/builtin_alert_types/es_query/esql_only.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group3/builtin_alert_types/es_query/esql_only.ts @@ -73,12 +73,10 @@ export default function ruleTests({ getService }: FtrProviderContext) { await createRule({ name: 'never fire', esqlQuery: 'from .kibana-alerting-test-data | stats c = count(date) | where c < 0', - size: 100, }); await createRule({ name: 'always fire', esqlQuery: 'from .kibana-alerting-test-data | stats c = count(date) | where c > -1', - size: 100, }); const docs = await waitForDocs(2); @@ -114,13 +112,13 @@ export default function ruleTests({ getService }: FtrProviderContext) { await createRule({ name: 'never fire', esqlQuery: 'from .kibana-alerting-test-data | stats c = count(date) | where c < 0', - size: 100, + timeField: 'date_epoch_millis', }); await createRule({ name: 'always fire', esqlQuery: 'from .kibana-alerting-test-data | stats c = count(date) | where c > -1', - size: 100, + timeField: 'date_epoch_millis', }); @@ -142,7 +140,6 @@ export default function ruleTests({ getService }: FtrProviderContext) { await createRule({ name: 'always fire', esqlQuery: 'from .kibana-alerting-test-data | stats c = count(date) | where c < 1', - size: 100, }); const docs = await waitForDocs(1); @@ -165,7 +162,7 @@ export default function ruleTests({ getService }: FtrProviderContext) { await createRule({ name: 'fire then recovers', esqlQuery: 'from .kibana-alerting-test-data | stats c = count(date) | where c < 1', - size: 100, + notifyWhen: 'onActionGroupChange', timeWindowSize: RULE_INTERVAL_SECONDS, }); @@ -212,12 +209,10 @@ export default function ruleTests({ getService }: FtrProviderContext) { await createRule({ name: 'never fire', esqlQuery: 'from test-data-stream | stats c = count(@timestamp) | where c < 0', - size: 100, }); await createRule({ name: 'always fire', esqlQuery: 'from test-data-stream | stats c = count(@timestamp) | where c > -1', - size: 100, }); const docs = await waitForDocs(2); @@ -234,6 +229,122 @@ export default function ruleTests({ getService }: FtrProviderContext) { } }); + it('throws an error if the thresholdComparator is not >', async () => { + const { body } = await supertest + .post(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule`) + .set('kbn-xsrf', 'foo') + .send({ + name: 'test', + consumer: 'alerts', + enabled: true, + rule_type_id: RULE_TYPE_ID, + schedule: { interval: `${RULE_INTERVAL_SECONDS}s` }, + actions: [], + notify_when: 'onActiveAlert', + params: { + size: 100, + timeWindowSize: RULE_INTERVAL_SECONDS * 5, + timeWindowUnit: 's', + thresholdComparator: '<', + threshold: [0], + searchType: 'esqlQuery', + timeField: 'date', + esqlQuery: { + esql: 'from .kibana-alerting-test-data | stats c = count(date) | where c < 0', + }, + }, + }) + .expect(400); + expect(body.message).to.be( + 'params invalid: [thresholdComparator]: is required to be greater than' + ); + }); + + it('throws an error if the threshold is not [0]', async () => { + const { body } = await supertest + .post(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule`) + .set('kbn-xsrf', 'foo') + .send({ + name: 'test', + consumer: 'alerts', + enabled: true, + rule_type_id: RULE_TYPE_ID, + schedule: { interval: `${RULE_INTERVAL_SECONDS}s` }, + actions: [], + notify_when: 'onActiveAlert', + params: { + size: 100, + timeWindowSize: RULE_INTERVAL_SECONDS * 5, + timeWindowUnit: 's', + thresholdComparator: '>', + threshold: [100], + searchType: 'esqlQuery', + timeField: 'date', + esqlQuery: { + esql: 'from .kibana-alerting-test-data | stats c = count(date) | where c < 0', + }, + }, + }) + .expect(400); + expect(body.message).to.be('params invalid: [threshold]: is required to be 0'); + }); + + it('throws an error if the timeField is undefined', async () => { + const { body } = await supertest + .post(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule`) + .set('kbn-xsrf', 'foo') + .send({ + name: 'test', + consumer: 'alerts', + enabled: true, + rule_type_id: RULE_TYPE_ID, + schedule: { interval: `${RULE_INTERVAL_SECONDS}s` }, + actions: [], + notify_when: 'onActiveAlert', + params: { + size: 100, + timeWindowSize: RULE_INTERVAL_SECONDS * 5, + timeWindowUnit: 's', + thresholdComparator: '>', + threshold: [0], + searchType: 'esqlQuery', + esqlQuery: { + esql: 'from .kibana-alerting-test-data | stats c = count(date) | where c < 0', + }, + }, + }) + .expect(400); + expect(body.message).to.be('params invalid: [timeField]: is required'); + }); + + it('throws an error if the esqlQuery is undefined', async () => { + const { body } = await supertest + .post(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule`) + .set('kbn-xsrf', 'foo') + .send({ + name: 'test', + consumer: 'alerts', + enabled: true, + rule_type_id: RULE_TYPE_ID, + schedule: { interval: `${RULE_INTERVAL_SECONDS}s` }, + actions: [], + notify_when: 'onActiveAlert', + params: { + size: 100, + timeWindowSize: RULE_INTERVAL_SECONDS * 5, + timeWindowUnit: 's', + thresholdComparator: '>', + threshold: [0], + searchType: 'esqlQuery', + timeField: 'date', + }, + }) + .expect(400); + expect(body.message).to.be( + 'params invalid: [esqlQuery.esql]: expected value of type [string] but got [undefined]' + ); + }); + async function waitForDocs(count: number): Promise { return await esTestIndexToolOutput.waitForDocs( ES_TEST_INDEX_SOURCE, @@ -244,7 +355,6 @@ export default function ruleTests({ getService }: FtrProviderContext) { interface CreateRuleParams { name: string; - size: number; esqlQuery: string; timeWindowSize?: number; timeField?: string; @@ -312,7 +422,7 @@ export default function ruleTests({ getService }: FtrProviderContext) { actions: [action, recoveryAction], notify_when: params.notifyWhen || 'onActiveAlert', params: { - size: params.size, + size: 100, timeWindowSize: params.timeWindowSize || RULE_INTERVAL_SECONDS * 5, timeWindowUnit: 's', thresholdComparator: '>', diff --git a/x-pack/test/api_integration/apis/asset_manager/tests/assets.ts b/x-pack/test/api_integration/apis/asset_manager/tests/assets.ts deleted file mode 100644 index 7514513971688..0000000000000 --- a/x-pack/test/api_integration/apis/asset_manager/tests/assets.ts +++ /dev/null @@ -1,275 +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 { AssetWithoutTimestamp } from '@kbn/assetManager-plugin/common/types_api'; -import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../../ftr_provider_context'; -import { createSampleAssets, deleteSampleAssets, viewSampleAssetDocs } from './helpers'; -import { ASSETS_ENDPOINT } from './constants'; - -export default function ({ getService }: FtrProviderContext) { - const supertest = getService('supertest'); - - describe('asset management', () => { - let sampleAssetDocs: AssetWithoutTimestamp[] = []; - before(async () => { - sampleAssetDocs = await viewSampleAssetDocs(supertest); - }); - - beforeEach(async () => { - await deleteSampleAssets(supertest); - }); - - describe('GET /assets', () => { - it('should return the full list of assets', async () => { - await createSampleAssets(supertest); - const getResponse = await supertest - .get(ASSETS_ENDPOINT) - .query({ size: sampleAssetDocs.length }) - .expect(200); - - expect(getResponse.body).to.have.property('results'); - expect(getResponse.body.results.length).to.equal(sampleAssetDocs.length); - }); - - it('should only return one document per asset, even if the asset has been indexed multiple times', async () => { - const now = new Date(); - const oneHourAgo = new Date(now.getTime() - 1000 * 60 * 60 * 1); - const twoHoursAgo = new Date(now.getTime() - 1000 * 60 * 60 * 2); - await createSampleAssets(supertest, { baseDateTime: twoHoursAgo.toISOString() }); - await createSampleAssets(supertest, { baseDateTime: oneHourAgo.toISOString() }); - - const getResponse = await supertest - .get(ASSETS_ENDPOINT) - .query({ size: sampleAssetDocs.length, from: 'now-1d' }) - .expect(200); - - expect(getResponse.body).to.have.property('results'); - expect(getResponse.body.results.length).to.equal(sampleAssetDocs.length); - - // Also make sure the returned timestamp for the documents is the more recent of the two - expect(getResponse.body.results[0]['@timestamp']).to.equal(oneHourAgo.toISOString()); - }); - - // TODO: should allow for sorting? right now the returned subset is somewhat random - it('should allow caller to request n assets', async () => { - await createSampleAssets(supertest); - - expect(sampleAssetDocs.length).to.be.greaterThan(5); - - const getResponse = await supertest - .get(ASSETS_ENDPOINT) - .query({ size: 5, from: 'now-1d' }) - .expect(200); - - expect(getResponse.body).to.have.property('results'); - expect(getResponse.body.results.length).to.equal(5); - }); - - it('should return assets filtered by a single type', async () => { - await createSampleAssets(supertest); - - const singleSampleType = sampleAssetDocs[0]['asset.type']; - const samplesForType = sampleAssetDocs.filter( - (doc) => doc['asset.type'] === singleSampleType - ); - - const getResponse = await supertest - .get(ASSETS_ENDPOINT) - .query({ size: sampleAssetDocs.length, from: 'now-1d', type: singleSampleType }) - .expect(200); - - expect(getResponse.body).to.have.property('results'); - expect(getResponse.body.results.length).to.equal(samplesForType.length); - }); - - it('should return assets filtered by multiple types (OR)', async () => { - await createSampleAssets(supertest); - - // Dynamically grab all types from the sample asset data set - const sampleTypeSet: Set = new Set(); - for (let i = 0; i < sampleAssetDocs.length; i++) { - sampleTypeSet.add(sampleAssetDocs[i]['asset.type']!); - } - const sampleTypes = Array.from(sampleTypeSet); - if (sampleTypes.length <= 2) { - throw new Error( - 'Not enough asset type values in sample asset documents, need more than two to test filtering by multiple types' - ); - } - - // Pick the first two unique types from the sample data set - const filterByTypes = sampleTypes.slice(0, 2); - - // Track a reference to how many docs should be returned for these two types - const samplesForFilteredTypes = sampleAssetDocs.filter((doc) => - filterByTypes.includes(doc['asset.type']!) - ); - - expect(samplesForFilteredTypes.length).to.be.lessThan(sampleAssetDocs.length); - - // Request assets for multiple types (with a size matching the number of total sample asset docs) - const getResponse = await supertest - .get(ASSETS_ENDPOINT) - .query({ size: sampleAssetDocs.length, from: 'now-1d', type: filterByTypes }) - .expect(200); - - expect(getResponse.body).to.have.property('results'); - expect(getResponse.body.results.length).to.equal(samplesForFilteredTypes.length); - }); - - it('should reject requests that try to filter by both type and ean', async () => { - const sampleType = sampleAssetDocs[0]['asset.type']; - const sampleEan = sampleAssetDocs[0]['asset.ean']; - - const getResponse = await supertest - .get(ASSETS_ENDPOINT) - .query({ type: sampleType, ean: sampleEan }) - .expect(400); - - expect(getResponse.body.message).to.equal( - 'Filters "type" and "ean" are mutually exclusive but found both.' - ); - }); - - it('should return assets filtered by a single asset.kind value', async () => { - await createSampleAssets(supertest); - - const singleSampleKind = sampleAssetDocs[0]['asset.kind']; - const samplesForKind = sampleAssetDocs.filter( - (doc) => doc['asset.kind'] === singleSampleKind - ); - - const getResponse = await supertest - .get(ASSETS_ENDPOINT) - .query({ size: sampleAssetDocs.length, from: 'now-1d', kind: singleSampleKind }) - .expect(200); - - expect(getResponse.body).to.have.property('results'); - expect(getResponse.body.results.length).to.equal(samplesForKind.length); - }); - - it('should return assets filtered by multiple asset.kind values (OR)', async () => { - await createSampleAssets(supertest); - - // Dynamically grab all asset.kind values from the sample asset data set - const sampleKindSet: Set = new Set(); - for (let i = 0; i < sampleAssetDocs.length; i++) { - sampleKindSet.add(sampleAssetDocs[i]['asset.kind']!); - } - const sampleKinds = Array.from(sampleKindSet); - if (sampleKinds.length <= 2) { - throw new Error( - 'Not enough asset kind values in sample asset documents, need more than two to test filtering by multiple kinds' - ); - } - - // Pick the first two unique kinds from the sample data set - const filterByKinds = sampleKinds.slice(0, 2); - - // Track a reference to how many docs should be returned for these two kinds - const samplesForFilteredKinds = sampleAssetDocs.filter((doc) => - filterByKinds.includes(doc['asset.kind']!) - ); - - expect(samplesForFilteredKinds.length).to.be.lessThan(sampleAssetDocs.length); - - // Request assets for multiple types (with a size matching the number of total sample asset docs) - const getResponse = await supertest - .get(ASSETS_ENDPOINT) - .query({ size: sampleAssetDocs.length, from: 'now-1d', kind: filterByKinds }) - .expect(200); - - expect(getResponse.body).to.have.property('results'); - expect(getResponse.body.results.length).to.equal(samplesForFilteredKinds.length); - }); - - it('should reject requests that try to filter by both kind and ean', async () => { - const sampleKind = sampleAssetDocs[0]['asset.kind']; - const sampleEan = sampleAssetDocs[0]['asset.ean']; - - const getResponse = await supertest - .get(ASSETS_ENDPOINT) - .query({ kind: sampleKind, ean: sampleEan }) - .expect(400); - - expect(getResponse.body.message).to.equal( - 'Filters "kind" and "ean" are mutually exclusive but found both.' - ); - }); - - it('should return the asset matching a single ean', async () => { - await createSampleAssets(supertest); - - const targetAsset = sampleAssetDocs[0]; - const singleSampleEan = targetAsset['asset.ean']; - - const getResponse = await supertest - .get(ASSETS_ENDPOINT) - .query({ size: 5, from: 'now-1d', ean: singleSampleEan }) - .expect(200); - - expect(getResponse.body).to.have.property('results'); - expect(getResponse.body.results.length).to.equal(1); - - const returnedAsset = getResponse.body.results[0]; - delete returnedAsset['@timestamp']; - expect(returnedAsset).to.eql(targetAsset); - }); - - it('should return assets matching multiple eans', async () => { - await createSampleAssets(supertest); - - const targetAssets = [sampleAssetDocs[0], sampleAssetDocs[2], sampleAssetDocs[4]]; - const sampleEans = targetAssets.map((asset) => asset['asset.ean']); - sampleEans.push('ean-that-does-not-exist'); - - const getResponse = await supertest - .get(ASSETS_ENDPOINT) - .query({ size: 5, from: 'now-1d', ean: sampleEans }) - .expect(200); - - expect(getResponse.body).to.have.property('results'); - expect(getResponse.body.results.length).to.equal(3); - - delete getResponse.body.results[0]['@timestamp']; - delete getResponse.body.results[1]['@timestamp']; - delete getResponse.body.results[2]['@timestamp']; - - // The order of the expected assets is fixed - expect(getResponse.body.results).to.eql(targetAssets); - }); - - it('should reject requests with negative size parameter', async () => { - const getResponse = await supertest.get(ASSETS_ENDPOINT).query({ size: -1 }).expect(400); - - expect(getResponse.body.message).to.equal( - '[request query]: Failed to validate: \n in /size: -1 does not match expected type pipe(ToNumber, InRange)\n in /size: "-1" does not match expected type pipe(undefined, BooleanFromString)' - ); - }); - - it('should reject requests with size parameter greater than 100', async () => { - const getResponse = await supertest.get(ASSETS_ENDPOINT).query({ size: 101 }).expect(400); - - expect(getResponse.body.message).to.equal( - '[request query]: Failed to validate: \n in /size: 101 does not match expected type pipe(ToNumber, InRange)\n in /size: "101" does not match expected type pipe(undefined, BooleanFromString)' - ); - }); - - it('should reject requests with invalid from and to parameters', async () => { - const getResponse = await supertest - .get(ASSETS_ENDPOINT) - .query({ from: 'now_1p', to: 'now_1p' }) - .expect(400); - - expect(getResponse.body.message).to.equal( - '[request query]: Failed to validate: \n in /from: "now_1p" does not match expected type Date\n in /from: "now_1p" does not match expected type datemath\n in /to: "now_1p" does not match expected type Date\n in /to: "now_1p" does not match expected type datemath' - ); - }); - }); - }); -} diff --git a/x-pack/test/api_integration/apis/asset_manager/tests/assets_diff.ts b/x-pack/test/api_integration/apis/asset_manager/tests/assets_diff.ts deleted file mode 100644 index 79c2db74d3f95..0000000000000 --- a/x-pack/test/api_integration/apis/asset_manager/tests/assets_diff.ts +++ /dev/null @@ -1,183 +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 { sortBy } from 'lodash'; - -import { AssetWithoutTimestamp } from '@kbn/assetManager-plugin/common/types_api'; -import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../../ftr_provider_context'; -import { createSampleAssets, deleteSampleAssets, viewSampleAssetDocs } from './helpers'; -import { ASSETS_ENDPOINT } from './constants'; - -const DIFF_ENDPOINT = `${ASSETS_ENDPOINT}/diff`; - -export default function ({ getService }: FtrProviderContext) { - const supertest = getService('supertest'); - - describe('asset management', () => { - let sampleAssetDocs: AssetWithoutTimestamp[] = []; - before(async () => { - sampleAssetDocs = await viewSampleAssetDocs(supertest); - }); - - beforeEach(async () => { - await deleteSampleAssets(supertest); - }); - - describe('GET /assets/diff', () => { - it('should reject requests that do not include the two time ranges to compare', async () => { - const timestamp = new Date().toISOString(); - - let getResponse = await supertest.get(DIFF_ENDPOINT).expect(400); - expect(getResponse.body.message).to.equal( - '[request query]: Failed to validate: \n in /0/aFrom: undefined does not match expected type Date\n in /0/aFrom: undefined does not match expected type datemath\n in /0/aTo: undefined does not match expected type Date\n in /0/aTo: undefined does not match expected type datemath\n in /0/bFrom: undefined does not match expected type Date\n in /0/bFrom: undefined does not match expected type datemath\n in /0/bTo: undefined does not match expected type Date\n in /0/bTo: undefined does not match expected type datemath' - ); - - getResponse = await supertest.get(DIFF_ENDPOINT).query({ aFrom: timestamp }).expect(400); - expect(getResponse.body.message).to.equal( - '[request query]: Failed to validate: \n in /0/aTo: undefined does not match expected type Date\n in /0/aTo: undefined does not match expected type datemath\n in /0/bFrom: undefined does not match expected type Date\n in /0/bFrom: undefined does not match expected type datemath\n in /0/bTo: undefined does not match expected type Date\n in /0/bTo: undefined does not match expected type datemath' - ); - - getResponse = await supertest - .get(DIFF_ENDPOINT) - .query({ aFrom: timestamp, aTo: timestamp }) - .expect(400); - expect(getResponse.body.message).to.equal( - '[request query]: Failed to validate: \n in /0/bFrom: undefined does not match expected type Date\n in /0/bFrom: undefined does not match expected type datemath\n in /0/bTo: undefined does not match expected type Date\n in /0/bTo: undefined does not match expected type datemath' - ); - - getResponse = await supertest - .get(DIFF_ENDPOINT) - .query({ aFrom: timestamp, aTo: timestamp, bFrom: timestamp }) - .expect(400); - expect(getResponse.body.message).to.equal( - '[request query]: Failed to validate: \n in /0/bTo: undefined does not match expected type Date\n in /0/bTo: undefined does not match expected type datemath' - ); - - return await supertest - .get(DIFF_ENDPOINT) - .query({ aFrom: timestamp, aTo: timestamp, bFrom: timestamp, bTo: timestamp }) - .expect(200); - }); - - it('should reject requests where either time range is moving backwards in time', async () => { - const now = new Date(); - const isoNow = now.toISOString(); - const oneHourAgo = new Date(now.getTime() - 1000 * 60 * 60 * 1).toISOString(); - - let getResponse = await supertest - .get(DIFF_ENDPOINT) - .query({ - aFrom: isoNow, - aTo: oneHourAgo, - bFrom: isoNow, - bTo: isoNow, - }) - .expect(400); - expect(getResponse.body.message).to.equal( - `Time range cannot move backwards in time. "aTo" (${oneHourAgo}) is before "aFrom" (${isoNow}).` - ); - - getResponse = await supertest - .get(DIFF_ENDPOINT) - .query({ - aFrom: isoNow, - aTo: isoNow, - bFrom: isoNow, - bTo: oneHourAgo, - }) - .expect(400); - expect(getResponse.body.message).to.equal( - `Time range cannot move backwards in time. "bTo" (${oneHourAgo}) is before "bFrom" (${isoNow}).` - ); - - return await supertest - .get(DIFF_ENDPOINT) - .query({ - aFrom: oneHourAgo, - aTo: isoNow, - bFrom: oneHourAgo, - bTo: isoNow, - }) - .expect(200); - }); - - it('should return the difference in assets present between two time ranges', async () => { - const onlyInA = sampleAssetDocs.slice(0, 2); // first two sample assets - const onlyInB = sampleAssetDocs.slice(sampleAssetDocs.length - 2); // last two sample assets - const inBoth = sampleAssetDocs.slice(2, sampleAssetDocs.length - 2); // everything between first 2, last 2 - const now = new Date(); - const oneHourAgo = new Date(now.getTime() - 1000 * 60 * 60 * 1); - const twoHoursAgo = new Date(now.getTime() - 1000 * 60 * 60 * 2); - - // Set 1: Two hours ago, excludes inBoth + onlyInB (leaves just onlyInA) - await createSampleAssets(supertest, { - baseDateTime: twoHoursAgo.toISOString(), - excludeEans: inBoth.concat(onlyInB).map((asset) => asset['asset.ean']), - }); - - // Set 2: One hour ago, excludes onlyInA + onlyInB (leaves just inBoth) - await createSampleAssets(supertest, { - baseDateTime: oneHourAgo.toISOString(), - excludeEans: onlyInA.concat(onlyInB).map((asset) => asset['asset.ean']), - }); - - // Set 3: Right now, excludes inBoth + onlyInA (leaves just onlyInB) - await createSampleAssets(supertest, { - excludeEans: inBoth.concat(onlyInA).map((asset) => asset['asset.ean']), - }); - - const twoHoursAndTenMinuesAgo = new Date(now.getTime() - 1000 * 60 * 130 * 1); - const fiftyMinuesAgo = new Date(now.getTime() - 1000 * 60 * 50 * 1); - const seventyMinuesAgo = new Date(now.getTime() - 1000 * 60 * 70 * 1); - const tenMinutesAfterNow = new Date(now.getTime() + 1000 * 60 * 10); - - // Range A: 2h10m ago - 50m ago (Sets 1 and 2) - // Range B: 70m ago - 10m after now (Sets 2 and 3) - const getResponse = await supertest - .get(DIFF_ENDPOINT) - .query({ - aFrom: twoHoursAndTenMinuesAgo, - aTo: fiftyMinuesAgo, - bFrom: seventyMinuesAgo, - bTo: tenMinutesAfterNow, - }) - .expect(200); - - expect(getResponse.body).to.have.property('onlyInA'); - expect(getResponse.body).to.have.property('onlyInB'); - expect(getResponse.body).to.have.property('inBoth'); - - getResponse.body.onlyInA.forEach((asset: any) => { - delete asset['@timestamp']; - }); - getResponse.body.onlyInB.forEach((asset: any) => { - delete asset['@timestamp']; - }); - getResponse.body.inBoth.forEach((asset: any) => { - delete asset['@timestamp']; - }); - - const sortByEan = (assets: any[]) => sortBy(assets, (asset) => asset['asset.ean']); - expect(sortByEan(getResponse.body.onlyInA)).to.eql(sortByEan(onlyInA)); - expect(sortByEan(getResponse.body.onlyInB)).to.eql(sortByEan(onlyInB)); - expect(sortByEan(getResponse.body.inBoth)).to.eql(sortByEan(inBoth)); - }); - - it('should reject requests with invalid datemath', async () => { - const getResponse = await supertest - .get(DIFF_ENDPOINT) - .query({ aFrom: 'now_1p', aTo: 'now_1p', bFrom: 'now_1p', bTo: 'now_1p' }) - .expect(400); - - expect(getResponse.body.message).to.equal( - '[request query]: Failed to validate: \n in /0/aFrom: "now_1p" does not match expected type Date\n in /0/aFrom: "now_1p" does not match expected type datemath\n in /0/aTo: "now_1p" does not match expected type Date\n in /0/aTo: "now_1p" does not match expected type datemath\n in /0/bFrom: "now_1p" does not match expected type Date\n in /0/bFrom: "now_1p" does not match expected type datemath\n in /0/bTo: "now_1p" does not match expected type Date\n in /0/bTo: "now_1p" does not match expected type datemath' - ); - }); - }); - }); -} diff --git a/x-pack/test/api_integration/apis/asset_manager/tests/assets_related.ts b/x-pack/test/api_integration/apis/asset_manager/tests/assets_related.ts deleted file mode 100644 index 58d4988fd7ab4..0000000000000 --- a/x-pack/test/api_integration/apis/asset_manager/tests/assets_related.ts +++ /dev/null @@ -1,375 +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 { pick } from 'lodash'; - -import { Asset, AssetWithoutTimestamp } from '@kbn/assetManager-plugin/common/types_api'; -import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../../ftr_provider_context'; -import { createSampleAssets, deleteSampleAssets, viewSampleAssetDocs } from './helpers'; -import { ASSETS_ENDPOINT } from './constants'; - -const RELATED_ASSETS_ENDPOINT = `${ASSETS_ENDPOINT}/related`; - -export default function ({ getService }: FtrProviderContext) { - const supertest = getService('supertest'); - - describe('asset management', () => { - let sampleAssetDocs: AssetWithoutTimestamp[] = []; - let relatedAssetBaseQuery = {}; - - before(async () => { - sampleAssetDocs = await viewSampleAssetDocs(supertest); - relatedAssetBaseQuery = { - size: sampleAssetDocs.length, - from: 'now-1d', - maxDistance: 5, - }; - }); - - beforeEach(async () => { - await deleteSampleAssets(supertest); - }); - - describe('GET /assets/related', () => { - describe('basic validation of all relations', () => { - const relations = [ - { - name: 'ancestors', - ean: 'host:node-101', - expectedRelatedEans: ['cluster:cluster-001'], - }, - { - name: 'descendants', - ean: 'cluster:cluster-001', - expectedRelatedEans: ['host:node-101', 'host:node-102', 'host:node-103'], - }, - { - name: 'references', - ean: 'pod:pod-200xrg1', - expectedRelatedEans: ['cluster:cluster-001'], - }, - ]; - - relations.forEach((relation) => { - it(`should return the ${relation.name} assets`, async () => { - await createSampleAssets(supertest); - - const getResponse = await supertest - .get(RELATED_ASSETS_ENDPOINT) - .query({ - relation: relation.name, - size: sampleAssetDocs.length, - from: 'now-1d', - ean: relation.ean, - maxDistance: 1, - }) - .expect(200); - - const relatedEans = getResponse.body.results[relation.name].map( - (asset: Asset) => asset['asset.ean'] - ); - expect(relatedEans).to.eql(relation.expectedRelatedEans); - }); - }); - }); - - describe('response validation', () => { - it('should return 404 if primary asset not found', async () => { - await supertest - .get(RELATED_ASSETS_ENDPOINT) - .query({ - ...relatedAssetBaseQuery, - relation: 'descendants', - ean: 'non-existing-ean', - }) - .expect(404); - }); - - it('should return the primary asset', async () => { - await createSampleAssets(supertest); - - const sampleCluster = sampleAssetDocs.find( - (asset) => asset['asset.id'] === 'cluster-002' - ); - - const getResponse = await supertest - .get(RELATED_ASSETS_ENDPOINT) - .query({ - ...relatedAssetBaseQuery, - relation: 'descendants', - ean: sampleCluster!['asset.ean'], - }) - .expect(200); - - const { - body: { results }, - } = getResponse; - delete results.primary['@timestamp']; - expect(results.primary).to.eql(sampleCluster); - }); - - it('should return empty assets when none matching', async () => { - await createSampleAssets(supertest); - - const sampleCluster = sampleAssetDocs.find( - (asset) => asset['asset.id'] === 'cluster-002' - ); - - const getResponse = await supertest - .get(RELATED_ASSETS_ENDPOINT) - .query({ - ...relatedAssetBaseQuery, - relation: 'descendants', - ean: sampleCluster!['asset.ean'], - }) - .expect(200); - - const { - body: { results }, - } = getResponse; - - expect(results).to.have.property('descendants'); - expect(results.descendants).to.have.length(0); - }); - - it('breaks circular dependency', async () => { - await createSampleAssets(supertest); - - // pods reference a node that references the pods - const sampleNode = sampleAssetDocs.find((asset) => asset['asset.id'] === 'pod-203ugg5'); - - const getResponse = await supertest - .get(RELATED_ASSETS_ENDPOINT) - .query({ - ...relatedAssetBaseQuery, - relation: 'references', - ean: sampleNode!['asset.ean'], - }) - .expect(200); - - const { - body: { results }, - } = getResponse; - expect( - results.references.map((asset: Asset) => pick(asset, ['asset.ean', 'distance'])) - ).to.eql([ - { 'asset.ean': 'host:node-203', distance: 1 }, - { 'asset.ean': 'pod:pod-203ugg9', distance: 2 }, - ]); - }); - - it('should reject requests with negative size parameter', async () => { - const getResponse = await supertest - .get(RELATED_ASSETS_ENDPOINT) - .query({ - ...relatedAssetBaseQuery, - relation: 'descendants', - ean: 'non-existing-ean', - size: -1, - }) - .expect(400); - - expect(getResponse.body.message).to.equal( - '[request query]: Failed to validate: \n in /0/size: -1 does not match expected type pipe(ToNumber, InRange)\n in /0/size: "-1" does not match expected type pipe(undefined, BooleanFromString)' - ); - }); - - it('should reject requests with size parameter greater than 100', async () => { - const getResponse = await supertest - .get(RELATED_ASSETS_ENDPOINT) - .query({ - ...relatedAssetBaseQuery, - relation: 'descendants', - ean: 'non-existing-ean', - size: 101, - }) - .expect(400); - - expect(getResponse.body.message).to.equal( - '[request query]: Failed to validate: \n in /0/size: 101 does not match expected type pipe(ToNumber, InRange)\n in /0/size: "101" does not match expected type pipe(undefined, BooleanFromString)' - ); - }); - - it('should reject requests with negative maxDistance parameter', async () => { - const getResponse = await supertest - .get(RELATED_ASSETS_ENDPOINT) - .query({ - ...relatedAssetBaseQuery, - relation: 'descendants', - ean: 'non-existing-ean', - maxDistance: -1, - }) - .expect(400); - - expect(getResponse.body.message).to.equal( - '[request query]: Failed to validate: \n in /0/maxDistance: -1 does not match expected type pipe(ToNumber, InRange)\n in /0/maxDistance: "-1" does not match expected type pipe(undefined, BooleanFromString)' - ); - }); - - it('should reject requests with size parameter maxDistance is greater than 5', async () => { - const getResponse = await supertest - .get(RELATED_ASSETS_ENDPOINT) - .query({ - ...relatedAssetBaseQuery, - relation: 'descendants', - ean: 'non-existing-ean', - maxDistance: 6, - }) - .expect(400); - - expect(getResponse.body.message).to.equal( - '[request query]: Failed to validate: \n in /0/maxDistance: 6 does not match expected type pipe(ToNumber, InRange)\n in /0/maxDistance: "6" does not match expected type pipe(undefined, BooleanFromString)' - ); - }); - - it('should reject requests with invalid from and to parameters', async () => { - const getResponse = await supertest - .get(RELATED_ASSETS_ENDPOINT) - .query({ - ...relatedAssetBaseQuery, - relation: 'descendants', - ean: 'non-existing-ean', - from: 'now_1p', - to: 'now_1p', - }) - .expect(400); - - expect(getResponse.body.message).to.equal( - '[request query]: Failed to validate: \n in /0/from: "now_1p" does not match expected type Date\n in /0/from: "now_1p" does not match expected type datemath\n in /1/to: "now_1p" does not match expected type Date\n in /1/to: "now_1p" does not match expected type datemath' - ); - }); - - it('should reject requests where time range is moving backwards in time', async () => { - const now = new Date(); - const isoNow = now.toISOString(); - const oneHourAgo = new Date(now.getTime() - 1000 * 60 * 60 * 1).toISOString(); - - const getResponse = await supertest - .get(RELATED_ASSETS_ENDPOINT) - .query({ - ...relatedAssetBaseQuery, - relation: 'descendants', - from: isoNow, - to: oneHourAgo, - maxDistance: 1, - ean: 'non-existing-ean', - }) - .expect(400); - expect(getResponse.body.message).to.equal( - `Time range cannot move backwards in time. "to" (${oneHourAgo}) is before "from" (${isoNow}).` - ); - }); - }); - - describe('no asset.type filters', () => { - it('should return all descendants of a provided ean at maxDistance 1', async () => { - await createSampleAssets(supertest); - - const sampleCluster = sampleAssetDocs.find( - (asset) => asset['asset.id'] === 'cluster-001' - ); - - const getResponse = await supertest - .get(RELATED_ASSETS_ENDPOINT) - .query({ - relation: 'descendants', - size: sampleAssetDocs.length, - from: 'now-1d', - ean: sampleCluster!['asset.ean'], - maxDistance: 1, - }) - .expect(200); - - const { - body: { results }, - } = getResponse; - expect(results.descendants).to.have.length(3); - expect(results.descendants.every((asset: { distance: number }) => asset.distance === 1)); - }); - - it('should return all descendants of a provided ean at maxDistance 2', async () => { - await createSampleAssets(supertest); - - const sampleCluster = sampleAssetDocs.find( - (asset) => asset['asset.id'] === 'cluster-001' - ); - - const getResponse = await supertest - .get(RELATED_ASSETS_ENDPOINT) - .query({ - relation: 'descendants', - size: sampleAssetDocs.length, - from: 'now-1d', - ean: sampleCluster!['asset.ean'], - maxDistance: 2, - }) - .expect(200); - - const { - body: { results }, - } = getResponse; - expect(results.descendants).to.have.length(12); - }); - }); - - describe('with asset.kind filters', () => { - it('should filter by the provided asset kind', async () => { - await createSampleAssets(supertest); - - const sampleCluster = sampleAssetDocs.find( - (asset) => asset['asset.id'] === 'cluster-001' - ); - - const getResponse = await supertest - .get(RELATED_ASSETS_ENDPOINT) - .query({ - relation: 'descendants', - size: sampleAssetDocs.length, - from: 'now-1d', - ean: sampleCluster!['asset.ean'], - maxDistance: 1, - kind: ['pod'], - }) - .expect(200); - - const { - body: { results }, - } = getResponse; - expect(results.descendants).to.have.length(0); - }); - - it('should return all descendants of a provided ean at maxDistance 2', async () => { - await createSampleAssets(supertest); - - const sampleCluster = sampleAssetDocs.find( - (asset) => asset['asset.id'] === 'cluster-001' - ); - - const getResponse = await supertest - .get(RELATED_ASSETS_ENDPOINT) - .query({ - relation: 'descendants', - size: sampleAssetDocs.length, - from: 'now-1d', - ean: sampleCluster!['asset.ean'], - maxDistance: 2, - kind: ['pod'], - }) - .expect(200); - - const { - body: { results }, - } = getResponse; - expect(results.descendants).to.have.length(9); - expect(results.descendants.every((asset: { distance: number }) => asset.distance === 2)); - expect(results.descendants.every((asset: Asset) => asset['asset.kind'] === 'pod')); - }); - }); - }); - }); -} diff --git a/x-pack/test/api_integration/apis/asset_manager/tests/containers.ts b/x-pack/test/api_integration/apis/asset_manager/tests/containers.ts new file mode 100644 index 0000000000000..9948244e48fe2 --- /dev/null +++ b/x-pack/test/api_integration/apis/asset_manager/tests/containers.ts @@ -0,0 +1,112 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { timerange, infra } from '@kbn/apm-synthtrace-client'; +import expect from '@kbn/expect'; +import { Asset } from '@kbn/assetManager-plugin/common/types_api'; +import * as routePaths from '@kbn/assetManager-plugin/common/constants_routes'; +import { FtrProviderContext } from '../types'; + +export default function ({ getService }: FtrProviderContext) { + const supertest = getService('supertest'); + const synthtrace = getService('infraSynthtraceEsClient'); + + describe(`GET ${routePaths.GET_CONTAINERS}`, () => { + const from = new Date(Date.now() - 1000 * 60 * 2).toISOString(); + const to = new Date().toISOString(); + + beforeEach(async () => { + await synthtrace.clean(); + }); + + it('should return container assets', async () => { + await synthtrace.index(generateContainersData({ from, to, count: 5 })); + + const response = await supertest + .get(routePaths.GET_CONTAINERS) + .query({ + from, + to, + }) + .expect(200); + + expect(response.body).to.have.property('containers'); + expect(response.body.containers.length).to.equal(5); + }); + + it('should return a specific container asset by EAN', async () => { + await synthtrace.index(generateContainersData({ from, to, count: 5 })); + const testEan = 'container:container-id-1'; + + const response = await supertest + .get(routePaths.GET_CONTAINERS) + .query({ + from, + to, + stringFilters: JSON.stringify({ ean: testEan }), + }) + .expect(200); + + expect(response.body).to.have.property('containers'); + expect(response.body.containers.length).to.equal(1); + expect(response.body.containers[0]['asset.ean']).to.equal(testEan); + }); + + it('should return a filtered list of container assets by ID wildcard pattern', async () => { + await synthtrace.index(generateContainersData({ from, to, count: 15 })); + const testIdPattern = '*id-1*'; + + const response = await supertest + .get(routePaths.GET_CONTAINERS) + .query({ + from, + to, + stringFilters: JSON.stringify({ id: testIdPattern }), + }) + .expect(200); + + expect(response.body).to.have.property('containers'); + expect(response.body.containers.length).to.equal(6); + + const ids = response.body.containers.map((result: Asset) => result['asset.id'][0]); + + expect(ids).to.eql([ + 'container-id-1', + 'container-id-10', + 'container-id-11', + 'container-id-12', + 'container-id-13', + 'container-id-14', + ]); + }); + }); +} + +function generateContainersData({ + from, + to, + count = 1, +}: { + from: string; + to: string; + count: number; +}) { + const range = timerange(from, to); + + const containers = Array(count) + .fill(0) + .map((_, idx) => + infra.container(`container-id-${idx}`, `container-uid-${idx + 1000}`, `node-name-${idx}`) + ); + + return range + .interval('1m') + .rate(1) + .generator((timestamp) => + containers.map((container) => container.metrics().timestamp(timestamp)) + ); +} diff --git a/x-pack/test/api_integration/apis/asset_manager/tests/hosts.ts b/x-pack/test/api_integration/apis/asset_manager/tests/hosts.ts index 1dab6373ddc9b..2459a2d2fb7b4 100644 --- a/x-pack/test/api_integration/apis/asset_manager/tests/hosts.ts +++ b/x-pack/test/api_integration/apis/asset_manager/tests/hosts.ts @@ -7,6 +7,7 @@ import { timerange, infra } from '@kbn/apm-synthtrace-client'; import expect from '@kbn/expect'; +import { Asset } from '@kbn/assetManager-plugin/common/types_api'; import { ASSETS_ENDPOINT } from './constants'; import { FtrProviderContext } from '../types'; @@ -17,13 +18,14 @@ export default function ({ getService }: FtrProviderContext) { const synthtrace = getService('infraSynthtraceEsClient'); describe('GET /assets/hosts', () => { + const from = new Date(Date.now() - 1000 * 60 * 2).toISOString(); + const to = new Date().toISOString(); + beforeEach(async () => { await synthtrace.clean(); }); it('should return hosts', async () => { - const from = new Date(Date.now() - 1000 * 60 * 2).toISOString(); - const to = new Date().toISOString(); await synthtrace.index(generateHostsData({ from, to, count: 5 })); const response = await supertest @@ -37,6 +39,52 @@ export default function ({ getService }: FtrProviderContext) { expect(response.body).to.have.property('hosts'); expect(response.body.hosts.length).to.equal(5); }); + + it('should return a specific host by EAN', async () => { + await synthtrace.index(generateHostsData({ from, to, count: 5 })); + const testEan = 'host:my-host-1'; + + const response = await supertest + .get(HOSTS_ASSETS_ENDPOINT) + .query({ + from, + to, + stringFilters: JSON.stringify({ ean: testEan }), + }) + .expect(200); + + expect(response.body).to.have.property('hosts'); + expect(response.body.hosts.length).to.equal(1); + expect(response.body.hosts[0]['asset.ean']).to.equal(testEan); + }); + + it('should return a filtered list of hosts by ID wildcard pattern', async () => { + await synthtrace.index(generateHostsData({ from, to, count: 15 })); + const testIdPattern = '*host-1*'; + + const response = await supertest + .get(HOSTS_ASSETS_ENDPOINT) + .query({ + from, + to, + stringFilters: JSON.stringify({ id: testIdPattern }), + }) + .expect(200); + + expect(response.body).to.have.property('hosts'); + expect(response.body.hosts.length).to.equal(6); + + const ids = response.body.hosts.map((result: Asset) => result['asset.id'][0]); + + expect(ids).to.eql([ + 'my-host-1', + 'my-host-10', + 'my-host-11', + 'my-host-12', + 'my-host-13', + 'my-host-14', + ]); + }); }); } diff --git a/x-pack/test/api_integration/apis/asset_manager/tests/index.ts b/x-pack/test/api_integration/apis/asset_manager/tests/index.ts index f64733fa2e062..e2ea53990b216 100644 --- a/x-pack/test/api_integration/apis/asset_manager/tests/index.ts +++ b/x-pack/test/api_integration/apis/asset_manager/tests/index.ts @@ -9,11 +9,9 @@ import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ loadTestFile }: FtrProviderContext) { describe('Asset Manager API Endpoints', () => { loadTestFile(require.resolve('./basics')); + loadTestFile(require.resolve('./containers')); loadTestFile(require.resolve('./hosts')); loadTestFile(require.resolve('./services')); loadTestFile(require.resolve('./sample_assets')); - loadTestFile(require.resolve('./assets')); - loadTestFile(require.resolve('./assets_diff')); - loadTestFile(require.resolve('./assets_related')); }); } diff --git a/x-pack/test/api_integration/apis/metrics_ui/inventory_threshold_alert.ts b/x-pack/test/api_integration/apis/metrics_ui/inventory_threshold_alert.ts index 8fc78999ae590..692672b29c09c 100644 --- a/x-pack/test/api_integration/apis/metrics_ui/inventory_threshold_alert.ts +++ b/x-pack/test/api_integration/apis/metrics_ui/inventory_threshold_alert.ts @@ -7,10 +7,7 @@ import expect from '@kbn/expect'; import { Comparator, InventoryMetricConditions } from '@kbn/infra-plugin/common/alerting/metrics'; -import { - InventoryItemType, - SnapshotMetricType, -} from '@kbn/infra-plugin/common/inventory_models/types'; +import { InventoryItemType, SnapshotMetricType } from '@kbn/metrics-data-access-plugin/common'; import { evaluateCondition } from '@kbn/infra-plugin/server/lib/alerting/inventory_metric_threshold/evaluate_condition'; import { InfraSource } from '@kbn/infra-plugin/server/lib/sources'; import { FtrProviderContext } from '../../ftr_provider_context'; diff --git a/x-pack/test/api_integration/apis/metrics_ui/metrics.ts b/x-pack/test/api_integration/apis/metrics_ui/metrics.ts index a1e4552df68fe..434238620f94c 100644 --- a/x-pack/test/api_integration/apis/metrics_ui/metrics.ts +++ b/x-pack/test/api_integration/apis/metrics_ui/metrics.ts @@ -9,7 +9,7 @@ import expect from '@kbn/expect'; import { first, last } from 'lodash'; import { InfraTimerangeInput } from '@kbn/infra-plugin/common/http_api/snapshot_api'; -import { InventoryMetric } from '@kbn/infra-plugin/common/inventory_models/types'; +import { InventoryMetric } from '@kbn/metrics-data-access-plugin/common'; import { NodeDetailsMetricDataResponse } from '@kbn/infra-plugin/common/http_api/node_details_api'; import { FtrProviderContext } from '../../ftr_provider_context'; diff --git a/x-pack/test/api_integration/apis/security/privileges.ts b/x-pack/test/api_integration/apis/security/privileges.ts index e6bc3b76f74ad..81cceb6561bd6 100644 --- a/x-pack/test/api_integration/apis/security/privileges.ts +++ b/x-pack/test/api_integration/apis/security/privileges.ts @@ -105,8 +105,6 @@ export default function ({ getService }: FtrProviderContext) { 'minimal_read', 'allFlappingSettings', 'readFlappingSettings', - 'allQueryDelaySettings', - 'readQueryDelaySettings', ], maintenanceWindow: ['all', 'read', 'minimal_all', 'minimal_read'], guidedOnboardingFeature: ['all', 'read', 'minimal_all', 'minimal_read'], diff --git a/x-pack/test/api_integration/apis/security/privileges_basic.ts b/x-pack/test/api_integration/apis/security/privileges_basic.ts index ecc37fdaf08ab..174ac2a3c8f66 100644 --- a/x-pack/test/api_integration/apis/security/privileges_basic.ts +++ b/x-pack/test/api_integration/apis/security/privileges_basic.ts @@ -187,8 +187,6 @@ export default function ({ getService }: FtrProviderContext) { 'minimal_read', 'allFlappingSettings', 'readFlappingSettings', - 'allQueryDelaySettings', - 'readQueryDelaySettings', ], maintenanceWindow: ['all', 'read', 'minimal_all', 'minimal_read'], guidedOnboardingFeature: ['all', 'read', 'minimal_all', 'minimal_read'], diff --git a/x-pack/test/apm_api_integration/tests/alerts/anomaly_alert.spec.ts b/x-pack/test/apm_api_integration/tests/alerts/anomaly_alert.spec.ts index cae769750b4cc..e7e29c34c6634 100644 --- a/x-pack/test/apm_api_integration/tests/alerts/anomaly_alert.spec.ts +++ b/x-pack/test/apm_api_integration/tests/alerts/anomaly_alert.spec.ts @@ -6,7 +6,7 @@ */ import moment from 'moment'; -import { ApmRuleType } from '@kbn/apm-plugin/common/rules/apm_rule_types'; +import { ApmRuleType } from '@kbn/rule-data-utils'; import { apm, timerange } from '@kbn/apm-synthtrace-client'; import expect from '@kbn/expect'; import { range } from 'lodash'; diff --git a/x-pack/test/apm_api_integration/tests/alerts/error_count_threshold.spec.ts b/x-pack/test/apm_api_integration/tests/alerts/error_count_threshold.spec.ts index 1cfcbc165b17f..239cff2e98af5 100644 --- a/x-pack/test/apm_api_integration/tests/alerts/error_count_threshold.spec.ts +++ b/x-pack/test/apm_api_integration/tests/alerts/error_count_threshold.spec.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { ApmRuleType } from '@kbn/apm-plugin/common/rules/apm_rule_types'; +import { ApmRuleType } from '@kbn/rule-data-utils'; import { errorCountActionVariables } from '@kbn/apm-plugin/server/routes/alerts/rule_types/error_count/register_error_count_rule_type'; import { apm, timerange } from '@kbn/apm-synthtrace-client'; import { getErrorGroupingKey } from '@kbn/apm-synthtrace-client/src/lib/apm/instance'; diff --git a/x-pack/test/apm_api_integration/tests/alerts/helpers/alerting_api_helper.ts b/x-pack/test/apm_api_integration/tests/alerts/helpers/alerting_api_helper.ts index 53d8819ef1745..42fca92b47540 100644 --- a/x-pack/test/apm_api_integration/tests/alerts/helpers/alerting_api_helper.ts +++ b/x-pack/test/apm_api_integration/tests/alerts/helpers/alerting_api_helper.ts @@ -9,7 +9,7 @@ import { Client, errors } from '@elastic/elasticsearch'; import { ParsedTechnicalFields } from '@kbn/rule-registry-plugin/common'; import pRetry from 'p-retry'; import type { SuperTest, Test } from 'supertest'; -import { ApmRuleType } from '@kbn/apm-plugin/common/rules/apm_rule_types'; +import { ApmRuleType } from '@kbn/rule-data-utils'; import { ApmRuleParamsType } from '@kbn/apm-plugin/common/rules/schema'; import { ApmDocumentType } from '@kbn/apm-plugin/common/document_type'; import { RollupInterval } from '@kbn/apm-plugin/common/rollup'; @@ -199,6 +199,7 @@ export async function createIndexConnector({ }, connector_type_id: '.index', }); + return body.id as string; } @@ -228,19 +229,31 @@ export function getIndexAction({ }; } -export async function deleteActionConnector({ +export async function deleteAllActionConnectors({ supertest, es, - actionId, }: { supertest: SuperTest; es: Client; +}): Promise { + const res = await supertest.get(`/api/actions/connectors`); + + const body = res.body as Array<{ id: string; connector_type_id: string; name: string }>; + return Promise.all( + body.map(({ id }) => { + return deleteActionConnector({ supertest, actionId: id }); + }) + ); +} + +async function deleteActionConnector({ + supertest, + actionId, +}: { + supertest: SuperTest; actionId: string; }) { - return Promise.all([ - await supertest.delete(`/api/actions/connector/${actionId}`).set('kbn-xsrf', 'foo'), - await deleteActionConnectorIndex(es), - ]); + return supertest.delete(`/api/actions/connector/${actionId}`).set('kbn-xsrf', 'foo'); } export async function deleteActionConnectorIndex(es: Client) { diff --git a/x-pack/test/apm_api_integration/tests/alerts/helpers/cleanup_rule_and_alert_state.ts b/x-pack/test/apm_api_integration/tests/alerts/helpers/cleanup_rule_and_alert_state.ts index 144446a28b3d7..ae97266ee084c 100644 --- a/x-pack/test/apm_api_integration/tests/alerts/helpers/cleanup_rule_and_alert_state.ts +++ b/x-pack/test/apm_api_integration/tests/alerts/helpers/cleanup_rule_and_alert_state.ts @@ -13,6 +13,7 @@ import { deleteApmRules, deleteApmAlerts, deleteActionConnectorIndex, + deleteAllActionConnectors, } from './alerting_api_helper'; export async function cleanupRuleAndAlertState({ @@ -26,10 +27,11 @@ export async function cleanupRuleAndAlertState({ }) { try { await Promise.all([ - await deleteActionConnectorIndex(es), - await deleteApmRules(supertest), - await deleteApmAlerts(es), - await clearKibanaApmEventLog(es), + deleteApmRules(supertest), + deleteApmAlerts(es), + clearKibanaApmEventLog(es), + deleteActionConnectorIndex(es), + deleteAllActionConnectors({ supertest, es }), ]); } catch (e) { logger.error(`An error occured while cleaning up the state: ${e}`); diff --git a/x-pack/test/apm_api_integration/tests/alerts/transaction_duration.spec.ts b/x-pack/test/apm_api_integration/tests/alerts/transaction_duration.spec.ts index bb8c9833bbc6d..c4b5110e42fb4 100644 --- a/x-pack/test/apm_api_integration/tests/alerts/transaction_duration.spec.ts +++ b/x-pack/test/apm_api_integration/tests/alerts/transaction_duration.spec.ts @@ -5,7 +5,8 @@ * 2.0. */ -import { AggregationType, ApmRuleType } from '@kbn/apm-plugin/common/rules/apm_rule_types'; +import { AggregationType } from '@kbn/apm-plugin/common/rules/apm_rule_types'; +import { ApmRuleType } from '@kbn/rule-data-utils'; import { transactionDurationActionVariables } from '@kbn/apm-plugin/server/routes/alerts/rule_types/transaction_duration/register_transaction_duration_rule_type'; import { apm, timerange } from '@kbn/apm-synthtrace-client'; import expect from '@kbn/expect'; diff --git a/x-pack/test/apm_api_integration/tests/alerts/transaction_error_rate.spec.ts b/x-pack/test/apm_api_integration/tests/alerts/transaction_error_rate.spec.ts index 056ee4e272d61..a3f69827cf7a8 100644 --- a/x-pack/test/apm_api_integration/tests/alerts/transaction_error_rate.spec.ts +++ b/x-pack/test/apm_api_integration/tests/alerts/transaction_error_rate.spec.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { ApmRuleType } from '@kbn/apm-plugin/common/rules/apm_rule_types'; +import { ApmRuleType } from '@kbn/rule-data-utils'; import { transactionErrorRateActionVariables } from '@kbn/apm-plugin/server/routes/alerts/rule_types/transaction_error_rate/register_transaction_error_rate_rule_type'; import { apm, timerange } from '@kbn/apm-synthtrace-client'; import expect from '@kbn/expect'; diff --git a/x-pack/test/apm_api_integration/tests/service_groups/service_group_count/service_group_count.spec.ts b/x-pack/test/apm_api_integration/tests/service_groups/service_group_count/service_group_count.spec.ts index 14a5af9478b0b..cf46d4771d6cb 100644 --- a/x-pack/test/apm_api_integration/tests/service_groups/service_group_count/service_group_count.spec.ts +++ b/x-pack/test/apm_api_integration/tests/service_groups/service_group_count/service_group_count.spec.ts @@ -4,14 +4,12 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import { AggregationType, ApmRuleType } from '@kbn/apm-plugin/common/rules/apm_rule_types'; +import { AggregationType } from '@kbn/apm-plugin/common/rules/apm_rule_types'; +import { ApmRuleType } from '@kbn/rule-data-utils'; import expect from '@kbn/expect'; import { FtrProviderContext } from '../../../common/ftr_provider_context'; -import { - createApmRule, - deleteRuleById, - deleteApmAlerts, -} from '../../alerts/helpers/alerting_api_helper'; +import { createApmRule } from '../../alerts/helpers/alerting_api_helper'; +import { cleanupRuleAndAlertState } from '../../alerts/helpers/cleanup_rule_and_alert_state'; import { waitForActiveApmAlert } from '../../alerts/helpers/wait_for_active_apm_alerts'; import { createServiceGroupApi, @@ -92,8 +90,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { }); after(async () => { - await deleteRuleById({ supertest, ruleId }); - await deleteApmAlerts(es); + await cleanupRuleAndAlertState({ es, supertest, logger: log }); }); it('returns the correct number of alerts', async () => { diff --git a/x-pack/test/apm_api_integration/tests/services/service_alerts.spec.ts b/x-pack/test/apm_api_integration/tests/services/service_alerts.spec.ts index 0b611042d5acc..acef21aab3317 100644 --- a/x-pack/test/apm_api_integration/tests/services/service_alerts.spec.ts +++ b/x-pack/test/apm_api_integration/tests/services/service_alerts.spec.ts @@ -5,18 +5,14 @@ * 2.0. */ import expect from '@kbn/expect'; -import { AggregationType, ApmRuleType } from '@kbn/apm-plugin/common/rules/apm_rule_types'; +import { AggregationType } from '@kbn/apm-plugin/common/rules/apm_rule_types'; +import { ApmRuleType } from '@kbn/rule-data-utils'; import { apm, timerange } from '@kbn/apm-synthtrace-client'; import { FtrProviderContext } from '../../common/ftr_provider_context'; -import { - createApmRule, - deleteApmAlerts, - runRuleSoon, - deleteRuleById, - ApmAlertFields, -} from '../alerts/helpers/alerting_api_helper'; +import { createApmRule, runRuleSoon, ApmAlertFields } from '../alerts/helpers/alerting_api_helper'; import { waitForActiveRule } from '../alerts/helpers/wait_for_active_rule'; import { waitForAlertsForRule } from '../alerts/helpers/wait_for_alerts_for_rule'; +import { cleanupRuleAndAlertState } from '../alerts/helpers/cleanup_rule_and_alert_state'; export default function ServiceAlerts({ getService }: FtrProviderContext) { const registry = getService('registry'); @@ -28,6 +24,7 @@ export default function ServiceAlerts({ getService }: FtrProviderContext) { const start = Date.now() - dayInMs; const end = Date.now() + dayInMs; const goService = 'synth-go'; + const logger = getService('log'); async function getServiceAlerts({ serviceName, @@ -130,8 +127,7 @@ export default function ServiceAlerts({ getService }: FtrProviderContext) { }); after(async () => { - await deleteRuleById({ supertest, ruleId }); - await deleteApmAlerts(es); + await cleanupRuleAndAlertState({ es, supertest, logger }); }); it('checks if rule is active', async () => { @@ -140,10 +136,7 @@ export default function ServiceAlerts({ getService }: FtrProviderContext) { }); it('should successfully run the rule', async () => { - const response = await runRuleSoon({ - ruleId, - supertest, - }); + const response = await runRuleSoon({ ruleId, supertest }); expect(response.status).to.be(204); }); diff --git a/x-pack/test/apm_api_integration/tests/transactions/transactions_groups_alerts.spec.ts b/x-pack/test/apm_api_integration/tests/transactions/transactions_groups_alerts.spec.ts index 23c680fd81ae7..0cb9f194dfa51 100644 --- a/x-pack/test/apm_api_integration/tests/transactions/transactions_groups_alerts.spec.ts +++ b/x-pack/test/apm_api_integration/tests/transactions/transactions_groups_alerts.spec.ts @@ -11,17 +11,13 @@ import { LatencyAggregationType } from '@kbn/apm-plugin/common/latency_aggregati import { ApmDocumentType, ApmTransactionDocumentType } from '@kbn/apm-plugin/common/document_type'; import { RollupInterval } from '@kbn/apm-plugin/common/rollup'; import { apm, timerange } from '@kbn/apm-synthtrace-client'; -import { AggregationType, ApmRuleType } from '@kbn/apm-plugin/common/rules/apm_rule_types'; +import { AggregationType } from '@kbn/apm-plugin/common/rules/apm_rule_types'; +import { ApmRuleType } from '@kbn/rule-data-utils'; import { FtrProviderContext } from '../../common/ftr_provider_context'; -import { - createApmRule, - runRuleSoon, - deleteApmAlerts, - deleteRuleById, - ApmAlertFields, -} from '../alerts/helpers/alerting_api_helper'; +import { createApmRule, runRuleSoon, ApmAlertFields } from '../alerts/helpers/alerting_api_helper'; import { waitForActiveRule } from '../alerts/helpers/wait_for_active_rule'; import { waitForAlertsForRule } from '../alerts/helpers/wait_for_alerts_for_rule'; +import { cleanupRuleAndAlertState } from '../alerts/helpers/cleanup_rule_and_alert_state'; type TransactionsGroupsMainStatistics = APIReturnType<'GET /internal/apm/services/{serviceName}/transactions/groups/main_statistics'>; @@ -36,6 +32,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { const dayInMs = 24 * 60 * 60 * 1000; const start = Date.now() - dayInMs; const end = Date.now() + dayInMs; + const logger = getService('log'); async function getTransactionGroups(overrides?: { path?: { @@ -170,8 +167,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { }); after(async () => { - await deleteRuleById({ supertest, ruleId }); - await deleteApmAlerts(es); + await cleanupRuleAndAlertState({ es, supertest, logger }); }); it('checks if rule is active', async () => { @@ -244,8 +240,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { }); after(async () => { - await deleteRuleById({ supertest, ruleId }); - await deleteApmAlerts(es); + await cleanupRuleAndAlertState({ es, supertest, logger }); }); it('checks if rule is active', async () => { @@ -319,8 +314,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { }); after(async () => { - await deleteRuleById({ supertest, ruleId }); - await deleteApmAlerts(es); + await cleanupRuleAndAlertState({ es, supertest, logger }); }); it('checks if rule is active', async () => { diff --git a/x-pack/test/cases_api_integration/security_and_spaces/tests/common/cases/find_cases.ts b/x-pack/test/cases_api_integration/security_and_spaces/tests/common/cases/find_cases.ts index 7b58f32fe630f..bd1b865512856 100644 --- a/x-pack/test/cases_api_integration/security_and_spaces/tests/common/cases/find_cases.ts +++ b/x-pack/test/cases_api_integration/security_and_spaces/tests/common/cases/find_cases.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { v1 as uuidv1 } from 'uuid'; +import { v4 as uuidv4 } from 'uuid'; import expect from '@kbn/expect'; import { @@ -387,7 +387,7 @@ export default ({ getService }: FtrProviderContext): void => { }); it('should successfully find a case with a valid uuid in title', async () => { - const uuid = uuidv1(); + const uuid = uuidv4(); await createCase(supertest, { ...postCaseReq, title: uuid }); const cases = await findCases({ @@ -400,7 +400,7 @@ export default ({ getService }: FtrProviderContext): void => { }); it('should successfully find a case with a valid uuid in description', async () => { - const uuid = uuidv1(); + const uuid = uuidv4(); await createCase(supertest, { ...postCaseReq, description: uuid }); const cases = await findCases({ diff --git a/x-pack/test/cloud_security_posture_functional/config.ts b/x-pack/test/cloud_security_posture_functional/config.ts index 53d87d2378db5..96698bbbb007e 100644 --- a/x-pack/test/cloud_security_posture_functional/config.ts +++ b/x-pack/test/cloud_security_posture_functional/config.ts @@ -38,8 +38,10 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) { * 2. merge the updated version number change to kibana */ `--xpack.fleet.packages.0.name=cloud_security_posture`, - `--xpack.fleet.packages.0.version=1.6.0`, + `--xpack.fleet.packages.0.version=1.6.5`, // `--xpack.fleet.registryUrl=https://localhost:8080`, + `--xpack.fleet.agents.fleet_server.hosts=["https://ftr.kibana:8220"]`, + `--xpack.fleet.internal.fleetServerStandalone=true`, ], }, }; diff --git a/x-pack/test/cloud_security_posture_functional/page_objects/add_cis_integration_form_page.ts b/x-pack/test/cloud_security_posture_functional/page_objects/add_cis_integration_form_page.ts index 795c2edb62dd4..0500a68e8654d 100644 --- a/x-pack/test/cloud_security_posture_functional/page_objects/add_cis_integration_form_page.ts +++ b/x-pack/test/cloud_security_posture_functional/page_objects/add_cis_integration_form_page.ts @@ -13,6 +13,15 @@ export function AddCisIntegrationFormPageProvider({ }: FtrProviderContext) { const testSubjects = getService('testSubjects'); const PageObjects = getPageObjects(['common', 'header']); + const browser = getService('browser'); + + const cisAws = { + getUrlValueInEditPage: async () => { + /* Newly added/edited integration always shows up on top by default as such we can just always click the most top if we want to check for the latest one */ + const fieldValue = await (await testSubjects.find('externalLink')).getAttribute('href'); + return fieldValue; + }, + }; const cisGcp = { getIntegrationFormEntirePage: () => testSubjects.find('dataCollectionSetupStep'), @@ -37,6 +46,11 @@ export function AddCisIntegrationFormPageProvider({ await optionToBeClicked.click(); }, + clickSaveIntegrationButton: async () => { + const optionToBeClicked = await cisGcp.findOptionInPage('saveIntegration'); + await optionToBeClicked.click(); + }, + getPostInstallModal: async () => { return await testSubjects.find('confirmModalTitleText'); }, @@ -80,6 +94,35 @@ export function AddCisIntegrationFormPageProvider({ const fieldValue = await (await testSubjects.find(field)).getAttribute('value'); return fieldValue; }, + + doesStringExistInCodeBlock: async (str: string) => { + const flyout = await testSubjects.find('agentEnrollmentFlyout'); + const codeBlock = await flyout.findByXpath('//code'); + const commandsToBeCopied = await codeBlock.getVisibleText(); + return commandsToBeCopied.includes(str); + }, + + getFieldValueInAddAgentFlyout: async (field: string, value: string) => { + /* Newly added/edited integration always shows up on top by default as such we can just always click the most top if we want to check for the latest one */ + const integrationList = await testSubjects.findAll('agentEnrollmentFlyout'); + await integrationList[0].click(); + await PageObjects.header.waitUntilLoadingHasFinished(); + const fieldValue = await (await testSubjects.find(field)).getAttribute(value); + return fieldValue; + }, + }; + + const isRadioButtonChecked = async (selector: string) => { + const page = await testSubjects.find('dataCollectionSetupStep'); + const findCheckedButton = await page.findAllByCssSelector(`input[id="${selector}"]:checked`); + if (findCheckedButton.length === 0) return false; + return true; + }; + + const getUrlOnPostInstallModal = async () => { + /* Newly added/edited integration always shows up on top by default as such we can just always click the most top if we want to check for the latest one */ + const fieldValue = await (await testSubjects.find('externalLink')).getAttribute('href'); + return fieldValue; }; const navigateToAddIntegrationCspmPage = async () => { @@ -90,6 +133,14 @@ export function AddCisIntegrationFormPageProvider({ ); }; + const navigateToAddIntegrationCnvmPage = async () => { + await PageObjects.common.navigateToUrl( + 'fleet', // Defined in Security Solution plugin + 'integrations/cloud_security_posture/add-integration/vuln_mgmt', + { shouldUseHashForSubUrl: false } + ); + }; + const navigateToIntegrationCspList = async () => { await PageObjects.common.navigateToActualUrl( 'integrations', // Defined in Security Solution plugin @@ -97,9 +148,43 @@ export function AddCisIntegrationFormPageProvider({ ); }; + const clickPolicyToBeEdited = async (name: string) => { + const table = await testSubjects.find('integrationPolicyTable'); + const integrationToBeEdited = await table.findByXpath(`//text()="${name}"`); + await integrationToBeEdited.click(); + }; + + const clickFirstElementOnIntegrationTable = async () => { + const integrationList = await testSubjects.findAll('integrationNameLink'); + await integrationList[0].click(); + }; + + const clickFirstElementOnIntegrationTableAddAgent = async () => { + const integrationList = await testSubjects.findAll('addAgentButton'); + await integrationList[0].click(); + }; + + const clickLaunchAndGetCurrentUrl = async (buttonId: string, tabNumber: number) => { + const button = await testSubjects.find(buttonId); + await button.click(); + await browser.switchTab(tabNumber); + await new Promise((r) => setTimeout(r, 3000)); + const currentUrl = await browser.getCurrentUrl(); + await browser.switchTab(0); + return currentUrl; + }; + return { + cisAws, cisGcp, navigateToAddIntegrationCspmPage, + navigateToAddIntegrationCnvmPage, navigateToIntegrationCspList, + getUrlOnPostInstallModal, + isRadioButtonChecked, + clickPolicyToBeEdited, + clickFirstElementOnIntegrationTable, + clickFirstElementOnIntegrationTableAddAgent, + clickLaunchAndGetCurrentUrl, }; } diff --git a/x-pack/test/cloud_security_posture_functional/pages/cis_integration.ts b/x-pack/test/cloud_security_posture_functional/pages/cis_integration.ts index 20f85163521a7..eb121f33f1278 100644 --- a/x-pack/test/cloud_security_posture_functional/pages/cis_integration.ts +++ b/x-pack/test/cloud_security_posture_functional/pages/cis_integration.ts @@ -9,6 +9,7 @@ import expect from '@kbn/expect'; import type { FtrProviderContext } from '../ftr_provider_context'; const CIS_GCP_OPTION_TEST_ID = 'cisGcpTestId'; +const CIS_AWS_OPTION_TEST_ID = 'cisAwsTestId'; const GCP_ORGANIZATION_TEST_ID = 'gcpOrganizationAccountTestId'; const GCP_SINGLE_ACCOUNT_TEST_ID = 'gcpSingleAccountTestId'; const GCP_CLOUD_SHELL_TEST_ID = 'gcpGoogleCloudShellOptionTestId'; @@ -41,6 +42,87 @@ export default function (providerContext: FtrProviderContext) { await kibanaServer.savedObjects.cleanStandardList(); }); + describe('CNVM AWS', () => { + it('Hyperlink on PostInstallation Modal should have the correct URL', async () => { + await cisIntegration.navigateToAddIntegrationCnvmPage(); + await cisIntegrationGcp.clickSaveButton(); + pageObjects.header.waitUntilLoadingHasFinished(); + expect( + (await cisIntegration.getUrlOnPostInstallModal()) === + 'https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cfn-whatis-howdoesitwork.html' + ); + }); + + it('On Add Agent modal there should be modal that has Cloud Formation details as well as button that redirects user to Cloud formation page on AWS upon clicking them ', async () => { + await cisIntegration.navigateToIntegrationCspList(); + await cisIntegration.clickFirstElementOnIntegrationTableAddAgent(); + expect( + ( + await cisIntegrationGcp.getFieldValueInAddAgentFlyout( + 'launchCloudFormationButtonAgentFlyoutTestId', + 'href' + ) + ).includes('https://console.aws.amazon.com/cloudformation/') + ).to.be(true); + }); + + it('Clicking on Launch CloudFormation on post intall modal should lead user to Cloud Formation page', async () => { + await cisIntegration.navigateToAddIntegrationCnvmPage(); + await cisIntegrationGcp.clickSaveButton(); + pageObjects.header.waitUntilLoadingHasFinished(); + expect( + ( + await cisIntegration.clickLaunchAndGetCurrentUrl( + 'confirmCloudFormationModalConfirmButton', + 1 + ) + ).includes('console.aws.amazon.com%2Fcloudformation') + ).to.be(true); + }); + }); + + describe('CIS_AWS', () => { + it('Initial form state, AWS Org account, and CloudFormation should be selected by default', async () => { + expect((await cisIntegration.isRadioButtonChecked('cloudbeat/cis_aws')) === true); + expect((await cisIntegration.isRadioButtonChecked('organization-account')) === true); + expect((await cisIntegration.isRadioButtonChecked('cloud_formation')) === true); + }); + it('Hyperlink on PostInstallation Modal should have the correct URL', async () => { + await cisIntegrationGcp.clickOptionButton(CIS_AWS_OPTION_TEST_ID); + await cisIntegrationGcp.clickSaveButton(); + pageObjects.header.waitUntilLoadingHasFinished(); + expect( + (await cisIntegration.getUrlOnPostInstallModal()) === + 'https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cfn-whatis-howdoesitwork.html' + ); + }); + it('On Add Agent modal there should be modal that has Cloud Formation details as well as button that redirects user to Cloud formation page on AWS upon clicking them ', async () => { + await cisIntegration.navigateToIntegrationCspList(); + await cisIntegration.clickFirstElementOnIntegrationTableAddAgent(); + expect( + ( + await cisIntegrationGcp.getFieldValueInAddAgentFlyout( + 'launchCloudFormationButtonAgentFlyoutTestId', + 'href' + ) + ).includes('https://console.aws.amazon.com/cloudformation/') + ).to.be(true); + }); + it('Clicking on Launch CloudFormation on post intall modal should lead user to Cloud Formation page', async () => { + await cisIntegrationGcp.clickOptionButton(CIS_AWS_OPTION_TEST_ID); + await cisIntegrationGcp.clickSaveButton(); + pageObjects.header.waitUntilLoadingHasFinished(); + expect( + ( + await cisIntegration.clickLaunchAndGetCurrentUrl( + 'confirmCloudFormationModalConfirmButton', + 2 + ) + ).includes('console.aws.amazon.com%2Fcloudformation') + ).to.be(true); + }); + }); + describe('CIS_GCP Organization', () => { it('Switch between Manual and Google cloud shell', async () => { await cisIntegrationGcp.clickOptionButton(CIS_GCP_OPTION_TEST_ID); @@ -93,6 +175,15 @@ export default function (providerContext: FtrProviderContext) { ).to.be(true); }); + it('Add Agent FLyout - Post Installation Google Cloud Shell modal pops up after user clicks on Save button when adding integration, when there are Project ID or Organization ID provided, it should use that value', async () => { + await cisIntegration.navigateToIntegrationCspList(); + await cisIntegration.clickFirstElementOnIntegrationTableAddAgent(); + expect(await cisIntegrationGcp.doesStringExistInCodeBlock('PRJ_NAME_TEST')).to.be(true); + expect(await cisIntegrationGcp.doesStringExistInCodeBlock('ORG_ID=ORG_NAME_TEST')).to.be( + true + ); + }); + it('Organization ID field on cloud shell command should only be shown if user chose Google Cloud Shell, if user chose Single Account it shouldn not show up', async () => { await cisIntegrationGcp.clickOptionButton(CIS_GCP_OPTION_TEST_ID); await cisIntegrationGcp.clickOptionButton(GCP_SINGLE_ACCOUNT_TEST_ID); @@ -104,6 +195,30 @@ export default function (providerContext: FtrProviderContext) { true ); }); + + it('Hyperlink on PostInstallation Modal should have the correct URL', async () => { + await cisIntegrationGcp.clickOptionButton(CIS_GCP_OPTION_TEST_ID); + await cisIntegrationGcp.clickSaveButton(); + pageObjects.header.waitUntilLoadingHasFinished(); + expect( + (await cisIntegration.getUrlOnPostInstallModal()) === + 'https://cloud.google.com/shell/docs' + ); + }); + + it('Clicking on Launch CloudShell on post intall modal should lead user to CloudShell page', async () => { + await cisIntegrationGcp.clickOptionButton(CIS_GCP_OPTION_TEST_ID); + await cisIntegrationGcp.clickSaveButton(); + pageObjects.header.waitUntilLoadingHasFinished(); + expect( + ( + await cisIntegration.clickLaunchAndGetCurrentUrl( + 'confirmGoogleCloudShellModalConfirmButton', + 3 + ) + ).includes('shell.cloud.google.com%2Fcloudshell') + ).to.be(true); + }); }); describe('CIS_GCP Single', () => { @@ -117,14 +232,12 @@ export default function (providerContext: FtrProviderContext) { true ); }); - it('Post Installation Google Cloud Shell modal pops up after user clicks on Save button when adding integration, when there are Project ID, it should use that value', async () => { const projectName = 'PRJ_NAME_TEST'; await cisIntegrationGcp.clickOptionButton(CIS_GCP_OPTION_TEST_ID); await cisIntegrationGcp.clickOptionButton(GCP_SINGLE_ACCOUNT_TEST_ID); await cisIntegrationGcp.clickOptionButton(GCP_CLOUD_SHELL_TEST_ID); await cisIntegrationGcp.fillInTextField('project_id_test_id', projectName); - await cisIntegrationGcp.clickSaveButton(); pageObjects.header.waitUntilLoadingHasFinished(); expect( @@ -132,7 +245,26 @@ export default function (providerContext: FtrProviderContext) { true ).to.be(true); }); - + it('Add Agent FLyout - Organization ID field on cloud shell command should only be shown if user chose Google Cloud Shell, if user chose Single Account it shouldn not show up', async () => { + await cisIntegration.navigateToIntegrationCspList(); + await cisIntegration.clickFirstElementOnIntegrationTableAddAgent(); + expect(await cisIntegrationGcp.doesStringExistInCodeBlock('PRJ_NAME_TEST')).to.be(true); + expect(await cisIntegrationGcp.doesStringExistInCodeBlock('ORG_ID=ORG_NAME_TEST')).to.be( + false + ); + }); + it('On add agent modal, if user chose Google Cloud Shell as their setup access; a google cloud shell modal should show up and clicking on the launch button will redirect user to Google cloud shell page', async () => { + await cisIntegration.navigateToIntegrationCspList(); + await cisIntegration.clickFirstElementOnIntegrationTableAddAgent(); + expect( + ( + await cisIntegrationGcp.getFieldValueInAddAgentFlyout( + 'launchGoogleCloudShellButtonAgentFlyoutTestId', + 'href' + ) + ).includes('https://shell.cloud.google.com/cloudshell/') + ).to.be(true); + }); it('Users are able to add CIS_GCP Integration with Manual settings using Credentials File', async () => { const projectName = 'PRJ_NAME_TEST'; const credentialFileName = 'CRED_FILE_TEST_NAME'; @@ -141,7 +273,6 @@ export default function (providerContext: FtrProviderContext) { await cisIntegrationGcp.clickOptionButton(GCP_MANUAL_TEST_ID); await cisIntegrationGcp.fillInTextField(PRJ_ID_TEST_ID, projectName); await cisIntegrationGcp.fillInTextField(CREDENTIALS_FILE_TEST_ID, credentialFileName); - await cisIntegrationGcp.clickSaveButton(); pageObjects.header.waitUntilLoadingHasFinished(); expect((await cisIntegrationGcp.getPostInstallModal()) !== undefined).to.be(true); @@ -151,7 +282,23 @@ export default function (providerContext: FtrProviderContext) { credentialFileName ).to.be(true); }); - + it('Users are able to switch credentials_type from/to Credential JSON fields ', async () => { + const credentialJsonName = 'CRED_JSON_TEST_NAME'; + await cisIntegration.navigateToIntegrationCspList(); + await cisIntegration.clickFirstElementOnIntegrationTable(); + await cisIntegrationGcp.chooseDropDown( + CREDENTIALS_TYPE_TEST_ID, + 'credentials_json_option_test_id' + ); + await cisIntegrationGcp.fillInTextField(CREDENTIALS_JSON_TEST_ID, credentialJsonName); + await cisIntegrationGcp.clickSaveIntegrationButton(); + pageObjects.header.waitUntilLoadingHasFinished(); + await cisIntegration.navigateToIntegrationCspList(); + expect( + (await cisIntegrationGcp.getFieldValueInEditPage(CREDENTIALS_JSON_TEST_ID)) === + credentialJsonName + ).to.be(true); + }); it('Users are able to add CIS_GCP Integration with Manual settings using Credentials JSON', async () => { const projectName = 'PRJ_NAME_TEST'; const credentialJsonName = 'CRED_JSON_TEST_NAME'; @@ -164,7 +311,6 @@ export default function (providerContext: FtrProviderContext) { 'credentials_json_option_test_id' ); await cisIntegrationGcp.fillInTextField(CREDENTIALS_JSON_TEST_ID, credentialJsonName); - await cisIntegrationGcp.clickSaveButton(); pageObjects.header.waitUntilLoadingHasFinished(); expect((await cisIntegrationGcp.getPostInstallModal()) !== undefined).to.be(true); @@ -174,6 +320,23 @@ export default function (providerContext: FtrProviderContext) { credentialJsonName ).to.be(true); }); + it('Users are able to switch credentials_type from/to Credential File fields ', async () => { + const credentialFileName = 'CRED_FILE_TEST_NAME'; + await cisIntegration.navigateToIntegrationCspList(); + await cisIntegration.clickFirstElementOnIntegrationTable(); + await cisIntegrationGcp.chooseDropDown( + CREDENTIALS_TYPE_TEST_ID, + 'credentials_file_option_test_id' + ); + await cisIntegrationGcp.fillInTextField(CREDENTIALS_FILE_TEST_ID, credentialFileName); + await cisIntegrationGcp.clickSaveIntegrationButton(); + pageObjects.header.waitUntilLoadingHasFinished(); + await cisIntegration.navigateToIntegrationCspList(); + expect( + (await cisIntegrationGcp.getFieldValueInEditPage(CREDENTIALS_FILE_TEST_ID)) === + credentialFileName + ).to.be(true); + }); }); }); } diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/index.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/index.ts index 1c9c874127660..94ba07b31bddf 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/index.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/index.ts @@ -17,7 +17,6 @@ export default ({ loadTestFile }: FtrProviderContext): void => { loadTestFile(require.resolve('./aliases')); loadTestFile(require.resolve('./check_privileges')); loadTestFile(require.resolve('./create_index')); - loadTestFile(require.resolve('./preview_rules')); loadTestFile(require.resolve('./create_rules_bulk')); loadTestFile(require.resolve('./delete_rules')); loadTestFile(require.resolve('./delete_rules_bulk')); diff --git a/x-pack/test/detection_engine_api_integration/utils/get_simple_rule_output_with_web_hook_action.ts b/x-pack/test/detection_engine_api_integration/utils/get_simple_rule_output_with_web_hook_action.ts deleted file mode 100644 index 7ecee679e50b3..0000000000000 --- a/x-pack/test/detection_engine_api_integration/utils/get_simple_rule_output_with_web_hook_action.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 { NOTIFICATION_DEFAULT_FREQUENCY } from '@kbn/security-solution-plugin/common/constants'; -import { getSimpleRuleOutput } from './get_simple_rule_output'; -import { RuleWithoutServerGeneratedProperties } from './remove_server_generated_properties'; - -export const getSimpleRuleOutputWithWebHookAction = ( - actionId: string, - uuid: string -): RuleWithoutServerGeneratedProperties => ({ - ...getSimpleRuleOutput(), - actions: [ - { - action_type_id: '.webhook', - group: 'default', - id: actionId, - params: { - body: '{}', - }, - uuid, - frequency: NOTIFICATION_DEFAULT_FREQUENCY, - }, - ], -}); diff --git a/x-pack/test/detection_engine_api_integration/utils/index.ts b/x-pack/test/detection_engine_api_integration/utils/index.ts index 0e75e72a2d0ed..5aca507b7134f 100644 --- a/x-pack/test/detection_engine_api_integration/utils/index.ts +++ b/x-pack/test/detection_engine_api_integration/utils/index.ts @@ -37,9 +37,6 @@ export * from './get_eql_rule_for_signal_testing'; export * from './get_event_log_execute_complete_by_id'; export * from './get_index_name_from_load'; export * from './get_legacy_action_notification_so'; -export * from './get_legacy_action_notifications_so_by_id'; -export * from './get_legacy_action_so'; -export * from './get_legacy_actions_so_by_id'; export * from './get_open_signals'; export * from './get_preview_alerts'; export * from './get_query_all_signals'; @@ -63,13 +60,10 @@ export * from './get_signals_by_rule_ids'; export * from './get_simple_ml_rule'; export * from './get_simple_ml_rule_output'; export * from './get_simple_ml_rule_update'; -export * from './get_simple_preview_rule'; export * from './get_simple_rule'; export * from './get_simple_rule_as_ndjson'; export * from './get_simple_rule_output'; -export * from './get_simple_rule_output_with_web_hook_action'; export * from './get_simple_rule_output_without_rule_id'; -export * from './get_simple_rule_preview_output'; export * from './get_simple_rule_update'; export * from './get_simple_rule_without_rule_id'; export * from './get_simple_saved_query_rule'; @@ -112,3 +106,4 @@ export * from './prebuilt_rules/install_prebuilt_rules'; export * from './prebuilt_rules/upgrade_prebuilt_rules'; export * from './prebuilt_rules/install_mock_prebuilt_rules'; export * from './prebuilt_rules/install_prebuilt_rules_and_timelines'; +export * from './get_legacy_action_so'; diff --git a/x-pack/test/fleet_api_integration/apis/epm/custom_ingest_pipeline.ts b/x-pack/test/fleet_api_integration/apis/epm/custom_ingest_pipeline.ts index 22490b4bbe31d..244bc0c9db6d7 100644 --- a/x-pack/test/fleet_api_integration/apis/epm/custom_ingest_pipeline.ts +++ b/x-pack/test/fleet_api_integration/apis/epm/custom_ingest_pipeline.ts @@ -79,24 +79,71 @@ export default function (providerContext: FtrProviderContext) { }); describe('With custom pipeline', () => { - before(() => - es.ingest.putPipeline({ + before(async () => { + await es.ingest.putPipeline({ + id: 'global@custom', + processors: [ + { + append: { + field: 'test', + value: ['global'], + }, + }, + ], + }); + + await es.ingest.putPipeline({ + id: 'logs@custom', + processors: [ + { + append: { + field: 'test', + value: ['logs'], + }, + }, + ], + }); + + await es.ingest.putPipeline({ + id: `logs-log@custom`, + processors: [ + { + append: { + field: 'test', + value: ['logs-log'], + }, + }, + ], + }); + + await es.ingest.putPipeline({ id: CUSTOM_PIPELINE, processors: [ { - set: { + append: { field: 'test', - value: 'itworks', + value: ['logs-log.log'], }, }, ], - }) - ); + }); + }); after(() => - es.ingest.deletePipeline({ - id: CUSTOM_PIPELINE, - }) + Promise.all([ + es.ingest.deletePipeline({ + id: 'global@custom', + }), + es.ingest.deletePipeline({ + id: 'logs@custom', + }), + es.ingest.deletePipeline({ + id: 'logs-log@custom', + }), + es.ingest.deletePipeline({ + id: CUSTOM_PIPELINE, + }), + ]) ); it('Should write doc correctly', async () => { const res = await es.index({ @@ -111,7 +158,7 @@ export default function (providerContext: FtrProviderContext) { id: res._id, index: res._index, }); - expect(doc._source?.test).to.eql('itworks'); + expect(doc._source?.test).be.eql(['global', 'logs', 'logs-log', 'logs-log.log']); }); }); }); diff --git a/x-pack/test/fleet_api_integration/apis/epm/data_views.ts b/x-pack/test/fleet_api_integration/apis/epm/data_views.ts new file mode 100644 index 0000000000000..1fc5e660dbc57 --- /dev/null +++ b/x-pack/test/fleet_api_integration/apis/epm/data_views.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 expect from '@kbn/expect'; + +import { FtrProviderContext } from '../../../api_integration/ftr_provider_context'; +import { skipIfNoDockerRegistry } from '../../helpers'; +import { setupFleetAndAgents } from '../agents/services'; + +export default function (providerContext: FtrProviderContext) { + const { getService } = providerContext; + + const supertest = getService('supertest'); + + const testPkgs = [ + { + name: 'apache', + version: '0.1.4', + }, + { + name: 'nginx', + version: '1.2.1', + }, + ]; + + const uninstallPackage = async (name: string, version: string) => { + await supertest.delete(`/api/fleet/epm/packages/${name}/${version}`).set('kbn-xsrf', 'xxxx'); + }; + + const installPackage = async (name: string, version: string) => { + await supertest + .post(`/api/fleet/epm/packages/${name}/${version}`) + .set('kbn-xsrf', 'xxxx') + .send({ force: true }); + }; + + const listDataViews = async () => { + const response = await supertest.get('/api/data_views'); + + return response.body.data_view; + }; + + describe('EPM - data views', () => { + skipIfNoDockerRegistry(providerContext); + setupFleetAndAgents(providerContext); + + afterEach(async () => { + await Promise.all(testPkgs.map((pkg) => uninstallPackage(pkg.name, pkg.version))); + }); + + describe('with subsequent integration installation', async () => { + it('does not recreate managed data views', async () => { + await installPackage(testPkgs[0].name, testPkgs[0].version); + const initialDataViews: any[] = await listDataViews(); + const initialLogsDataView = initialDataViews.find(({ title }) => title === 'logs-*'); + const initialMetricsDataView = initialDataViews.find(({ title }) => title === 'metrics-*'); + + expect(initialLogsDataView).to.be.ok(); + expect(initialMetricsDataView).to.be.ok(); + + await installPackage(testPkgs[1].name, testPkgs[1].version); + const subsequentDataViews: any[] = await listDataViews(); + const subsequentLogsDataView = subsequentDataViews.find(({ title }) => title === 'logs-*'); + const subsequentMetricsDataView = subsequentDataViews.find( + ({ title }) => title === 'metrics-*' + ); + + // ID's should not have changed as the data views should not have been recreated + expect(initialLogsDataView.id).to.eql(subsequentLogsDataView.id); + expect(initialMetricsDataView.id).to.eql(subsequentMetricsDataView.id); + }); + }); + }); +} diff --git a/x-pack/test/fleet_api_integration/apis/epm/index.js b/x-pack/test/fleet_api_integration/apis/epm/index.js index 94f7c12a15ce4..3c4315eff20cb 100644 --- a/x-pack/test/fleet_api_integration/apis/epm/index.js +++ b/x-pack/test/fleet_api_integration/apis/epm/index.js @@ -47,5 +47,6 @@ export default function loadTests({ loadTestFile, getService }) { loadTestFile(require.resolve('./routing_rules')); loadTestFile(require.resolve('./install_runtime_field')); loadTestFile(require.resolve('./get_templates_inputs')); + loadTestFile(require.resolve('./data_views')); }); } diff --git a/x-pack/test/fleet_api_integration/apis/epm/install_endpoint.ts b/x-pack/test/fleet_api_integration/apis/epm/install_endpoint.ts index 892f89f7c2bb6..2ba688dfb8bf5 100644 --- a/x-pack/test/fleet_api_integration/apis/epm/install_endpoint.ts +++ b/x-pack/test/fleet_api_integration/apis/epm/install_endpoint.ts @@ -15,8 +15,7 @@ export default function (providerContext: FtrProviderContext) { * There are a few features that are only currently supported for the Endpoint * package due to security concerns. */ - // Failing: See https://github.com/elastic/kibana/issues/156941 - describe.skip('Install endpoint package', () => { + describe('Install endpoint package', () => { const { getService } = providerContext; skipIfNoDockerRegistry(providerContext); setupFleetAndAgents(providerContext); diff --git a/x-pack/test/fleet_api_integration/apis/epm/install_overrides.ts b/x-pack/test/fleet_api_integration/apis/epm/install_overrides.ts index c93f30dddff7e..26211028a3411 100644 --- a/x-pack/test/fleet_api_integration/apis/epm/install_overrides.ts +++ b/x-pack/test/fleet_api_integration/apis/epm/install_overrides.ts @@ -57,6 +57,7 @@ export default function (providerContext: FtrProviderContext) { // the index template composed_of has the correct component templates in the correct order const indexTemplate = indexTemplateResponse.index_templates[0].index_template; expect(indexTemplate.composed_of).to.eql([ + `logs@settings`, `${templateName}@package`, `${templateName}@custom`, '.fleet_globals-1', @@ -131,13 +132,11 @@ export default function (providerContext: FtrProviderContext) { template: { settings: { index: { - codec: 'best_compression', default_pipeline: 'logs-overrides.test-0.1.0', lifecycle: { name: 'overridden by user', }, mapping: { - ignore_malformed: `true`, total_fields: { limit: '10000', }, @@ -149,7 +148,6 @@ export default function (providerContext: FtrProviderContext) { dynamic: 'false', properties: { '@timestamp': { - ignore_malformed: false, type: 'date', }, data_stream: { diff --git a/x-pack/test/fleet_api_integration/apis/epm/list.ts b/x-pack/test/fleet_api_integration/apis/epm/list.ts index 724f34454991f..5727f7130f563 100644 --- a/x-pack/test/fleet_api_integration/apis/epm/list.ts +++ b/x-pack/test/fleet_api_integration/apis/epm/list.ts @@ -21,8 +21,7 @@ export default function (providerContext: FtrProviderContext) { // because `this` has to point to the Mocha context // see https://mochajs.org/#arrow-functions - // Failing: See https://github.com/elastic/kibana/issues/167188 - describe.skip('EPM - list', async function () { + describe('EPM - list', async function () { skipIfNoDockerRegistry(providerContext); before(async () => { diff --git a/x-pack/test/fleet_api_integration/apis/epm/template.ts b/x-pack/test/fleet_api_integration/apis/epm/template.ts index c62afa6dccbf7..8f2d208a27421 100644 --- a/x-pack/test/fleet_api_integration/apis/epm/template.ts +++ b/x-pack/test/fleet_api_integration/apis/epm/template.ts @@ -35,6 +35,7 @@ export default function ({ getService }: FtrProviderContext) { composedOfTemplates: [], templatePriority: 200, mappings: { properties: [] }, + type: 'logs', }); // This test is not an API integration test with Kibana diff --git a/x-pack/test/fleet_api_integration/apis/epm/update_assets.ts b/x-pack/test/fleet_api_integration/apis/epm/update_assets.ts index 9b2527a5b025d..75040c8400d04 100644 --- a/x-pack/test/fleet_api_integration/apis/epm/update_assets.ts +++ b/x-pack/test/fleet_api_integration/apis/epm/update_assets.ts @@ -217,13 +217,11 @@ export default function (providerContext: FtrProviderContext) { expect(resPackage.statusCode).equal(200); expect(resPackage.body.component_templates[0].component_template.template.settings).eql({ index: { - codec: 'best_compression', default_pipeline: 'logs-all_assets.test_logs-0.2.0', lifecycle: { name: 'reference2', }, mapping: { - ignore_malformed: `true`, total_fields: { limit: '10000', }, diff --git a/x-pack/test/fleet_api_integration/apis/package_policy/input_package_create_upgrade.ts b/x-pack/test/fleet_api_integration/apis/package_policy/input_package_create_upgrade.ts index a1e6fe5d5556f..0d2af1d0e6ac1 100644 --- a/x-pack/test/fleet_api_integration/apis/package_policy/input_package_create_upgrade.ts +++ b/x-pack/test/fleet_api_integration/apis/package_policy/input_package_create_upgrade.ts @@ -221,11 +221,9 @@ export default function (providerContext: FtrProviderContext) { settings: { index: { lifecycle: { name: 'logs' }, - codec: 'best_compression', default_pipeline: 'logs-dataset1-1.0.0', mapping: { total_fields: { limit: '10000' }, - ignore_malformed: 'true', }, }, }, diff --git a/x-pack/test/fleet_api_integration/apis/service_tokens.ts b/x-pack/test/fleet_api_integration/apis/service_tokens.ts index e1830a8ac7f97..5d5dc8b414756 100644 --- a/x-pack/test/fleet_api_integration/apis/service_tokens.ts +++ b/x-pack/test/fleet_api_integration/apis/service_tokens.ts @@ -53,5 +53,26 @@ export default function (providerContext: FtrProviderContext) { .set('Elastic-Api-Version', `${API_VERSIONS.internal.v1}`) .expect(200); }); + + it('should create a valid remote service account token', async () => { + const { body: apiResponse } = await supertest + .post(`/api/fleet/service_tokens`) + .set('kbn-xsrf', 'xxxx') + .send({ remote: true }) + .expect(200); + + expect(apiResponse).have.property('name'); + expect(apiResponse).have.property('value'); + + const { body: tokensResponse } = await esClient.transport.request( + { + method: 'GET', + path: `_security/service/elastic/fleet-server-remote/credential`, + }, + { meta: true } + ); + + expect(tokensResponse.tokens).have.property(apiResponse.name); + }); }); } diff --git a/x-pack/test/functional/apps/infra/hosts_view.ts b/x-pack/test/functional/apps/infra/hosts_view.ts index a7c0ba54298fc..3a5b5a0156d5e 100644 --- a/x-pack/test/functional/apps/infra/hosts_view.ts +++ b/x-pack/test/functional/apps/infra/hosts_view.ts @@ -587,6 +587,16 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { await pageObjects.infraHostsView.submitQuery('cloud.provider="gcp" A'); await testSubjects.existOrFail('hostsViewErrorCallout'); }); + + it('should show no data message in the table content', async () => { + await pageObjects.infraHostsView.submitQuery('host.name : "foo"'); + + await waitForPageToLoad(); + + await retry.try(async () => { + await testSubjects.exists('hostsViewTableNoData'); + }); + }); }); describe('Pagination and Sorting', () => { diff --git a/x-pack/test/functional/apps/ingest_pipelines/ingest_pipelines.ts b/x-pack/test/functional/apps/ingest_pipelines/ingest_pipelines.ts index a66883d2d7b77..ec9f8815cd664 100644 --- a/x-pack/test/functional/apps/ingest_pipelines/ingest_pipelines.ts +++ b/x-pack/test/functional/apps/ingest_pipelines/ingest_pipelines.ts @@ -28,8 +28,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { const es = getService('es'); const security = getService('security'); - // FAILING ES PROMOTION: https://github.com/elastic/kibana/issues/169969 - describe.skip('Ingest Pipelines', function () { + describe('Ingest Pipelines', function () { this.tags('smoke'); before(async () => { await security.testUser.setRoles(['ingest_pipelines_user']); @@ -49,6 +48,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { }); it('Displays the test pipeline in the list of pipelines', async () => { + await pageObjects.ingestPipelines.increasePipelineListPageSize(); const pipelines = await pageObjects.ingestPipelines.getPipelinesList(); expect(pipelines).to.contain(TEST_PIPELINE_NAME); }); @@ -57,6 +57,8 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { it('Creates a pipeline', async () => { await pageObjects.ingestPipelines.createNewPipeline(PIPELINE); + await pageObjects.ingestPipelines.closePipelineDetailsFlyout(); + await pageObjects.ingestPipelines.increasePipelineListPageSize(); const pipelinesList = await pageObjects.ingestPipelines.getPipelinesList(); const newPipelineExists = Boolean( pipelinesList.find((pipelineName) => pipelineName === PIPELINE.name) @@ -74,6 +76,8 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { await pageObjects.ingestPipelines.createPipelineFromCsv(PIPELINE_CSV); + await pageObjects.ingestPipelines.closePipelineDetailsFlyout(); + await pageObjects.ingestPipelines.increasePipelineListPageSize(); const pipelinesList = await pageObjects.ingestPipelines.getPipelinesList(); const newPipelineExists = Boolean( pipelinesList.find((pipelineName) => pipelineName === PIPELINE.name) @@ -83,8 +87,6 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { }); afterEach(async () => { - // Close details flyout - await pageObjects.ingestPipelines.closePipelineDetailsFlyout(); // Delete the pipeline that was created await es.ingest.deletePipeline({ id: PIPELINE.name }); await security.testUser.restoreDefaults(); diff --git a/x-pack/test/functional/apps/observability_log_explorer/flyout.ts b/x-pack/test/functional/apps/observability_log_explorer/flyout.ts new file mode 100644 index 0000000000000..f8277db16e8db --- /dev/null +++ b/x-pack/test/functional/apps/observability_log_explorer/flyout.ts @@ -0,0 +1,91 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import { FtrProviderContext } from '../../ftr_provider_context'; + +const DATASET_NAME = 'flyout'; +const NAMESPACE = 'default'; +const DATA_STREAM_NAME = `logs-${DATASET_NAME}-${NAMESPACE}`; +const NOW = Date.now(); + +const sharedDoc = { + logFilepath: '/flyout.log', + serviceName: DATASET_NAME, + datasetName: DATASET_NAME, + namespace: NAMESPACE, +}; + +const docs = [ + { + ...sharedDoc, + time: NOW + 1000, + message: 'full document', + logLevel: 'info', + }, + { + ...sharedDoc, + time: NOW, + }, +]; + +export default function ({ getService, getPageObjects }: FtrProviderContext) { + const dataGrid = getService('dataGrid'); + const testSubjects = getService('testSubjects'); + const PageObjects = getPageObjects(['observabilityLogExplorer']); + + describe('Flyout content customization', () => { + let cleanupDataStreamSetup: () => Promise; + + before('initialize tests', async () => { + cleanupDataStreamSetup = await PageObjects.observabilityLogExplorer.setupDataStream( + DATASET_NAME, + NAMESPACE + ); + await PageObjects.observabilityLogExplorer.ingestLogEntries(DATA_STREAM_NAME, docs); + }); + + beforeEach(async () => { + await PageObjects.observabilityLogExplorer.navigateTo({ + from: new Date(NOW - 60_000).toISOString(), + to: new Date(NOW + 60_000).toISOString(), + }); + }); + + after('clean up archives', async () => { + if (cleanupDataStreamSetup) { + cleanupDataStreamSetup(); + } + }); + + it('should mount the flyout customization content', async () => { + await dataGrid.clickRowToggle(); + await testSubjects.existOrFail('logExplorerFlyoutDetail'); + }); + + it('should display a timestamp badge', async () => { + await dataGrid.clickRowToggle(); + await testSubjects.existOrFail('logExplorerFlyoutLogTimestamp'); + }); + + it('should display a log level badge when available', async () => { + await dataGrid.clickRowToggle(); + await testSubjects.existOrFail('logExplorerFlyoutLogLevel'); + await dataGrid.closeFlyout(); + + await dataGrid.clickRowToggle({ rowIndex: 1 }); + await testSubjects.missingOrFail('logExplorerFlyoutLogLevel'); + }); + + it('should display a message code block when available', async () => { + await dataGrid.clickRowToggle(); + await testSubjects.existOrFail('logExplorerFlyoutLogMessage'); + await dataGrid.closeFlyout(); + + await dataGrid.clickRowToggle({ rowIndex: 1 }); + await testSubjects.missingOrFail('logExplorerFlyoutLogMessage'); + }); + }); +} diff --git a/x-pack/test/functional/apps/observability_log_explorer/index.ts b/x-pack/test/functional/apps/observability_log_explorer/index.ts index aec38a6bb8308..948910dab6ab4 100644 --- a/x-pack/test/functional/apps/observability_log_explorer/index.ts +++ b/x-pack/test/functional/apps/observability_log_explorer/index.ts @@ -14,6 +14,7 @@ export default function ({ loadTestFile }: FtrProviderContext) { loadTestFile(require.resolve('./dataset_selection_state')); loadTestFile(require.resolve('./dataset_selector')); loadTestFile(require.resolve('./filter_controls')); + loadTestFile(require.resolve('./flyout')); loadTestFile(require.resolve('./header_menu')); }); } diff --git a/x-pack/test/functional/page_objects/ingest_pipelines_page.ts b/x-pack/test/functional/page_objects/ingest_pipelines_page.ts index d2a8edb489d90..b3f9e7735ad1c 100644 --- a/x-pack/test/functional/page_objects/ingest_pipelines_page.ts +++ b/x-pack/test/functional/page_objects/ingest_pipelines_page.ts @@ -100,5 +100,10 @@ export function IngestPipelinesPageProvider({ getService, getPageObjects }: FtrP async closePipelineDetailsFlyout() { await testSubjects.click('euiFlyoutCloseButton'); }, + + async increasePipelineListPageSize() { + await testSubjects.click('tablePaginationPopoverButton'); + await testSubjects.click(`tablePagination-50-rows`); + }, }; } diff --git a/x-pack/test/functional/page_objects/observability_log_explorer.ts b/x-pack/test/functional/page_objects/observability_log_explorer.ts index 5cca2f522bafe..2978e3205f464 100644 --- a/x-pack/test/functional/page_objects/observability_log_explorer.ts +++ b/x-pack/test/functional/page_objects/observability_log_explorer.ts @@ -109,7 +109,10 @@ export function ObservabilityLogExplorerPageObject({ getService, }: FtrProviderContext) { const PageObjects = getPageObjects(['common']); + const dataGrid = getService('dataGrid'); + const es = getService('es'); const log = getService('log'); + const queryBar = getService('queryBar'); const supertest = getService('supertest'); const testSubjects = getService('testSubjects'); const toasts = getService('toasts'); @@ -119,6 +122,8 @@ export function ObservabilityLogExplorerPageObject({ 'search' > & { search?: Record; + from?: string; + to?: string; }; return { @@ -167,6 +172,27 @@ export function ObservabilityLogExplorerPageObject({ }; }, + async setupDataStream(datasetName: string, namespace: string = 'default') { + const dataStream = `logs-${datasetName}-${namespace}`; + log.info(`===== Setup initial data stream "${dataStream}". =====`); + await es.indices.createDataStream({ name: dataStream }); + + return async () => { + log.info(`===== Removing data stream "${dataStream}". =====`); + await es.indices.deleteDataStream({ + name: dataStream, + }); + }; + }, + + ingestLogEntries(dataStream: string, docs: MockLogDoc[] = []) { + log.info(`===== Ingesting ${docs.length} docs for "${dataStream}" data stream. =====`); + return es.bulk({ + body: docs.flatMap((doc) => [{ create: { _index: dataStream } }, createLogDoc(doc)]), + refresh: 'wait_for', + }); + }, + async setupAdditionalIntegrations() { log.info(`===== Setup additional integration packages. =====`); log.info(`===== Install ${additionalPackages.length} mock integration packages. =====`); @@ -183,11 +209,11 @@ export function ObservabilityLogExplorerPageObject({ }, async navigateTo(options: NavigateToAppOptions = {}) { - const { search = {}, ...extraOptions } = options; + const { search = {}, from = FROM, to = TO, ...extraOptions } = options; const composedSearch = querystring.stringify({ ...search, _g: rison.encode({ - time: { from: FROM, to: TO }, + time: { from, to }, }), }); @@ -265,6 +291,11 @@ export function ObservabilityLogExplorerPageObject({ return testSubjects.find('unmanagedDatasets'); }, + async getFlyoutDetail(rowIndex: number = 0) { + await dataGrid.clickRowToggle({ rowIndex }); + return testSubjects.find('logExplorerFlyoutDetail'); + }, + async getIntegrations() { const menu = await this.getIntegrationsContextMenu(); @@ -362,24 +393,65 @@ export function ObservabilityLogExplorerPageObject({ }, // Query Bar - getQueryBar() { - return testSubjects.find('queryInput'); + getQueryBarValue() { + return queryBar.getQueryString(); }, - async getQueryBarValue() { - const queryBar = await testSubjects.find('queryInput'); - return queryBar.getAttribute('value'); + async submitQuery(query: string) { + await queryBar.setQuery(query); + await queryBar.clickQuerySubmitButton(); }, + }; +} - async typeInQueryBar(query: string) { - const queryBar = await this.getQueryBar(); - await queryBar.clearValueWithKeyboard(); - return queryBar.type(query); - }, +interface MockLogDoc { + time: number; + logFilepath: string; + serviceName?: string; + namespace: string; + datasetName: string; + message?: string; + logLevel?: string; + [key: string]: unknown; +} - async submitQuery(query: string) { - await this.typeInQueryBar(query); - await testSubjects.click('querySubmitButton'); - }, +export function createLogDoc({ + time, + logFilepath, + serviceName, + namespace, + datasetName, + message, + logLevel, + ...extraFields +}: MockLogDoc) { + return { + input: { + type: 'log', + }, + '@timestamp': new Date(time).toISOString(), + log: { + file: { + path: logFilepath, + }, + }, + ...(serviceName + ? { + service: { + name: serviceName, + }, + } + : {}), + data_stream: { + namespace, + type: 'logs', + dataset: datasetName, + }, + message, + event: { + dataset: datasetName, + }, + ...(logLevel && { 'log.level': logLevel }), + ...extraFields, }; } diff --git a/x-pack/test/functional/page_objects/security_page.ts b/x-pack/test/functional/page_objects/security_page.ts index 5b0a9a679840a..bb127df565ccd 100644 --- a/x-pack/test/functional/page_objects/security_page.ts +++ b/x-pack/test/functional/page_objects/security_page.ts @@ -41,6 +41,8 @@ export class SecurityPageObject extends FtrService { private readonly monacoEditor = this.ctx.getService('monacoEditor'); private readonly es = this.ctx.getService('es'); + delay = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms)); + public loginPage = Object.freeze({ login: async (username?: string, password?: string, options: LoginOptions = {}) => { if (!(await this.isLoginFormVisible())) { @@ -316,7 +318,7 @@ export class SecurityPageObject extends FtrService { await this.waitForLoginPage(); } else { this.log.debug('Waiting for logout to complete'); - await this.retry.waitFor('Waiting for logout to complete', async () => { + await this.retry.waitFor('logout to complete', async () => { // There are cases when browser/Kibana would like users to confirm that they want to navigate away from the // current page and lose the state (e.g. unsaved changes) via native alert dialog. const alert = await this.browser.getAlert(); @@ -324,12 +326,19 @@ export class SecurityPageObject extends FtrService { await alert.accept(); } + await this.retry.waitFor('URL redirects to finish', async () => { + const urlBefore = await this.browser.getCurrentUrl(); + await this.delay(1000); + const urlAfter = await this.browser.getCurrentUrl(); + return urlAfter === urlBefore; + }); + + const currentUrl = await this.browser.getCurrentUrl(); if (this.config.get('serverless')) { // Logout might trigger multiple redirects, but in the end we expect the Cloud login page - this.log.debug('Wait 5 sec for Cloud login page to be displayed'); - return await this.find.existsByDisplayedByCssSelector('.login-form-password', 5000); + return currentUrl.includes('/login') || currentUrl.includes('/projects'); } else { - return !(await this.browser.getCurrentUrl()).includes('/logout'); + return !currentUrl.includes('/logout'); } }); } diff --git a/x-pack/test/functional/services/cases/list.ts b/x-pack/test/functional/services/cases/list.ts index e1b4e45724283..a83b11da78b78 100644 --- a/x-pack/test/functional/services/cases/list.ts +++ b/x-pack/test/functional/services/cases/list.ts @@ -5,7 +5,6 @@ * 2.0. */ -import expect from '@kbn/expect'; import { CaseSeverityWithAll } from '@kbn/cases-plugin/common/ui'; import { CaseSeverity, CaseStatuses } from '@kbn/cases-plugin/common/types/domain'; import { WebElementWrapper } from '../../../../../test/functional/services/lib/web_element_wrapper'; @@ -85,10 +84,12 @@ export function CasesTableServiceProvider( }, async validateCasesTableHasNthRows(nrRows: number) { - await retry.tryForTime(3000, async () => { + await retry.waitFor(`the cases table to have ${nrRows} cases`, async () => { const rows = await find.allByCssSelector('[data-test-subj*="cases-table-row-"'); - expect(rows.length).equal(nrRows); + return rows.length === nrRows; }); + + await header.waitUntilLoadingHasFinished(); }, async waitForCasesToBeListed() { diff --git a/x-pack/test/functional_with_es_ssl/apps/cases/group2/list_view.ts b/x-pack/test/functional_with_es_ssl/apps/cases/group2/list_view.ts index e9daffe92c586..51a37c1eaccd9 100644 --- a/x-pack/test/functional_with_es_ssl/apps/cases/group2/list_view.ts +++ b/x-pack/test/functional_with_es_ssl/apps/cases/group2/list_view.ts @@ -279,8 +279,7 @@ export default ({ getPageObject, getService }: FtrProviderContext) => { }); }); - // FLAKY: https://github.com/elastic/kibana/issues/152925 - describe.skip('filtering', () => { + describe('filtering', () => { const caseTitle = 'matchme'; const caseIds: string[] = []; @@ -459,8 +458,7 @@ export default ({ getPageObject, getService }: FtrProviderContext) => { await testSubjects.existOrFail(`case-table-column-severity-${CaseSeverity.MEDIUM}`); }); - // FLAKY: https://github.com/elastic/kibana/issues/152928 - describe.skip('assignees filtering', () => { + describe('assignees filtering', () => { it('filters cases by the first cases all user assignee', async () => { await cases.casesTable.filterByAssignee('all'); await cases.casesTable.validateCasesTableHasNthRows(1); diff --git a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/rules_settings.ts b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/rules_settings.ts index 8c86e8a5e5965..290404269d701 100644 --- a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/rules_settings.ts +++ b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/rules_settings.ts @@ -90,19 +90,23 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { await testSubjects.existOrFail('rulesSettingsFlappingEnableSwitch'); await testSubjects.existOrFail('lookBackWindowRangeInput'); await testSubjects.existOrFail('statusChangeThresholdRangeInput'); - await testSubjects.existOrFail('queryDelayRangeInput'); + + await testSubjects.missingOrFail('queryDelayRangeInput'); const lookBackWindowInput = await testSubjects.find('lookBackWindowRangeInput'); const statusChangeThresholdInput = await testSubjects.find('statusChangeThresholdRangeInput'); - const queryDelayInput = await testSubjects.find('queryDelayRangeInput'); const lookBackWindowValue = await lookBackWindowInput.getAttribute('value'); const statusChangeThresholdValue = await statusChangeThresholdInput.getAttribute('value'); - const queryDelayValue = await queryDelayInput.getAttribute('value'); expect(lookBackWindowValue).to.eql('10'); expect(statusChangeThresholdValue).to.eql('10'); - expect(queryDelayValue).to.eql('10'); + + // Enable query delay tests once feature flag is removed + // await testSubjects.existOrFail('queryDelayRangeInput'); + // const queryDelayInput = await testSubjects.find('queryDelayRangeInput'); + // const queryDelayValue = await queryDelayInput.getAttribute('value'); + // expect(queryDelayValue).to.eql('10'); }); it('should allow the user to modify rules settings', async () => { @@ -111,19 +115,21 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { await dragRangeInput('lookBackWindowRangeInput', 5, 'right'); await dragRangeInput('statusChangeThresholdRangeInput', 5, 'left'); - await dragRangeInput('queryDelayRangeInput', 5, 'left'); let lookBackWindowInput = await testSubjects.find('lookBackWindowRangeInput'); let statusChangeThresholdInput = await testSubjects.find('statusChangeThresholdRangeInput'); - let queryDelayInput = await testSubjects.find('queryDelayRangeInput'); let lookBackWindowValue = await lookBackWindowInput.getAttribute('value'); let statusChangeThresholdValue = await statusChangeThresholdInput.getAttribute('value'); - let queryDelayValue = await queryDelayInput.getAttribute('value'); expect(lookBackWindowValue).to.eql('15'); expect(statusChangeThresholdValue).to.eql('5'); - expect(queryDelayValue).to.eql('5'); + + // Enable query delay tests once feature flag is removed + // await dragRangeInput('queryDelayRangeInput', 5, 'left'); + // let queryDelayInput = await testSubjects.find('queryDelayRangeInput'); + // let queryDelayValue = await queryDelayInput.getAttribute('value'); + // expect(queryDelayValue).to.eql('5'); await testSubjects.click('rulesSettingsFlappingEnableSwitch'); await testSubjects.existOrFail('rulesSettingsFlappingOffPrompt'); @@ -143,15 +149,17 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { lookBackWindowInput = await testSubjects.find('lookBackWindowRangeInput'); statusChangeThresholdInput = await testSubjects.find('statusChangeThresholdRangeInput'); - queryDelayInput = await testSubjects.find('queryDelayRangeInput'); lookBackWindowValue = await lookBackWindowInput.getAttribute('value'); statusChangeThresholdValue = await statusChangeThresholdInput.getAttribute('value'); - queryDelayValue = await queryDelayInput.getAttribute('value'); expect(lookBackWindowValue).to.eql('15'); expect(statusChangeThresholdValue).to.eql('5'); - expect(queryDelayValue).to.eql('5'); + + // Enable query delay tests once feature flag is removed + // queryDelayInput = await testSubjects.find('queryDelayRangeInput'); + // queryDelayValue = await queryDelayInput.getAttribute('value'); + // expect(queryDelayValue).to.eql('5'); }); }); }; diff --git a/x-pack/test/observability_onboarding_api_integration/tests/flow/progress/es_utils.ts b/x-pack/test/observability_onboarding_api_integration/tests/flow/progress/es_utils.ts index 001415ca59abb..33207ed6cdd8c 100644 --- a/x-pack/test/observability_onboarding_api_integration/tests/flow/progress/es_utils.ts +++ b/x-pack/test/observability_onboarding_api_integration/tests/flow/progress/es_utils.ts @@ -12,6 +12,7 @@ export function createLogDoc({ namespace, datasetName, message, + agentId, }: { time: number; logFilepath: string; @@ -19,6 +20,7 @@ export function createLogDoc({ namespace: string; datasetName: string; message: string; + agentId?: string; }) { return { input: { @@ -46,5 +48,12 @@ export function createLogDoc({ event: { dataset: datasetName, }, + ...(agentId + ? { + agent: { + id: agentId, + }, + } + : {}), }; } diff --git a/x-pack/test/observability_onboarding_api_integration/tests/flow/progress/progress.spec.ts b/x-pack/test/observability_onboarding_api_integration/tests/flow/progress/progress.spec.ts index 2cf9157d356c1..7311f116736a3 100644 --- a/x-pack/test/observability_onboarding_api_integration/tests/flow/progress/progress.spec.ts +++ b/x-pack/test/observability_onboarding_api_integration/tests/flow/progress/progress.spec.ts @@ -104,6 +104,8 @@ export default function ApiTest({ getService }: FtrProviderContext) { describe('when ea-status is complete', () => { describe('should not skip logs verification', () => { + const agentId = 'my-agent-id'; + before(async () => { await observabilityOnboardingApiClient.logMonitoringUser({ endpoint: 'POST /internal/observability_onboarding/flow/{id}/step/{name}', @@ -114,6 +116,9 @@ export default function ApiTest({ getService }: FtrProviderContext) { }, body: { status: 'complete', + payload: { + agentId, + }, }, }, }); @@ -133,106 +138,224 @@ export default function ApiTest({ getService }: FtrProviderContext) { }); describe('when logs have been ingested', () => { - describe('and onboarding type is logFiles', () => { - before(async () => { - await es.indices.createDataStream({ - name: `logs-${datasetName}-${namespace}`, + describe('with a different agentId', () => { + describe('and onboarding type is logFiles', () => { + before(async () => { + await es.indices.createDataStream({ + name: `logs-${datasetName}-${namespace}`, + }); + + const doc = createLogDoc({ + time: new Date('06/28/2023').getTime(), + logFilepath: '/my-service.log', + serviceName: 'my-service', + namespace, + datasetName, + message: 'This is a log message', + agentId: 'another-agent-id', + }); + + await es.bulk({ + body: [{ create: { _index: `logs-${datasetName}-${namespace}` } }, doc], + refresh: 'wait_for', + }); }); - const doc = createLogDoc({ - time: new Date('06/28/2023').getTime(), - logFilepath: '/my-service.log', - serviceName: 'my-service', - namespace, - datasetName, - message: 'This is a log message', + it('should return log-ingest as incomplete', async () => { + const request = await callApi({ + onboardingId, + }); + + expect(request.status).to.be(200); + + const logsIngestProgress = request.body.progress['logs-ingest']; + expect(logsIngestProgress).to.have.property('status', 'loading'); }); - await es.bulk({ - body: [{ create: { _index: `logs-${datasetName}-${namespace}` } }, doc], - refresh: 'wait_for', + after(async () => { + await es.indices.deleteDataStream({ + name: `logs-${datasetName}-${namespace}`, + }); }); }); - it('should return log-ingest as complete', async () => { - const request = await callApi({ - onboardingId, + describe('and onboarding type is systemLogs', () => { + let systemLogsOnboardingId: string; + + before(async () => { + const req = await observabilityOnboardingApiClient.logMonitoringUser({ + endpoint: 'POST /internal/observability_onboarding/logs/flow', + params: { + body: { + type: 'systemLogs', + name: 'name', + }, + }, + }); + + systemLogsOnboardingId = req.body.onboardingId; + + await observabilityOnboardingApiClient.logMonitoringUser({ + endpoint: 'POST /internal/observability_onboarding/flow/{id}/step/{name}', + params: { + path: { + id: systemLogsOnboardingId, + name: 'ea-status', + }, + body: { + status: 'complete', + payload: { + agentId, + }, + }, + }, + }); + + await es.indices.createDataStream({ + name: `logs-system.syslog-${namespace}`, + }); + + const doc = createLogDoc({ + time: new Date('06/28/2023').getTime(), + logFilepath: '/var/log/system.log', + namespace, + datasetName: 'system.syslog', + message: 'This is a system log message', + agentId: 'another-agent-id', + }); + + await es.bulk({ + body: [{ create: { _index: `logs-system.syslog-${namespace}` } }, doc], + refresh: 'wait_for', + }); }); - expect(request.status).to.be(200); + it('should return log-ingest as incomplete', async () => { + const request = await callApi({ + onboardingId: systemLogsOnboardingId, + }); - const logsIngestProgress = request.body.progress['logs-ingest']; - expect(logsIngestProgress).to.have.property('status', 'complete'); - }); + expect(request.status).to.be(200); + + const logsIngestProgress = request.body.progress['logs-ingest']; + expect(logsIngestProgress).to.have.property('status', 'loading'); + }); - after(async () => { - await es.indices.deleteDataStream({ - name: `logs-${datasetName}-${namespace}`, + after(async () => { + await es.indices.deleteDataStream({ + name: `logs-system.syslog-${namespace}`, + }); }); }); }); - describe('and onboarding type is systemLogs', () => { - let systemLogsOnboardingId: string; - - before(async () => { - const req = await observabilityOnboardingApiClient.logMonitoringUser({ - endpoint: 'POST /internal/observability_onboarding/logs/flow', - params: { - body: { - type: 'systemLogs', - name: 'name', - }, - }, + describe('with the expected agentId', () => { + describe('and onboarding type is logFiles', () => { + before(async () => { + await es.indices.createDataStream({ + name: `logs-${datasetName}-${namespace}`, + }); + + const doc = createLogDoc({ + time: new Date('06/28/2023').getTime(), + logFilepath: '/my-service.log', + serviceName: 'my-service', + namespace, + datasetName, + message: 'This is a log message', + agentId, + }); + + await es.bulk({ + body: [{ create: { _index: `logs-${datasetName}-${namespace}` } }, doc], + refresh: 'wait_for', + }); }); - systemLogsOnboardingId = req.body.onboardingId; + it('should return log-ingest as complete', async () => { + const request = await callApi({ + onboardingId, + }); - await observabilityOnboardingApiClient.logMonitoringUser({ - endpoint: 'POST /internal/observability_onboarding/flow/{id}/step/{name}', - params: { - path: { - id: systemLogsOnboardingId, - name: 'ea-status', - }, - body: { - status: 'complete', - }, - }, - }); - - await es.indices.createDataStream({ - name: `logs-system.syslog-${namespace}`, - }); + expect(request.status).to.be(200); - const doc = createLogDoc({ - time: new Date('06/28/2023').getTime(), - logFilepath: '/var/log/system.log', - namespace, - datasetName: 'system.syslog', - message: 'This is a system log message', + const logsIngestProgress = request.body.progress['logs-ingest']; + expect(logsIngestProgress).to.have.property('status', 'complete'); }); - await es.bulk({ - body: [{ create: { _index: `logs-system.syslog-${namespace}` } }, doc], - refresh: 'wait_for', + after(async () => { + await es.indices.deleteDataStream({ + name: `logs-${datasetName}-${namespace}`, + }); }); }); - it('should return log-ingest as complete', async () => { - const request = await callApi({ - onboardingId: systemLogsOnboardingId, + describe('and onboarding type is systemLogs', () => { + let systemLogsOnboardingId: string; + + before(async () => { + const req = await observabilityOnboardingApiClient.logMonitoringUser({ + endpoint: 'POST /internal/observability_onboarding/logs/flow', + params: { + body: { + type: 'systemLogs', + name: 'name', + }, + }, + }); + + systemLogsOnboardingId = req.body.onboardingId; + + await observabilityOnboardingApiClient.logMonitoringUser({ + endpoint: 'POST /internal/observability_onboarding/flow/{id}/step/{name}', + params: { + path: { + id: systemLogsOnboardingId, + name: 'ea-status', + }, + body: { + status: 'complete', + payload: { + agentId, + }, + }, + }, + }); + + await es.indices.createDataStream({ + name: `logs-system.syslog-${namespace}`, + }); + + const doc = createLogDoc({ + time: new Date('06/28/2023').getTime(), + logFilepath: '/var/log/system.log', + namespace, + datasetName: 'system.syslog', + message: 'This is a system log message', + agentId, + }); + + await es.bulk({ + body: [{ create: { _index: `logs-system.syslog-${namespace}` } }, doc], + refresh: 'wait_for', + }); }); - expect(request.status).to.be(200); + it('should return log-ingest as complete', async () => { + const request = await callApi({ + onboardingId: systemLogsOnboardingId, + }); - const logsIngestProgress = request.body.progress['logs-ingest']; - expect(logsIngestProgress).to.have.property('status', 'complete'); - }); + expect(request.status).to.be(200); + + const logsIngestProgress = request.body.progress['logs-ingest']; + expect(logsIngestProgress).to.have.property('status', 'complete'); + }); - after(async () => { - await es.indices.deleteDataStream({ - name: `logs-system.syslog-${namespace}`, + after(async () => { + await es.indices.deleteDataStream({ + name: `logs-system.syslog-${namespace}`, + }); }); }); }); diff --git a/x-pack/test/osquery_cypress/agent.ts b/x-pack/test/osquery_cypress/agent.ts index 7456e73b2333a..cd7969703c483 100644 --- a/x-pack/test/osquery_cypress/agent.ts +++ b/x-pack/test/osquery_cypress/agent.ts @@ -5,23 +5,33 @@ * 2.0. */ -import { ToolingLog } from '@kbn/tooling-log'; import execa from 'execa'; +import { ToolingLog } from '@kbn/tooling-log'; +import { KbnClient } from '@kbn/test'; +import { waitForHostToEnroll } from '@kbn/security-solution-plugin/scripts/endpoint/common/fleet_services'; import { getLatestVersion } from './artifact_manager'; import { Manager } from './resource_manager'; +import { generateRandomString } from './utils'; export class AgentManager extends Manager { private log: ToolingLog; private policyEnrollmentKey: string; private fleetServerPort: string; private agentContainerId?: string; + private kbnClient: KbnClient; - constructor(policyEnrollmentKey: string, fleetServerPort: string, log: ToolingLog) { + constructor( + policyEnrollmentKey: string, + fleetServerPort: string, + log: ToolingLog, + kbnClient: KbnClient + ) { super(); this.log = log; this.fleetServerPort = fleetServerPort; this.policyEnrollmentKey = policyEnrollmentKey; + this.kbnClient = kbnClient; } public async setup() { @@ -29,6 +39,7 @@ export class AgentManager extends Manager { const artifact = `docker.elastic.co/beats/elastic-agent:${await getLatestVersion()}`; this.log.info(artifact); + const containerName = generateRandomString(12); const dockerArgs = [ 'run', @@ -37,6 +48,10 @@ export class AgentManager extends Manager { '--detach', '--add-host', 'host.docker.internal:host-gateway', + '--name', + containerName, + '--hostname', + containerName, '--env', 'FLEET_ENROLL=1', '--env', @@ -50,6 +65,7 @@ export class AgentManager extends Manager { ]; this.agentContainerId = (await execa('docker', dockerArgs)).stdout; + await waitForHostToEnroll(this.kbnClient, containerName); } public cleanup() { diff --git a/x-pack/test/osquery_cypress/runner.ts b/x-pack/test/osquery_cypress/runner.ts index fddd90a336d05..7e7ac5e652fd7 100644 --- a/x-pack/test/osquery_cypress/runner.ts +++ b/x-pack/test/osquery_cypress/runner.ts @@ -48,12 +48,10 @@ async function setupFleetAgent({ getService }: FtrProviderContext) { const policyEnrollmentKey = await createAgentPolicy(kbnClient, log, 'Default policy'); const policyEnrollmentKeyTwo = await createAgentPolicy(kbnClient, log, 'Osquery policy'); - await new AgentManager(policyEnrollmentKey, config.get('servers.fleetserver.port'), log).setup(); - await new AgentManager( - policyEnrollmentKeyTwo, - config.get('servers.fleetserver.port'), - log - ).setup(); + const port = config.get('servers.fleetserver.port'); + + await new AgentManager(policyEnrollmentKey, port, log, kbnClient).setup(); + await new AgentManager(policyEnrollmentKeyTwo, port, log, kbnClient).setup(); } export async function startOsqueryCypress(context: FtrProviderContext) { diff --git a/x-pack/test/osquery_cypress/utils.ts b/x-pack/test/osquery_cypress/utils.ts index a852cfd8bed99..810f432d14dd9 100644 --- a/x-pack/test/osquery_cypress/utils.ts +++ b/x-pack/test/osquery_cypress/utils.ts @@ -137,3 +137,7 @@ export const getLatestAvailableAgentVersion = async (kbnClient: KbnClient): Prom return version; }; + +export const generateRandomString = (length: number) => { + return [...Array(length)].map(() => Math.random().toString(36)[2]).join(''); +}; diff --git a/x-pack/test/plugin_api_integration/test_suites/event_log/public_api_integration.ts b/x-pack/test/plugin_api_integration/test_suites/event_log/public_api_integration.ts index 0b1ec65593a34..ed7d31efe1c10 100644 --- a/x-pack/test/plugin_api_integration/test_suites/event_log/public_api_integration.ts +++ b/x-pack/test/plugin_api_integration/test_suites/event_log/public_api_integration.ts @@ -23,8 +23,7 @@ export default function ({ getService }: FtrProviderContext) { const esArchiver = getService('esArchiver'); const kibanaServer = getService('kibanaServer'); - // FLAKY: https://github.com/elastic/kibana/issues/168750 - describe.skip('Event Log public API', () => { + describe('Event Log public API', () => { before(async () => { await spacesService.create({ id: 'namespace-a', diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/actions/migrations.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/actions/migrations.ts index ce5c87d2c3fb4..be5503a1cef23 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/actions/migrations.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/actions/migrations.ts @@ -13,7 +13,7 @@ import { getLegacyActionSOById, getLegacyActionNotificationSOById, getRuleSOById, -} from '../../../../../detection_engine_api_integration/utils'; +} from '../../utils'; import { FtrProviderContext } from '../../../../ftr_provider_context'; /** @@ -24,7 +24,7 @@ export default ({ getService }: FtrProviderContext) => { const es = getService('es'); const esArchiver = getService('esArchiver'); - describe('@ess @skipInQA actions migrations', () => { + describe('@ess actions migrations', () => { // This test suite is not meant to test a specific route, but to test the legacy action migration // code that lives in multiple routes. This code is also tested in each of the routes it lives in // but not in as much detail and relying on mocks. This test loads an es_archive containing rules diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/rule_creation/index.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/rule_creation/index.ts index a3e706c580e5c..1d22c7ef57cda 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/rule_creation/index.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/rule_creation/index.ts @@ -10,5 +10,6 @@ export default function ({ loadTestFile }: FtrProviderContext) { describe('Rule creation API', function () { loadTestFile(require.resolve('./create_rules')); loadTestFile(require.resolve('./create_new_terms')); + loadTestFile(require.resolve('./preview_rules')); }); } diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/preview_rules.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/rule_creation/preview_rules.ts similarity index 85% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/group1/preview_rules.ts rename to x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/rule_creation/preview_rules.ts index b930f43dc9809..bcfbf77ef23e1 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/preview_rules.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/rule_creation/preview_rules.ts @@ -9,25 +9,35 @@ import expect from '@kbn/expect'; import { DETECTION_ENGINE_RULES_PREVIEW } from '@kbn/security-solution-plugin/common/constants'; import { ROLES } from '@kbn/security-solution-plugin/common/test'; -import { FtrProviderContext } from '../../common/ftr_provider_context'; import { deleteAllRules, getSimplePreviewRule, getSimpleRulePreviewOutput } from '../../utils'; -import { createUserAndRole, deleteUserAndRole } from '../../../common/services/security_solution'; -// eslint-disable-next-line import/no-default-export +import { + createUserAndRole, + deleteUserAndRole, +} from '../../../../../common/services/security_solution'; + +import { FtrProviderContext } from '../../../../ftr_provider_context'; +import { EsArchivePathBuilder } from '../../../../es_archive_path_builder'; + export default ({ getService }: FtrProviderContext) => { const esArchiver = getService('esArchiver'); const supertest = getService('supertest'); const supertestWithoutAuth = getService('supertestWithoutAuth'); const log = getService('log'); + // TODO: add a new service + const config = getService('config'); + const isServerless = config.get('serverless'); + const dataPathBuilder = new EsArchivePathBuilder(isServerless); + const path = dataPathBuilder.getPath('auditbeat/hosts'); - describe('preview_rules', () => { + describe('@serverless @ess preview_rules', () => { describe('previewing rules', () => { before(async () => { - await esArchiver.load('x-pack/test/functional/es_archives/auditbeat/hosts'); + await esArchiver.load(path); }); after(async () => { - await esArchiver.unload('x-pack/test/functional/es_archives/auditbeat/hosts'); + await esArchiver.unload(path); }); afterEach(async () => { @@ -84,7 +94,7 @@ export default ({ getService }: FtrProviderContext) => { }); }); - describe('t1_analyst', () => { + describe('@brokenInServerless t1_analyst', () => { const role = ROLES.t1_analyst; beforeEach(async () => { @@ -105,7 +115,7 @@ export default ({ getService }: FtrProviderContext) => { }); }); - describe('hunter', () => { + describe('@brokenInServerless hunter', () => { const role = ROLES.hunter; beforeEach(async () => { diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/actions/index.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/actions/index.ts index d9b65ba596dd6..af7e564d1c663 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/actions/index.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/actions/index.ts @@ -8,3 +8,4 @@ export * from './get_slack_action'; export * from './get_web_hook_action'; export * from './remove_uuid_from_actions'; export * from './create_new_action'; +export * from './legacy_actions'; diff --git a/x-pack/test/detection_engine_api_integration/utils/get_legacy_action_notifications_so_by_id.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/actions/legacy_actions/get_legacy_action_notifications_so_by_id.ts similarity index 100% rename from x-pack/test/detection_engine_api_integration/utils/get_legacy_action_notifications_so_by_id.ts rename to x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/actions/legacy_actions/get_legacy_action_notifications_so_by_id.ts diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/actions/legacy_actions/get_legacy_action_so.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/actions/legacy_actions/get_legacy_action_so.ts new file mode 100644 index 0000000000000..e714dfcec28cc --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/actions/legacy_actions/get_legacy_action_so.ts @@ -0,0 +1,25 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import type { Client } from '@elastic/elasticsearch'; +import type { SearchResponse } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import { SECURITY_SOLUTION_SAVED_OBJECT_INDEX } from '@kbn/core-saved-objects-server'; +import type { SavedObjectReference } from '@kbn/core/server'; +import type { LegacyRuleActions } from '@kbn/security-solution-plugin/server/lib/detection_engine/rule_actions_legacy'; + +interface LegacyActionSO extends LegacyRuleActions { + references: SavedObjectReference[]; +} + +/** + * Fetch all legacy action sidecar SOs from the security solution savedObjects index + * @param es The ElasticSearch service + */ +export const getLegacyActionSO = async (es: Client): Promise> => + es.search({ + index: SECURITY_SOLUTION_SAVED_OBJECT_INDEX, + q: 'type:siem-detection-engine-rule-actions', + }); diff --git a/x-pack/test/detection_engine_api_integration/utils/get_legacy_actions_so_by_id.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/actions/legacy_actions/get_legacy_actions_so_by_id.ts similarity index 100% rename from x-pack/test/detection_engine_api_integration/utils/get_legacy_actions_so_by_id.ts rename to x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/actions/legacy_actions/get_legacy_actions_so_by_id.ts diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/actions/legacy_actions/index.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/actions/legacy_actions/index.ts new file mode 100644 index 0000000000000..9b88b1f73d11e --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/actions/legacy_actions/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 './get_legacy_action_so'; +export * from './get_legacy_actions_so_by_id'; +export * from './get_legacy_action_notifications_so_by_id'; diff --git a/x-pack/test/detection_engine_api_integration/utils/get_simple_preview_rule.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/get_simple_preview_rule.ts similarity index 100% rename from x-pack/test/detection_engine_api_integration/utils/get_simple_preview_rule.ts rename to x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/get_simple_preview_rule.ts diff --git a/x-pack/test/detection_engine_api_integration/utils/get_simple_rule_preview_output.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/get_simple_rule_preview_output.ts similarity index 100% rename from x-pack/test/detection_engine_api_integration/utils/get_simple_rule_preview_output.ts rename to x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/get_simple_rule_preview_output.ts diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/index.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/index.ts index 0170faa8ceeda..26862dc62d038 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/index.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/index.ts @@ -26,6 +26,8 @@ export * from './find_immutable_rule_by_id'; export * from './create_rule_with_exception_entries'; export * from './downgrade_immutable_rule'; export * from './get_eql_rule_for_alert_testing'; +export * from './get_simple_preview_rule'; +export * from './get_simple_rule_preview_output'; export * from './get_rule_with_web_hook_action'; export * from './get_simple_rule_output_with_web_hook_action'; export * from './rule_to_update_schema'; diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/ai_assistant/ai_assistant_feature_complete.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/ai_assistant/ai_assistant_feature_complete.cy.ts new file mode 100644 index 0000000000000..8f241dfe9d560 --- /dev/null +++ b/x-pack/test/security_solution_cypress/cypress/e2e/ai_assistant/ai_assistant_feature_complete.cy.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 { AI_ASSISTANT_BUTTON } from '../../screens/ai_assistant'; +import { login } from '../../tasks/login'; +import { visitGetStartedPage } from '../../tasks/navigation'; + +describe( + 'App Features for Security Complete', + { + tags: ['@serverless'], + env: { + ftrConfig: { + productTypes: [ + { product_line: 'security', product_tier: 'complete' }, + { product_line: 'endpoint', product_tier: 'complete' }, + ], + }, + }, + }, + () => { + beforeEach(() => { + login(); + }); + + it('should have have AI Assistant available', () => { + visitGetStartedPage(); + cy.get(AI_ASSISTANT_BUTTON).should('exist'); + }); + } +); diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/ai_assistant/ai_assistant_feature_essentials.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/ai_assistant/ai_assistant_feature_essentials.cy.ts new file mode 100644 index 0000000000000..b16ea50043c17 --- /dev/null +++ b/x-pack/test/security_solution_cypress/cypress/e2e/ai_assistant/ai_assistant_feature_essentials.cy.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 { AI_ASSISTANT_BUTTON } from '../../screens/ai_assistant'; +import { login } from '../../tasks/login'; +import { visitGetStartedPage } from '../../tasks/navigation'; + +describe( + 'App Features for Security Essentials', + { + tags: ['@serverless'], + env: { + ftrConfig: { + productTypes: [ + { product_line: 'security', product_tier: 'essentials' }, + { product_line: 'endpoint', product_tier: 'essentials' }, + ], + }, + }, + }, + () => { + beforeEach(() => { + login(); + }); + + it('should not have AI Assistant available', () => { + visitGetStartedPage(); + cy.get(AI_ASSISTANT_BUTTON).should('not.exist'); + }); + } +); diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/alerts_details.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/alerts_details.cy.ts index bfa5a98921be0..3f89a68441cdb 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/alerts_details.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/alerts_details.cy.ts @@ -40,7 +40,7 @@ import { waitForPageToBeLoaded as waitForRuleDetailsPageToBeLoaded, } from '../../../tasks/rule_details'; -describe('Alert details flyout', () => { +describe('Alert details flyout', { tags: ['@ess', '@serverless'] }, () => { describe('Basic functions', () => { beforeEach(() => { cleanKibana(); @@ -52,23 +52,18 @@ describe('Alert details flyout', () => { expandFirstAlert(); }); - // Issue tracked in: https://github.com/elastic/kibana/issues/167809 - it( - 'should update the table when status of the alert is updated', - { tags: ['@ess', '@brokenInServerless'] }, - () => { - cy.get(OVERVIEW_RULE).should('be.visible'); - cy.get(ALERTS_TABLE_COUNT).should('have.text', '2 alerts'); - cy.get(ALERT_SUMMARY_SEVERITY_DONUT_CHART).should('contain.text', '2alerts'); - expandFirstAlert(); - changeAlertStatusTo('acknowledged'); - cy.get(ALERTS_TABLE_COUNT).should('have.text', '1 alert'); - cy.get(ALERT_SUMMARY_SEVERITY_DONUT_CHART).should('contain.text', '1alert'); - } - ); + it('should update the table when status of the alert is updated', () => { + cy.get(OVERVIEW_RULE).should('be.visible'); + cy.get(ALERTS_TABLE_COUNT).should('have.text', '2 alerts'); + cy.get(ALERT_SUMMARY_SEVERITY_DONUT_CHART).should('contain.text', '2alerts'); + expandFirstAlert(); + changeAlertStatusTo('acknowledged'); + cy.get(ALERTS_TABLE_COUNT).should('have.text', '1 alert'); + cy.get(ALERT_SUMMARY_SEVERITY_DONUT_CHART).should('contain.text', '1alert'); + }); }); - describe('With unmapped fields', { tags: ['@ess', '@serverless'] }, () => { + describe('With unmapped fields', () => { before(() => { cleanKibana(); cy.task('esArchiverLoad', { archiveName: 'unmapped_fields' }); @@ -141,7 +136,7 @@ describe('Alert details flyout', () => { }); }); - describe('Url state management', { tags: ['@ess', '@serverless'] }, () => { + describe('Url state management', () => { before(() => { cleanKibana(); cy.task('esArchiverLoad', { archiveName: 'query_alert', useCreate: true, docsOnly: true }); @@ -187,7 +182,7 @@ describe('Alert details flyout', () => { }); }); - describe('Localstorage management', { tags: ['@ess', '@serverless'] }, () => { + describe('Localstorage management', () => { const ARCHIVED_RULE_ID = '7015a3e2-e4ea-11ed-8c11-49608884878f'; const ARCHIVED_RULE_NAME = 'Endpoint Security'; diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/header/navigation.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/navigation/navigation.cy.ts similarity index 56% rename from x-pack/test/security_solution_cypress/cypress/e2e/header/navigation.cy.ts rename to x-pack/test/security_solution_cypress/cypress/e2e/navigation/navigation.cy.ts index 9ca9adf8e6cb6..788ff1d9eac0f 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/header/navigation.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/navigation/navigation.cy.ts @@ -31,9 +31,10 @@ import { SETTINGS, ENTITY_ANALYTICS, } from '../../screens/security_header'; +import * as ServerlessHeaders from '../../screens/serverless_security_header'; import { login } from '../../tasks/login'; -import { visit, visitWithTimeRange } from '../../tasks/navigation'; +import { visit, visitGetStartedPage, visitWithTimeRange } from '../../tasks/navigation'; import { navigateFromHeaderTo } from '../../tasks/security_header'; import { @@ -61,6 +62,15 @@ import { POLICIES_URL, ENTITY_ANALYTICS_URL, INDICATORS_URL, + DISCOVER_URL, + RULES_LANDING_URL, + RULES_COVERAGE_URL, + INVESTIGATIONS_URL, + OSQUERY_URL, + MACHINE_LEARNING_LANDING_URL, + ASSETS_URL, + FLEET_URL, + CLOUD_DEFEND_URL, } from '../../urls/navigation'; import { RULES_MANAGEMENT_URL } from '../../urls/rules_management'; import { @@ -247,3 +257,144 @@ describe('Kibana navigation to all pages in the Security app ', { tags: '@ess' } cy.url().should('include', MANAGE_URL); }); }); + +describe('Serverless side navigation links', { tags: '@serverless' }, () => { + beforeEach(() => { + login(); + visitGetStartedPage(); + }); + + it('navigates to the Discover page', () => { + navigateFromHeaderTo(ServerlessHeaders.DISCOVER, true); + cy.url().should('include', DISCOVER_URL); + }); + + it('navigates to the Dashboards landing page', () => { + navigateFromHeaderTo(ServerlessHeaders.DASHBOARDS, true); + cy.url().should('include', DASHBOARDS_URL); + }); + + it('navigates to the Overview page', () => { + navigateFromHeaderTo(ServerlessHeaders.OVERVIEW, true); + cy.url().should('include', OVERVIEW_URL); + }); + + it('navigates to the Detection & Response page', () => { + navigateFromHeaderTo(ServerlessHeaders.DETECTION_RESPONSE, true); + cy.url().should('include', DETECTION_AND_RESPONSE_URL); + }); + + it('navigates to the Entity Analytics page', () => { + navigateFromHeaderTo(ServerlessHeaders.ENTITY_ANALYTICS, true); + cy.url().should('include', ENTITY_ANALYTICS_URL); + }); + + it('navigates to the Kubernetes page', () => { + navigateFromHeaderTo(ServerlessHeaders.KUBERNETES, true); + cy.url().should('include', KUBERNETES_URL); + }); + + it('navigates to the CSP dashboard page', () => { + navigateFromHeaderTo(ServerlessHeaders.CSP_DASHBOARD, true); + cy.url().should('include', CSP_DASHBOARD_URL); + }); + + it('navigates to the Rules landing page', () => { + navigateFromHeaderTo(ServerlessHeaders.RULES_LANDING, true); + cy.url().should('include', RULES_LANDING_URL); + }); + it('navigates to the Rules page', () => { + navigateFromHeaderTo(ServerlessHeaders.RULES, true); + cy.url().should('include', RULES_MANAGEMENT_URL); + }); + + it('navigates to the Rules page', () => { + navigateFromHeaderTo(ServerlessHeaders.CSP_BENCHMARKS, true); + cy.url().should('include', CSP_BENCHMARKS_URL); + }); + + it('navigates to the Exceptions page', () => { + navigateFromHeaderTo(ServerlessHeaders.EXCEPTIONS, true); + cy.url().should('include', EXCEPTIONS_URL); + }); + + it('navigates to the Rules coverage page', () => { + navigateFromHeaderTo(ServerlessHeaders.RULES_COVERAGE, true); + cy.url().should('include', RULES_COVERAGE_URL); + }); + + it('navigates to the Alerts page', () => { + navigateFromHeaderTo(ServerlessHeaders.ALERTS, true); + cy.url().should('include', ALERTS_URL); + }); + + it('navigates to the Findings page', () => { + navigateFromHeaderTo(ServerlessHeaders.CSP_FINDINGS, true); + cy.url().should('include', CSP_FINDINGS_URL); + }); + + it('navigates to the Cases page', () => { + navigateFromHeaderTo(ServerlessHeaders.CASES, true); + cy.url().should('include', CASES_URL); + }); + + it('navigates to the Investigations page', () => { + navigateFromHeaderTo(ServerlessHeaders.INVESTIGATIONS, true); + cy.url().should('include', INVESTIGATIONS_URL); + }); + + it('navigates to the Timelines page', () => { + navigateFromHeaderTo(ServerlessHeaders.TIMELINES, true); + cy.url().should('include', TIMELINES_URL); + }); + it('navigates to the Osquery page', () => { + navigateFromHeaderTo(ServerlessHeaders.OSQUERY, true); + cy.url().should('include', OSQUERY_URL); + }); + + it('navigates to the Indicators page', () => { + navigateFromHeaderTo(ServerlessHeaders.THREAT_INTELLIGENCE, true); + cy.url().should('include', INDICATORS_URL); + }); + + it('navigates to the Explore landing page', () => { + navigateFromHeaderTo(ServerlessHeaders.EXPLORE, true); + cy.url().should('include', EXPLORE_URL); + }); + + it('navigates to the Hosts page', () => { + navigateFromHeaderTo(ServerlessHeaders.HOSTS, true); + cy.url().should('include', hostsUrl('allHosts')); + }); + + it('navigates to the Network page', () => { + navigateFromHeaderTo(ServerlessHeaders.NETWORK, true); + cy.url().should('include', NETWORK_URL); + }); + + it('navigates to the Users page', () => { + navigateFromHeaderTo(ServerlessHeaders.USERS, true); + cy.url().should('include', USERS_URL); + }); + + it('navigates to the Assets page', () => { + navigateFromHeaderTo(ServerlessHeaders.ASSETS, true); + cy.url().should('include', ASSETS_URL); + }); + it('navigates to the Endpoints page', () => { + navigateFromHeaderTo(ServerlessHeaders.ENDPOINTS, true); + cy.url().should('include', ENDPOINTS_URL); + }); + it('navigates to the Fleet page', () => { + navigateFromHeaderTo(ServerlessHeaders.FLEET, true); + cy.url().should('include', FLEET_URL); + }); + it('navigates to the Cloud defend page', () => { + navigateFromHeaderTo(ServerlessHeaders.CLOUD_DEFEND, true); + cy.url().should('include', CLOUD_DEFEND_URL); + }); + it('navigates to the Machine learning landing page', () => { + navigateFromHeaderTo(ServerlessHeaders.MACHINE_LEARNING, true); + cy.url().should('include', MACHINE_LEARNING_LANDING_URL); + }); +}); diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/header/search_bar.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/navigation/search_bar.cy.ts similarity index 100% rename from x-pack/test/security_solution_cypress/cypress/e2e/header/search_bar.cy.ts rename to x-pack/test/security_solution_cypress/cypress/e2e/navigation/search_bar.cy.ts diff --git a/x-pack/test/security_solution_cypress/cypress/screens/ai_assistant.ts b/x-pack/test/security_solution_cypress/cypress/screens/ai_assistant.ts new file mode 100644 index 0000000000000..2abd9208dd070 --- /dev/null +++ b/x-pack/test/security_solution_cypress/cypress/screens/ai_assistant.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 const AI_ASSISTANT_BUTTON = '[data-test-subj="assistantHeaderLink"]'; diff --git a/x-pack/test/security_solution_cypress/cypress/screens/serverless_security_header.ts b/x-pack/test/security_solution_cypress/cypress/screens/serverless_security_header.ts index 11885714a0dda..4ac4463ae4db1 100644 --- a/x-pack/test/security_solution_cypress/cypress/screens/serverless_security_header.ts +++ b/x-pack/test/security_solution_cypress/cypress/screens/serverless_security_header.ts @@ -6,28 +6,33 @@ */ // main panels links -export const DASHBOARDS = '[data-test-subj$="nav-item-deepLinkId-securitySolutionUI:dashboards"]'; +export const DASHBOARDS = '[data-test-subj*="nav-item-deepLinkId-securitySolutionUI:dashboards"]'; export const DASHBOARDS_PANEL_BTN = '[data-test-subj*="panelOpener-deepLinkId-securitySolutionUI:dashboards"]'; export const INVESTIGATIONS = - '[data-test-subj$="nav-item-deepLinkId-securitySolutionUI:investigations"]'; + '[data-test-subj*="nav-item-deepLinkId-securitySolutionUI:investigations"]'; export const INVESTIGATIONS_PANEL_BTN = '[data-test-subj*="panelOpener-deepLinkId-securitySolutionUI:investigations"]'; -export const EXPLORE = '[data-test-subj$="nav-item-deepLinkId-securitySolutionUI:explore"]'; +export const EXPLORE = '[data-test-subj*="nav-item-deepLinkId-securitySolutionUI:explore"]'; export const EXPLORE_PANEL_BTN = '[data-test-subj*="panelOpener-deepLinkId-securitySolutionUI:explore"]'; export const RULES_LANDING = - '[data-test-subj$="nav-item-deepLinkId-securitySolutionUI:rules-landing"]'; + '[data-test-subj*="nav-item-deepLinkId-securitySolutionUI:rules-landing"]'; export const RULES_PANEL_BTN = '[data-test-subj*="panelOpener-deepLinkId-securitySolutionUI:rules-landing"]'; -export const ASSETS = '[data-test-subj$="nav-item-deepLinkId-securitySolutionUI:assets"]'; +export const ASSETS = '[data-test-subj*="nav-item-deepLinkId-securitySolutionUI:assets"]'; export const ASSETS_PANEL_BTN = '[data-test-subj*="panelOpener-deepLinkId-securitySolutionUI:assets"]'; +export const MACHINE_LEARNING = + '[data-test-subj*="nav-item-deepLinkId-securitySolutionUI:machine_learning-landing"]'; +export const MACHINE_LEARNING_BTN = + '[data-test-subj*="panelOpener-deepLinkId-securitySolutionUI:machine_learning-landing"]'; + // main direct links export const DISCOVER = '[data-test-subj*="nav-item-deepLinkId-discover"]'; @@ -36,10 +41,12 @@ export const ALERTS = '[data-test-subj*="nav-item-deepLinkId-securitySolutionUI: export const CSP_FINDINGS = '[data-test-subj*="nav-item-deepLinkId-securitySolutionUI:cloud_security_posture-findings"]'; -export const CASES = '[data-test-subj*="nav-item-deepLinkId-securitySolutionUI:cases"]'; +export const THREAT_INTELLIGENCE = + '[data-test-subj*="nav-item-deepLinkId-securitySolutionUI:threat_intelligence"]'; -// nested links +export const CASES = '[data-test-subj*="nav-item-deepLinkId-securitySolutionUI:cases"]'; +// nested panel links export const OVERVIEW = '[data-test-subj="solutionSideNavPanelLink-overview"]'; export const DETECTION_RESPONSE = '[data-test-subj="solutionSideNavPanelLink-detection_response"]'; @@ -47,6 +54,7 @@ export const DETECTION_RESPONSE = '[data-test-subj="solutionSideNavPanelLink-det export const ENTITY_ANALYTICS = '[data-test-subj="solutionSideNavPanelLink-entity_analytics"]'; export const TIMELINES = '[data-test-subj="solutionSideNavPanelLink-timelines"]'; +export const OSQUERY = '[data-test-subj="solutionSideNavPanelLink-osquery:"]'; export const KUBERNETES = '[data-test-subj="solutionSideNavPanelLink-kubernetes"]'; @@ -55,7 +63,9 @@ export const CSP_DASHBOARD = export const HOSTS = '[data-test-subj="solutionSideNavPanelLink-hosts"]'; +export const FLEET = '[data-test-subj="solutionSideNavPanelLink-fleet:"]'; export const ENDPOINTS = '[data-test-subj="solutionSideNavPanelLink-endpoints"]'; +export const CLOUD_DEFEND = '[data-test-subj="solutionSideNavPanelLink-cloud_defend"]'; export const POLICIES = '[data-test-subj="solutionSideNavPanelLink-policy"]'; @@ -68,20 +78,23 @@ export const BLOCKLIST = '[data-test-subj="solutionSideNavPanelLink-blocklist"]' export const CSP_BENCHMARKS = '[data-test-subj="solutionSideNavPanelLink-cloud_security_posture-benchmarks"]'; +export const RULES_COVERAGE = '[data-test-subj="solutionSideNavPanelLink-coverage-overview"]'; + export const NETWORK = '[data-test-subj="solutionSideNavPanelLink-network"]'; export const USERS = '[data-test-subj="solutionSideNavPanelLink-users"]'; -export const INDICATORS = '[data-test-subj="solutionSideNavItemLink-threat_intelligence"]'; - export const RULES = '[data-test-subj="solutionSideNavPanelLink-rules"]'; export const EXCEPTIONS = '[data-test-subj="solutionSideNavPanelLink-exceptions"]'; +export const getBreadcrumb = (deepLinkId: string) => { + return `breadcrumb-deepLinkId-${deepLinkId}`; +}; // opens the navigation panel for a given nested link -export const openNavigationPanelFor = (page: string) => { +export const openNavigationPanelFor = (pageName: string) => { let panel; - switch (page) { + switch (pageName) { case OVERVIEW: case DETECTION_RESPONSE: case KUBERNETES: @@ -90,23 +103,27 @@ export const openNavigationPanelFor = (page: string) => { panel = DASHBOARDS_PANEL_BTN; break; } + case RULES: + case CSP_BENCHMARKS: + case EXCEPTIONS: + case RULES_COVERAGE: { + panel = RULES_PANEL_BTN; + break; + } + case TIMELINES: + case OSQUERY: { + panel = INVESTIGATIONS_PANEL_BTN; + break; + } case HOSTS: case NETWORK: case USERS: { panel = EXPLORE_PANEL_BTN; break; } - case RULES: - case EXCEPTIONS: - case CSP_BENCHMARKS: { - panel = RULES_PANEL_BTN; - break; - } + case FLEET: case ENDPOINTS: - case TRUSTED_APPS: - case EVENT_FILTERS: - case POLICIES: - case BLOCKLIST: { + case CLOUD_DEFEND: { panel = ASSETS_PANEL_BTN; break; } @@ -117,6 +134,6 @@ export const openNavigationPanelFor = (page: string) => { }; // opens the navigation panel of a main link -export const openNavigationPanel = (page: string) => { - cy.get(page).click(); +export const openNavigationPanel = (pageName: string) => { + cy.get(pageName).click(); }; diff --git a/x-pack/test/security_solution_cypress/cypress/tasks/navigation.ts b/x-pack/test/security_solution_cypress/cypress/tasks/navigation.ts index 20e34387d7f12..b7c6f55386c3f 100644 --- a/x-pack/test/security_solution_cypress/cypress/tasks/navigation.ts +++ b/x-pack/test/security_solution_cypress/cypress/tasks/navigation.ts @@ -9,7 +9,7 @@ import { encode } from '@kbn/rison'; import { NEW_FEATURES_TOUR_STORAGE_KEYS } from '@kbn/security-solution-plugin/common/constants'; import type { SecurityRoleName } from '@kbn/security-solution-plugin/common/test'; -import { hostDetailsUrl, userDetailsUrl } from '../urls/navigation'; +import { GET_STARTED_URL, hostDetailsUrl, userDetailsUrl } from '../urls/navigation'; import { constructUrlWithUser, getUrlWithRoute, User } from './login'; export const visit = ( @@ -87,6 +87,11 @@ export const visitHostDetailsPage = (hostName = 'suricata-iowa') => { cy.get('[data-test-subj="loading-spinner"]').should('not.exist'); }; +export const visitGetStartedPage = () => { + visit(GET_STARTED_URL); + cy.get('#security-solution-app').should('exist'); +}; + export const visitUserDetailsPage = (userName = 'test') => { visitWithTimeRange(userDetailsUrl(userName)); }; diff --git a/x-pack/test/security_solution_cypress/cypress/tasks/security_header.ts b/x-pack/test/security_solution_cypress/cypress/tasks/security_header.ts index 4cca17aa18dae..73549d9ed052c 100644 --- a/x-pack/test/security_solution_cypress/cypress/tasks/security_header.ts +++ b/x-pack/test/security_solution_cypress/cypress/tasks/security_header.ts @@ -7,6 +7,7 @@ import { TOASTER } from '../screens/alerts_detection_rules'; import { KQL_INPUT, openNavigationPanelFor, REFRESH_BUTTON } from '../screens/security_header'; +import { openNavigationPanelFor as openServerlessNavigationPanelFor } from '../screens/serverless_security_header'; export const clearSearchBar = () => { cy.get(KQL_INPUT).clear(); @@ -17,9 +18,13 @@ export const kqlSearch = (search: string) => { cy.get(KQL_INPUT).type(search, { force: true }); }; -export const navigateFromHeaderTo = (page: string) => { - openNavigationPanelFor(page); - cy.get(page).click({ force: true }); +export const navigateFromHeaderTo = (page: string, isServerless: boolean = false) => { + if (isServerless) { + openServerlessNavigationPanelFor(page); + } else { + openNavigationPanelFor(page); + } + cy.get(page).click(); }; export const refreshPage = () => { diff --git a/x-pack/test/security_solution_cypress/cypress/urls/navigation.ts b/x-pack/test/security_solution_cypress/cypress/urls/navigation.ts index b63e785c96750..65c87efcc61b9 100644 --- a/x-pack/test/security_solution_cypress/cypress/urls/navigation.ts +++ b/x-pack/test/security_solution_cypress/cypress/urls/navigation.ts @@ -10,10 +10,13 @@ export const KIBANA_SAVED_OBJECTS = '/app/management/kibana/objects'; export const LOGOUT_URL = '/logout'; // Common +export const GET_STARTED_URL = '/app/security/get_started'; export const MANAGE_URL = '/app/security/manage'; export const DASHBOARDS_URL = '/app/security/dashboards'; +export const ASSETS_URL = '/app/security/assets'; export const ENDPOINTS_URL = '/app/security/administration/endpoints'; +export const CLOUD_DEFEND_URL = '/app/security/cloud_defend'; export const POLICIES_URL = '/app/security/administration/policy'; export const USERS_URL = '/app/security/users/allUsers'; export const TRUSTED_APPS_URL = '/app/security/administration/trusted_apps'; @@ -23,6 +26,9 @@ export const CSP_BENCHMARKS_URL = '/app/security/cloud_security_posture/benchmar export const CSP_DASHBOARD_URL = '/app/security/cloud_security_posture/dashboard'; export const CSP_FINDINGS_URL = '/app/security/cloud_security_posture/findings/vulnerabilities'; +export const RULES_LANDING_URL = '/app/security/rules/landing'; +export const RULES_COVERAGE_URL = '/app/security/rules_coverage_overview'; + export const NETWORK_URL = '/app/security/network/flows'; export const OVERVIEW_URL = '/app/security/overview'; @@ -34,6 +40,7 @@ export const EXPLORE_URL = '/app/security/explore'; export const userDetailsUrl = (userName: string) => `/app/security/users/name/${userName}/authentications`; +export const INVESTIGATIONS_URL = '/app/security/investigations'; export const TIMELINES_URL = '/app/security/timelines/default'; export const TIMELINE_TEMPLATES_URL = '/app/security/timelines/template'; export const CASES_URL = '/app/security/cases'; @@ -49,6 +56,8 @@ export const DISCOVER_WITH_PINNED_FILTER_URL = export const hostDetailsUrl = (hostName: string) => `/app/security/hosts/${hostName}/authentications`; +export const MACHINE_LEARNING_LANDING_URL = '/app/security/ml'; + // Detection and Response export const DETECTION_AND_RESPONSE_URL = '/app/security/detection_response'; export const ALERTS_URL = '/app/security/alerts'; @@ -58,3 +67,8 @@ export const ENTITY_ANALYTICS_MANAGEMENT_URL = '/app/security/entity_analytics_m export const exceptionsListDetailsUrl = (listId: string) => `/app/security/exceptions/details/${listId}`; + +// External (serverless) +export const DISCOVER_URL = '/app/discover'; +export const OSQUERY_URL = '/app/osquery'; +export const FLEET_URL = '/app/fleet'; diff --git a/x-pack/test/security_solution_cypress/package.json b/x-pack/test/security_solution_cypress/package.json index 988f504224b20..c7fe67bedd99a 100644 --- a/x-pack/test/security_solution_cypress/package.json +++ b/x-pack/test/security_solution_cypress/package.json @@ -10,7 +10,7 @@ "cypress:run:ess": "yarn cypress:ess --spec './cypress/e2e/!(investigations|explore)/**/*.cy.ts'", "cypress:run:cases:ess": "yarn cypress:ess --spec './cypress/e2e/explore/cases/*.cy.ts'", "cypress:ess": "TZ=UTC NODE_OPTIONS=--openssl-legacy-provider node ../../plugins/security_solution/scripts/start_cypress_parallel run --config-file ../../test/security_solution_cypress/cypress/cypress_ci.config.ts --ftr-config-file ../../test/security_solution_cypress/cli_config", - "cypress:run:respops:ess": "yarn cypress:ess --spec './cypress/e2e/(detection_alerts|detection_rules|exceptions)/*.cy.ts'", + "cypress:run:respops:ess": "yarn cypress:ess --spec './cypress/e2e/(detection_response|exceptions)/**/*.cy.ts'", "cypress:investigations:run:ess": "yarn cypress:ess --spec './cypress/e2e/investigations/**/*.cy.ts'", "cypress:explore:run:ess": "yarn cypress:ess --spec './cypress/e2e/explore/**/*.cy.ts'", "cypress:changed-specs-only:ess": "yarn cypress:ess --changed-specs-only --env burn=5", diff --git a/x-pack/test/security_solution_endpoint/apps/endpoint/endpoint_list.ts b/x-pack/test/security_solution_endpoint/apps/endpoint/endpoint_list.ts index 3c66c28d570c0..c1eed560a2142 100644 --- a/x-pack/test/security_solution_endpoint/apps/endpoint/endpoint_list.ts +++ b/x-pack/test/security_solution_endpoint/apps/endpoint/endpoint_list.ts @@ -14,6 +14,7 @@ import { deleteAllDocsFromMetadataCurrentIndex, deleteAllDocsFromMetadataUnitedIndex, } from '../../../security_solution_endpoint_api_int/apis/data_stream_helper'; +import { targetTags } from '../../target_tags'; export default ({ getPageObjects, getService }: FtrProviderContext) => { const pageObjects = getPageObjects(['common', 'endpoint', 'header', 'endpointPageUtils']); @@ -85,6 +86,8 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { }; describe('endpoint list', function () { + targetTags(this, ['@ess', '@serverless']); + let indexedData: IndexedHostsAndAlertsResponse; describe('when initially navigating to page', () => { before(async () => { @@ -114,7 +117,8 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { await pageObjects.endpoint.navigateToEndpointList(); }); - describe('when there is data,', () => { + // FLAKY: https://github.com/elastic/kibana/issues/170357 + describe.skip('when there is data,', () => { before(async () => { indexedData = await endpointTestResources.loadEndpointData({ numHosts: 3 }); await pageObjects.endpoint.navigateToEndpointList(); diff --git a/x-pack/test/security_solution_endpoint/apps/endpoint/endpoint_permissions.ts b/x-pack/test/security_solution_endpoint/apps/endpoint/endpoint_permissions.ts index 51d6ae8bcfadc..061e8936bf241 100644 --- a/x-pack/test/security_solution_endpoint/apps/endpoint/endpoint_permissions.ts +++ b/x-pack/test/security_solution_endpoint/apps/endpoint/endpoint_permissions.ts @@ -10,13 +10,16 @@ import { IndexedHostsAndAlertsResponse } from '@kbn/security-solution-plugin/com import { SecurityRoleName } from '@kbn/security-solution-plugin/common/test'; import { FtrProviderContext } from '../../ftr_provider_context'; import { createUserAndRole, deleteUserAndRole } from '../../../common/services/security_solution'; +import { targetTags } from '../../target_tags'; export default ({ getPageObjects, getService }: FtrProviderContext) => { const PageObjects = getPageObjects(['security', 'endpoint', 'detections', 'hosts']); const testSubjects = getService('testSubjects'); const endpointTestResources = getService('endpointTestResources'); - describe('Endpoint permissions:', () => { + describe('Endpoint permissions:', function () { + targetTags(this, ['@ess']); + let indexedData: IndexedHostsAndAlertsResponse; before(async () => { diff --git a/x-pack/test/security_solution_endpoint/apps/endpoint/endpoint_solution_integrations.ts b/x-pack/test/security_solution_endpoint/apps/endpoint/endpoint_solution_integrations.ts index c438b457c4b93..49e068a1a0c9a 100644 --- a/x-pack/test/security_solution_endpoint/apps/endpoint/endpoint_solution_integrations.ts +++ b/x-pack/test/security_solution_endpoint/apps/endpoint/endpoint_solution_integrations.ts @@ -11,6 +11,7 @@ import { TimelineResponse } from '@kbn/security-solution-plugin/common/api/timel import { kibanaPackageJson } from '@kbn/repo-info'; import { type IndexedEndpointRuleAlerts } from '@kbn/security-solution-plugin/common/endpoint/data_loaders/index_endpoint_rule_alerts'; import { FtrProviderContext } from '../../ftr_provider_context'; +import { targetTags } from '../../target_tags'; /** * Test suite is meant to cover usages of endpoint functionality or access to endpoint @@ -24,7 +25,9 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { const testSubjects = getService('testSubjects'); const pageObjects = getPageObjects(['common', 'timeline']); - describe('App level Endpoint functionality', () => { + describe('App level Endpoint functionality', function () { + targetTags(this, ['@ess']); + let indexedData: IndexedHostsAndAlertsResponse; let indexedAlerts: IndexedEndpointRuleAlerts; let endpointAgentId: string; @@ -59,8 +62,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { } }); - // FLAKY: https://github.com/elastic/kibana/issues/165344 - describe.skip('from Timeline', () => { + describe('from Timeline', () => { let timeline: TimelineResponse; before(async () => { diff --git a/x-pack/test/security_solution_endpoint/apps/endpoint/endpoint_telemetry.ts b/x-pack/test/security_solution_endpoint/apps/endpoint/endpoint_telemetry.ts index 3dc4f9fb3f3a4..e9c213e50e495 100644 --- a/x-pack/test/security_solution_endpoint/apps/endpoint/endpoint_telemetry.ts +++ b/x-pack/test/security_solution_endpoint/apps/endpoint/endpoint_telemetry.ts @@ -7,6 +7,7 @@ import expect from '@kbn/expect'; import { FtrProviderContext } from '../../ftr_provider_context'; +import { targetTags } from '../../target_tags'; export default function ({ getService }: FtrProviderContext) { const esArchiver = getService('esArchiver'); @@ -15,7 +16,9 @@ export default function ({ getService }: FtrProviderContext) { // The source of the data for these tests have changed and need to be updated // There are currently tests in the security_solution application being maintained - describe.skip('security solution endpoint telemetry', () => { + describe.skip('security solution endpoint telemetry', function () { + targetTags(this, ['@ess']); + after(async () => { await kibanaServer.savedObjects.cleanStandardList(); }); diff --git a/x-pack/test/security_solution_endpoint/apps/endpoint/index.ts b/x-pack/test/security_solution_endpoint/apps/endpoint/index.ts index ed0efeca86b32..081a03fef4f51 100644 --- a/x-pack/test/security_solution_endpoint/apps/endpoint/index.ts +++ b/x-pack/test/security_solution_endpoint/apps/endpoint/index.ts @@ -6,6 +6,7 @@ */ import { getRegistryUrl as getRegistryUrlFromIngest } from '@kbn/fleet-plugin/server'; +import { isServerlessKibanaFlavor } from '@kbn/security-solution-plugin/scripts/endpoint/common/stack_services'; import { FtrProviderContext } from '../../ftr_provider_context'; import { getRegistryUrlFromTestEnv, @@ -13,12 +14,13 @@ import { } from '../../../security_solution_endpoint_api_int/registry'; export default function (providerContext: FtrProviderContext) { - const { loadTestFile, getService } = providerContext; + const { loadTestFile, getService, getPageObjects } = providerContext; describe('endpoint', function () { const ingestManager = getService('ingestManager'); const log = getService('log'); const endpointTestResources = getService('endpointTestResources'); + const kbnClient = getService('kibanaServer'); if (!isRegistryEnabled()) { log.warning('These tests are being run with an external package registry'); @@ -33,6 +35,12 @@ export default function (providerContext: FtrProviderContext) { log.info('installing/upgrading Endpoint fleet package'); await endpointTestResources.installOrUpgradeEndpointFleetPackage(); + + if (await isServerlessKibanaFlavor(kbnClient)) { + log.info('login for serverless environment'); + const pageObjects = getPageObjects(['svlCommonPage']); + await pageObjects.svlCommonPage.login(); + } }); loadTestFile(require.resolve('./endpoint_list')); loadTestFile(require.resolve('./endpoint_telemetry')); diff --git a/x-pack/test/security_solution_endpoint/apps/endpoint/responder.ts b/x-pack/test/security_solution_endpoint/apps/endpoint/responder.ts index 6a220d35ffffd..855ab17178e51 100644 --- a/x-pack/test/security_solution_endpoint/apps/endpoint/responder.ts +++ b/x-pack/test/security_solution_endpoint/apps/endpoint/responder.ts @@ -10,6 +10,7 @@ import { TimelineResponse } from '@kbn/security-solution-plugin/common/api/timel import { type IndexedEndpointRuleAlerts } from '@kbn/security-solution-plugin/common/endpoint/data_loaders/index_endpoint_rule_alerts'; import { DATE_RANGE_OPTION_TO_TEST_SUBJ_MAP } from '@kbn/security-solution-plugin/common/test'; import { FtrProviderContext } from '../../ftr_provider_context'; +import { targetTags } from '../../target_tags'; export default ({ getPageObjects, getService }: FtrProviderContext) => { const pageObjects = getPageObjects([ @@ -82,6 +83,8 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { }; describe('Response Actions Responder', function () { + targetTags(this, ['@ess', '@serverless']); + let indexedData: IndexedHostsAndAlertsResponse; let endpointAgentId: string; diff --git a/x-pack/test/security_solution_endpoint/apps/integrations/artifact_entries_list.ts b/x-pack/test/security_solution_endpoint/apps/integrations/artifact_entries_list.ts index d62487d4fa383..9fcc87ceffa81 100644 --- a/x-pack/test/security_solution_endpoint/apps/integrations/artifact_entries_list.ts +++ b/x-pack/test/security_solution_endpoint/apps/integrations/artifact_entries_list.ts @@ -26,6 +26,7 @@ import { MultipleArtifactActionsType, } from './mocks'; import { PolicyTestResourceInfo } from '../../services/endpoint_policy'; +import { targetTags } from '../../target_tags'; export default ({ getPageObjects, getService }: FtrProviderContext) => { const pageObjects = getPageObjects(['common', 'artifactEntriesList']); @@ -52,6 +53,8 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { }; describe('For each artifact list under management', function () { + targetTags(this, ['@ess', '@serverless']); + this.timeout(60_000 * 5); let indexedData: IndexedHostsAndAlertsResponse; let policyInfo: PolicyTestResourceInfo; diff --git a/x-pack/test/security_solution_endpoint/apps/integrations/fleet_integrations.ts b/x-pack/test/security_solution_endpoint/apps/integrations/fleet_integrations.ts index ea5746060dedc..b6255d5b9a60b 100644 --- a/x-pack/test/security_solution_endpoint/apps/integrations/fleet_integrations.ts +++ b/x-pack/test/security_solution_endpoint/apps/integrations/fleet_integrations.ts @@ -10,6 +10,7 @@ import { deleteMetadataStream, deleteAllDocsFromMetadataCurrentIndex, } from '../../../security_solution_endpoint_api_int/apis/data_stream_helper'; +import { targetTags } from '../../target_tags'; export default function ({ getPageObjects, getService }: FtrProviderContext) { const { fleetIntegrations, trustedApps } = getPageObjects(['trustedApps', 'fleetIntegrations']); @@ -19,6 +20,8 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { const browser = getService('browser'); describe('When in the Fleet application', function () { + targetTags(this, ['@ess', '@serverless']); + before(async () => { await esArchiver.load('x-pack/test/functional/es_archives/endpoint/metadata/api_feature', { useCreate: true, diff --git a/x-pack/test/security_solution_endpoint/apps/integrations/index.ts b/x-pack/test/security_solution_endpoint/apps/integrations/index.ts index 0da61dbbb637f..56c66bfac241e 100644 --- a/x-pack/test/security_solution_endpoint/apps/integrations/index.ts +++ b/x-pack/test/security_solution_endpoint/apps/integrations/index.ts @@ -6,6 +6,7 @@ */ import { getRegistryUrl as getRegistryUrlFromIngest } from '@kbn/fleet-plugin/server'; +import { isServerlessKibanaFlavor } from '@kbn/security-solution-plugin/scripts/endpoint/common/stack_services'; import { FtrProviderContext } from '../../ftr_provider_context'; import { isRegistryEnabled, @@ -13,12 +14,13 @@ import { } from '../../../security_solution_endpoint_api_int/registry'; export default function (providerContext: FtrProviderContext) { - const { loadTestFile, getService } = providerContext; + const { loadTestFile, getService, getPageObjects } = providerContext; describe('endpoint', function () { const ingestManager = getService('ingestManager'); const log = getService('log'); const endpointTestResources = getService('endpointTestResources'); + const kbnClient = getService('kibanaServer'); if (!isRegistryEnabled()) { log.warning('These tests are being run with an external package registry'); @@ -33,6 +35,12 @@ export default function (providerContext: FtrProviderContext) { log.info('installing/upgrading Endpoint fleet package'); await endpointTestResources.installOrUpgradeEndpointFleetPackage(); + + if (await isServerlessKibanaFlavor(kbnClient)) { + log.info('login for serverless environment'); + const pageObjects = getPageObjects(['svlCommonPage']); + await pageObjects.svlCommonPage.login(); + } }); loadTestFile(require.resolve('./policy_list')); loadTestFile(require.resolve('./policy_details')); diff --git a/x-pack/test/security_solution_endpoint/apps/integrations/policy_details.ts b/x-pack/test/security_solution_endpoint/apps/integrations/policy_details.ts index 0093119a21e18..b48c64b5e9dd4 100644 --- a/x-pack/test/security_solution_endpoint/apps/integrations/policy_details.ts +++ b/x-pack/test/security_solution_endpoint/apps/integrations/policy_details.ts @@ -11,6 +11,7 @@ import { PROTECTION_NOTICE_SUPPORTED_ENDPOINT_VERSION } from '@kbn/security-solu import { getPolicySettingsFormTestSubjects } from '@kbn/security-solution-plugin/public/management/pages/policy/view/policy_settings_form/mocks'; import { FtrProviderContext } from '../../ftr_provider_context'; import { PolicyTestResourceInfo } from '../../services/endpoint_policy'; +import { targetTags } from '../../target_tags'; export default function ({ getPageObjects, getService }: FtrProviderContext) { const browser = getService('browser'); @@ -28,6 +29,8 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { const retry = getService('retry'); describe('When on the Endpoint Policy Details Page', function () { + targetTags(this, ['@ess', '@serverless']); + let indexedData: IndexedHostsAndAlertsResponse; const formTestSubjects = getPolicySettingsFormTestSubjects(); @@ -74,12 +77,16 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { ); }); - it('should not hide the side navigation', async () => { - await testSubjects.scrollIntoView('solutionSideNavItemLink-get_started'); - // ensure center of button is visible and not hidden by sticky bottom bar - await testSubjects.click('solutionSideNavItemLink-administration', 1000, 15); - // test cleanup: go back to policy details page - await pageObjects.policy.navigateToPolicyDetails(policyInfo.packagePolicy.id); + describe('side navigation', function () { + targetTags(this, ['@skipInServerless']); + + it('should not hide the side navigation', async function () { + await testSubjects.scrollIntoView('solutionSideNavItemLink-get_started'); + // ensure center of button is visible and not hidden by sticky bottom bar + await testSubjects.click('solutionSideNavItemLink-administration', 1000, 15); + // test cleanup: go back to policy details page + await pageObjects.policy.navigateToPolicyDetails(policyInfo.packagePolicy.id); + }); }); it('Should show/hide advanced section when button is clicked', async () => { @@ -148,10 +155,11 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { it('should show a tooltip on hover', async () => { await testSubjects.moveMouseTo(cardTestSubj.notifyCustomMessageTooltipIcon); - expect( - await testSubjects.getVisibleText(cardTestSubj.notifyCustomMessageTooltipInfo) - ).equal( - `Selecting the user notification option will display a notification to the host user when ${protection} is prevented or detected.\nThe user notification can be customized in the text box below. Bracketed tags can be used to dynamically populate the applicable action (such as prevented or detected) and the filename.` + await retry.waitFor( + 'should show a tooltip on hover', + async () => + (await testSubjects.getVisibleText(cardTestSubj.notifyCustomMessageTooltipInfo)) === + `Selecting the user notification option will display a notification to the host user when ${protection} is prevented or detected.\nThe user notification can be customized in the text box below. Bracketed tags can be used to dynamically populate the applicable action (such as prevented or detected) and the filename.` ); }); @@ -210,7 +218,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { await pageObjects.policy.confirmAndSave(); await testSubjects.existOrFail('policyDetailsSuccessMessage'); - await testSubjects.waitForHidden('toastCloseButton'); + await testSubjects.existOrFail('toastCloseButton'); await pageObjects.endpoint.navigateToEndpointList(); await pageObjects.policy.navigateToPolicyDetails(policyInfo.packagePolicy.id); diff --git a/x-pack/test/security_solution_endpoint/apps/integrations/policy_list.ts b/x-pack/test/security_solution_endpoint/apps/integrations/policy_list.ts index 5d0ee544360d6..37bb6d7cebfc3 100644 --- a/x-pack/test/security_solution_endpoint/apps/integrations/policy_list.ts +++ b/x-pack/test/security_solution_endpoint/apps/integrations/policy_list.ts @@ -9,6 +9,7 @@ import expect from '@kbn/expect'; import { IndexedHostsAndAlertsResponse } from '@kbn/security-solution-plugin/common/endpoint/index_data'; import { FtrProviderContext } from '../../ftr_provider_context'; import { PolicyTestResourceInfo } from '../../services/endpoint_policy'; +import { targetTags } from '../../target_tags'; export default function ({ getPageObjects, getService }: FtrProviderContext) { const browser = getService('browser'); @@ -24,7 +25,9 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { const policyTestResources = getService('policyTestResources'); const endpointTestResources = getService('endpointTestResources'); - describe('When on the Endpoint Policy List Page', () => { + describe('When on the Endpoint Policy List Page', function () { + targetTags(this, ['@ess', '@serverless']); + before(async () => { await browser.refresh(); }); diff --git a/x-pack/test/security_solution_endpoint/apps/integrations/trusted_apps_list.ts b/x-pack/test/security_solution_endpoint/apps/integrations/trusted_apps_list.ts index 12867852edc2d..e00dde08d58fb 100644 --- a/x-pack/test/security_solution_endpoint/apps/integrations/trusted_apps_list.ts +++ b/x-pack/test/security_solution_endpoint/apps/integrations/trusted_apps_list.ts @@ -8,6 +8,7 @@ import expect from '@kbn/expect'; import { IndexedHostsAndAlertsResponse } from '@kbn/security-solution-plugin/common/endpoint/index_data'; import { FtrProviderContext } from '../../ftr_provider_context'; +import { targetTags } from '../../target_tags'; export default ({ getPageObjects, getService }: FtrProviderContext) => { const pageObjects = getPageObjects(['common', 'trustedApps']); @@ -16,6 +17,8 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { const endpointTestResources = getService('endpointTestResources'); describe('When on the Trusted Apps list', function () { + targetTags(this, ['@ess', '@serverless']); + let indexedData: IndexedHostsAndAlertsResponse; before(async () => { indexedData = await endpointTestResources.loadEndpointData(); diff --git a/x-pack/test/security_solution_endpoint/config.base.ts b/x-pack/test/security_solution_endpoint/config.base.ts new file mode 100644 index 0000000000000..4291e16e17a18 --- /dev/null +++ b/x-pack/test/security_solution_endpoint/config.base.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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { Config } from '@kbn/test'; +import { FtrConfigProviderContext } from '@kbn/test'; +import { pageObjects } from './page_objects'; +import { + getRegistryUrlAsArray, + createEndpointDockerConfig, +} from '../security_solution_endpoint_api_int/registry'; +import type { TargetTags } from './target_tags'; + +const SUITE_TAGS: Record = { + ess: { + include: ['@ess'], + exclude: ['@skipInEss'], + }, + serverless: { + include: ['@serverless'], + exclude: ['@skipInServerless', '@brokenInServerless'], + }, +}; + +export const generateConfig = async ({ + ftrConfigProviderContext, + baseConfig, + testFiles, + junitReportName, + kbnServerArgs = [], + target, + services, +}: { + ftrConfigProviderContext: FtrConfigProviderContext; + baseConfig: Config; + testFiles: string[]; + junitReportName: string; + kbnServerArgs?: string[]; + target: keyof typeof SUITE_TAGS; + services: any; +}): Promise => { + const { readConfigFile } = ftrConfigProviderContext; + + const xpackFunctionalConfig = await readConfigFile( + require.resolve('../functional/config.base.js') + ); + + return { + ...baseConfig.getAll(), + pageObjects, + testFiles, + dockerServers: createEndpointDockerConfig(), + junit: { + reportName: junitReportName, + }, + suiteTags: { + ...baseConfig.get('suiteTags'), + include: [...baseConfig.get('suiteTags.include'), ...SUITE_TAGS[target].include], + exclude: [...baseConfig.get('suiteTags.exclude'), ...SUITE_TAGS[target].exclude], + }, + services, + apps: { + ...xpackFunctionalConfig.get('apps'), + ...baseConfig.get('apps'), + + ['securitySolutionManagement']: { + pathname: '/app/security/administration', + }, + ['security']: { + pathname: '/app/security', + }, + ['securitySolutionTimelines']: { + pathname: '/app/security/timelines', + }, + }, + kbnTestServer: { + ...baseConfig.get('kbnTestServer'), + serverArgs: [ + ...baseConfig.get('kbnTestServer.serverArgs'), + // if you return an empty string here the kibana server will not start properly but an empty array works + ...getRegistryUrlAsArray(), + // always install Endpoint package by default when Fleet sets up + `--xpack.fleet.packages.0.name=endpoint`, + `--xpack.fleet.packages.0.version=latest`, + // this will be removed in 8.7 when the file upload feature is released + `--xpack.fleet.enableExperimental.0=diagnosticFileUploadEnabled`, + ...kbnServerArgs, + ], + }, + layout: { + fixedHeaderHeight: 200, + }, + }; +}; diff --git a/x-pack/test/security_solution_endpoint/endpoint.config.ts b/x-pack/test/security_solution_endpoint/endpoint.config.ts index 61ed67b2b123f..ed64b4e955c87 100644 --- a/x-pack/test/security_solution_endpoint/endpoint.config.ts +++ b/x-pack/test/security_solution_endpoint/endpoint.config.ts @@ -5,56 +5,24 @@ * 2.0. */ -import { resolve } from 'path'; import { FtrConfigProviderContext } from '@kbn/test'; -import { pageObjects } from './page_objects'; +import { resolve } from 'path'; +import { generateConfig } from './config.base'; import { services } from './services'; -import { - getRegistryUrlAsArray, - createEndpointDockerConfig, -} from '../security_solution_endpoint_api_int/registry'; -export default async function ({ readConfigFile }: FtrConfigProviderContext) { +export default async function (ftrConfigProviderContext: FtrConfigProviderContext) { + const { readConfigFile } = ftrConfigProviderContext; + const xpackFunctionalConfig = await readConfigFile( require.resolve('../functional/config.base.js') ); - return { - ...xpackFunctionalConfig.getAll(), - pageObjects, + return generateConfig({ + ftrConfigProviderContext, + baseConfig: xpackFunctionalConfig, testFiles: [resolve(__dirname, './apps/endpoint')], - dockerServers: createEndpointDockerConfig(), - junit: { - reportName: 'X-Pack Endpoint Functional Tests', - }, + junitReportName: 'X-Pack Endpoint Functional Tests on ESS', + target: 'ess', services, - apps: { - ...xpackFunctionalConfig.get('apps'), - ['securitySolutionManagement']: { - pathname: '/app/security/administration', - }, - ['security']: { - pathname: '/app/security', - }, - ['securitySolutionTimelines']: { - pathname: '/app/security/timelines', - }, - }, - kbnTestServer: { - ...xpackFunctionalConfig.get('kbnTestServer'), - serverArgs: [ - ...xpackFunctionalConfig.get('kbnTestServer.serverArgs'), - // if you return an empty string here the kibana server will not start properly but an empty array works - ...getRegistryUrlAsArray(), - // always install Endpoint package by default when Fleet sets up - `--xpack.fleet.packages.0.name=endpoint`, - `--xpack.fleet.packages.0.version=latest`, - // this will be removed in 8.7 when the file upload feature is released - `--xpack.fleet.enableExperimental.0=diagnosticFileUploadEnabled`, - ], - }, - layout: { - fixedHeaderHeight: 200, - }, - }; + }); } diff --git a/x-pack/test/security_solution_endpoint/integrations.config.ts b/x-pack/test/security_solution_endpoint/integrations.config.ts index 618d94df0fe6e..a75e329505a4e 100644 --- a/x-pack/test/security_solution_endpoint/integrations.config.ts +++ b/x-pack/test/security_solution_endpoint/integrations.config.ts @@ -7,51 +7,26 @@ import { resolve } from 'path'; import { FtrConfigProviderContext } from '@kbn/test'; -import { pageObjects } from './page_objects'; +import { generateConfig } from './config.base'; import { services } from './services'; -import { - getRegistryUrlAsArray, - createEndpointDockerConfig, -} from '../security_solution_endpoint_api_int/registry'; -export default async function ({ readConfigFile }: FtrConfigProviderContext) { +export default async function (ftrConfigProviderContext: FtrConfigProviderContext) { + const { readConfigFile } = ftrConfigProviderContext; + const xpackFunctionalConfig = await readConfigFile( require.resolve('../functional/config.base.js') ); - return { - ...xpackFunctionalConfig.getAll(), - pageObjects, + return generateConfig({ + ftrConfigProviderContext, + baseConfig: xpackFunctionalConfig, testFiles: [resolve(__dirname, './apps/integrations')], - dockerServers: createEndpointDockerConfig(), - junit: { - reportName: 'X-Pack Endpoint Integrations Functional Tests', - }, + junitReportName: 'X-Pack Endpoint Integrations Functional Tests on ESS', + target: 'ess', + kbnServerArgs: [ + // set the packagerTaskInterval to 5s in order to speed up test executions when checking fleet artifacts + '--xpack.securitySolution.packagerTaskInterval=5s', + ], services, - apps: { - ...xpackFunctionalConfig.get('apps'), - ['securitySolutionManagement']: { - pathname: '/app/security/administration', - }, - ['security']: { - pathname: '/app/security', - }, - }, - kbnTestServer: { - ...xpackFunctionalConfig.get('kbnTestServer'), - serverArgs: [ - ...xpackFunctionalConfig.get('kbnTestServer.serverArgs'), - // if you return an empty string here the kibana server will not start properly but an empty array works - ...getRegistryUrlAsArray(), - // always install Endpoint package by default when Fleet sets up - `--xpack.fleet.packages.0.name=endpoint`, - `--xpack.fleet.packages.0.version=latest`, - // set the packagerTaskInterval to 5s in order to speed up test executions when checking fleet artifacts - '--xpack.securitySolution.packagerTaskInterval=5s', - ], - }, - layout: { - fixedHeaderHeight: 200, - }, - }; + }); } diff --git a/x-pack/test/security_solution_endpoint/page_objects/index.ts b/x-pack/test/security_solution_endpoint/page_objects/index.ts index 1cd57209d78b9..d7fb55608226f 100644 --- a/x-pack/test/security_solution_endpoint/page_objects/index.ts +++ b/x-pack/test/security_solution_endpoint/page_objects/index.ts @@ -17,9 +17,11 @@ import { EndpointPolicyPageProvider } from './policy_page'; import { TrustedAppsPageProvider } from './trusted_apps_page'; import { FleetIntegrations } from './fleet_integrations_page'; import { ArtifactEntriesListPageProvider } from './artifact_entries_list_page'; +import { SvlCommonPageProvider } from './svl_common_page'; export const pageObjects = { ...xpackFunctionalPageObjects, + endpoint: EndpointPageProvider, endpointPageUtils: EndpointPageUtils, ingestManagerCreatePackagePolicy: IngestManagerCreatePackagePolicy, @@ -31,4 +33,6 @@ export const pageObjects = { trustedApps: TrustedAppsPageProvider, artifactEntriesList: ArtifactEntriesListPageProvider, fleetIntegrations: FleetIntegrations, + + svlCommonPage: SvlCommonPageProvider, }; diff --git a/x-pack/test/security_solution_endpoint/page_objects/svl_common_page.ts b/x-pack/test/security_solution_endpoint/page_objects/svl_common_page.ts new file mode 100644 index 0000000000000..98ea6e80984d2 --- /dev/null +++ b/x-pack/test/security_solution_endpoint/page_objects/svl_common_page.ts @@ -0,0 +1,118 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrProviderContext } from '../ftr_provider_context'; + +/** copied from `x-pack/test_serverless/functional/page_objects` in order to be able to login when testing against serverless, + * without importing from a different project + */ +export function SvlCommonPageProvider({ getService, getPageObjects }: FtrProviderContext) { + const testSubjects = getService('testSubjects'); + const config = getService('config'); + const pageObjects = getPageObjects(['security', 'common']); + const retry = getService('retry'); + const deployment = getService('deployment'); + const log = getService('log'); + const browser = getService('browser'); + + const delay = (ms: number) => + new Promise((resolve) => { + setTimeout(resolve, ms); + }); + + return { + async navigateToLoginForm() { + const url = deployment.getHostPort() + '/login'; + await browser.get(url); + // ensure welcome screen won't be shown. This is relevant for environments which don't allow + // to use the yml setting, e.g. cloud + await browser.setLocalStorageItem('home:welcome:show', 'false'); + + log.debug('Waiting for Login Form to appear.'); + await retry.waitForWithTimeout('login form', 10_000, async () => { + return await pageObjects.security.isLoginFormVisible(); + }); + }, + + async login() { + await pageObjects.security.forceLogout({ waitForLoginPage: false }); + + // adding sleep to settle down logout + await pageObjects.common.sleep(2500); + + await retry.waitForWithTimeout( + 'Waiting for successful authentication', + 90_000, + async () => { + if (!(await testSubjects.exists('loginUsername', { timeout: 1000 }))) { + await this.navigateToLoginForm(); + + await testSubjects.setValue('loginUsername', config.get('servers.kibana.username')); + await testSubjects.setValue('loginPassword', config.get('servers.kibana.password')); + await testSubjects.click('loginSubmit'); + } + + if (await testSubjects.exists('userMenuButton', { timeout: 10_000 })) { + log.debug('userMenuButton is found, logged in passed'); + return true; + } else { + throw new Error(`Failed to login to Kibana via UI`); + } + }, + async () => { + // Sometimes authentication fails and user is redirected to Cloud login page + // [plugins.security.authentication] Authentication attempt failed: UNEXPECTED_SESSION_ERROR + const currentUrl = await browser.getCurrentUrl(); + if (currentUrl.startsWith('https://cloud.elastic.co')) { + log.debug( + 'Probably authentication attempt failed, we are at Cloud login page. Retrying from scratch' + ); + } else { + const authError = await testSubjects.exists('promptPage', { timeout: 2500 }); + if (authError) { + log.debug('Probably SAML callback page, doing logout again'); + await pageObjects.security.forceLogout({ waitForLoginPage: false }); + } else { + const isOnLoginPage = await testSubjects.exists('loginUsername', { timeout: 1000 }); + if (isOnLoginPage) { + log.debug( + 'Probably ES user profile activation failed, waiting 2 seconds and pressing Login button again' + ); + await delay(2000); + await testSubjects.click('loginSubmit'); + } else { + log.debug('New behaviour, trying to navigate and login again'); + } + } + } + } + ); + log.debug('Logged in successfully'); + }, + + async forceLogout() { + await pageObjects.security.forceLogout({ waitForLoginPage: false }); + log.debug('Logged out successfully'); + }, + + async assertProjectHeaderExists() { + await testSubjects.existOrFail('kibanaProjectHeader'); + }, + + async clickUserAvatar() { + testSubjects.click('userMenuAvatar'); + }, + + async assertUserAvatarExists() { + await testSubjects.existOrFail('userMenuAvatar'); + }, + + async assertUserMenuExists() { + await testSubjects.existOrFail('userMenu'); + }, + }; +} diff --git a/x-pack/test/security_solution_endpoint/serverless.endpoint.config.ts b/x-pack/test/security_solution_endpoint/serverless.endpoint.config.ts new file mode 100644 index 0000000000000..76ce4a0d38a4b --- /dev/null +++ b/x-pack/test/security_solution_endpoint/serverless.endpoint.config.ts @@ -0,0 +1,29 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrConfigProviderContext } from '@kbn/test'; +import { resolve } from 'path'; +import { generateConfig } from './config.base'; +import { svlServices } from './services'; + +export default async function (ftrConfigProviderContext: FtrConfigProviderContext) { + const { readConfigFile } = ftrConfigProviderContext; + + const svlBaseConfig = await readConfigFile( + require.resolve('../../test_serverless/shared/config.base.ts') + ); + + return generateConfig({ + ftrConfigProviderContext, + baseConfig: svlBaseConfig, + testFiles: [resolve(__dirname, './apps/endpoint')], + junitReportName: 'X-Pack Endpoint Functional Tests on Serverless', + kbnServerArgs: ['--serverless=security'], + target: 'serverless', + services: svlServices, + }); +} diff --git a/x-pack/test/security_solution_endpoint/serverless.integrations.config.ts b/x-pack/test/security_solution_endpoint/serverless.integrations.config.ts new file mode 100644 index 0000000000000..52a5f523856a6 --- /dev/null +++ b/x-pack/test/security_solution_endpoint/serverless.integrations.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 { resolve } from 'path'; +import { FtrConfigProviderContext } from '@kbn/test'; +import { generateConfig } from './config.base'; +import { svlServices } from './services'; + +export default async function (ftrConfigProviderContext: FtrConfigProviderContext) { + const { readConfigFile } = ftrConfigProviderContext; + + const svlBaseConfig = await readConfigFile( + require.resolve('../../test_serverless/shared/config.base.ts') + ); + + return generateConfig({ + ftrConfigProviderContext, + baseConfig: svlBaseConfig, + testFiles: [resolve(__dirname, './apps/integrations')], + junitReportName: 'X-Pack Endpoint Integrations Functional Tests on Serverless', + target: 'serverless', + kbnServerArgs: [ + '--serverless=security', + // set the packagerTaskInterval to 5s in order to speed up test executions when checking fleet artifacts + '--xpack.securitySolution.packagerTaskInterval=5s', + ], + services: svlServices, + }); +} diff --git a/x-pack/test/security_solution_endpoint/services/index.ts b/x-pack/test/security_solution_endpoint/services/index.ts index 41f5eb0add0b3..b2c52ada028b0 100644 --- a/x-pack/test/security_solution_endpoint/services/index.ts +++ b/x-pack/test/security_solution_endpoint/services/index.ts @@ -13,9 +13,11 @@ import { TimelineTestService } from '../../security_solution_ftr/services/timeli import { DetectionsTestService } from '../../security_solution_ftr/services/detections'; import { EndpointPolicyTestResourcesProvider } from './endpoint_policy'; import { EndpointArtifactsTestResources } from './endpoint_artifacts'; +import { KibanaSupertestWithCertProvider } from './supertest_with_cert'; export const services = { ...xPackFunctionalServices, + endpointTestResources: EndpointTestResources, telemetryTestResources: EndpointTelemetryTestResourcesProvider, ingestManager: IngestManagerProvider, @@ -24,3 +26,9 @@ export const services = { endpointArtifactTestResources: EndpointArtifactsTestResources, policyTestResources: EndpointPolicyTestResourcesProvider, }; + +export const svlServices = { + ...services, + + supertest: KibanaSupertestWithCertProvider, +}; diff --git a/x-pack/test/security_solution_endpoint/services/supertest_with_cert.ts b/x-pack/test/security_solution_endpoint/services/supertest_with_cert.ts new file mode 100644 index 0000000000000..e06e144a1667f --- /dev/null +++ b/x-pack/test/security_solution_endpoint/services/supertest_with_cert.ts @@ -0,0 +1,17 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import { format as formatUrl } from 'url'; +import supertest from 'supertest'; +import { FtrProviderContext } from '../ftr_provider_context'; + +export function KibanaSupertestWithCertProvider({ getService }: FtrProviderContext) { + const config = getService('config'); + const kibanaServerUrl = formatUrl(config.get('servers.kibana')); + const ca = config.get('servers.kibana').certificateAuthorities; + + return supertest.agent(kibanaServerUrl, { ca }); +} diff --git a/x-pack/test/security_solution_endpoint/target_tags.ts b/x-pack/test/security_solution_endpoint/target_tags.ts new file mode 100644 index 0000000000000..dd71736e95ee5 --- /dev/null +++ b/x-pack/test/security_solution_endpoint/target_tags.ts @@ -0,0 +1,17 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export type TargetTags = + | '@ess' + | '@skipInEss' + | '@serverless' + | '@skipInServerless' + | '@brokenInServerless'; + +export const targetTags = (thisSuite: Mocha.Suite, tags: TargetTags[]) => { + thisSuite.tags(tags); +}; diff --git a/x-pack/test/security_solution_endpoint_api_int/apis/metadata.ts b/x-pack/test/security_solution_endpoint_api_int/apis/metadata.ts index 48109e13257ca..17cc5906d7ba8 100644 --- a/x-pack/test/security_solution_endpoint_api_int/apis/metadata.ts +++ b/x-pack/test/security_solution_endpoint_api_int/apis/metadata.ts @@ -46,7 +46,8 @@ export default function ({ getService }: FtrProviderContext) { const endpointTestResources = getService('endpointTestResources'); const log = getService('log'); - describe('test metadata apis', () => { + // Failing: See https://github.com/elastic/kibana/issues/151854 + describe.skip('test metadata apis', () => { describe('list endpoints GET route', () => { const numberOfHostsInFixture = 2; let agent1Timestamp: number; diff --git a/x-pack/test/stack_functional_integration/apps/filebeat/filebeat.ts b/x-pack/test/stack_functional_integration/apps/filebeat/filebeat.ts index 5539125d770a8..f7e13aa998add 100644 --- a/x-pack/test/stack_functional_integration/apps/filebeat/filebeat.ts +++ b/x-pack/test/stack_functional_integration/apps/filebeat/filebeat.ts @@ -11,12 +11,15 @@ import { FtrProviderContext } from '../../../functional/ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { describe('check filebeat', function () { const retry = getService('retry'); + const kibanaServer = getService('kibanaServer'); const PageObjects = getPageObjects(['common', 'discover', 'timePicker']); it('filebeat- should have hit count GT 0', async function () { + await kibanaServer.uiSettings.update({ + 'timepicker:timeDefaults': `{ "from": "now-5y", "to": "now"}`, + }); await PageObjects.common.navigateToApp('discover', { insertTimestamp: false }); await PageObjects.discover.selectIndexPattern('filebeat-*'); - await PageObjects.timePicker.setCommonlyUsedTime('Last_1 year'); await retry.try(async () => { const hitCount = await PageObjects.discover.getHitCountInt(); expect(hitCount).to.be.greaterThan(0); diff --git a/x-pack/test/stack_functional_integration/apps/metricbeat/_metricbeat.ts b/x-pack/test/stack_functional_integration/apps/metricbeat/_metricbeat.ts index 50b254a65559e..03ae2c4d8e809 100644 --- a/x-pack/test/stack_functional_integration/apps/metricbeat/_metricbeat.ts +++ b/x-pack/test/stack_functional_integration/apps/metricbeat/_metricbeat.ts @@ -12,12 +12,16 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const log = getService('log'); const retry = getService('retry'); const browser = getService('browser'); + const kibanaServer = getService('kibanaServer'); const PageObjects = getPageObjects(['common', 'discover', 'timePicker']); const appsMenu = getService('appsMenu'); describe('check metricbeat', function () { it('metricbeat- should have hit count GT 0', async function () { const url = await browser.getCurrentUrl(); + await kibanaServer.uiSettings.update({ + 'timepicker:timeDefaults': `{ "from": "now-5y", "to": "now"}`, + }); log.debug(url); if (!url.includes('kibana')) { await PageObjects.common.navigateToApp('discover', { insertTimestamp: false }); @@ -26,7 +30,6 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { } await PageObjects.discover.selectIndexPattern('metricbeat-*'); - await PageObjects.timePicker.setCommonlyUsedTime('Last_1 year'); await retry.try(async function () { const hitCount = await PageObjects.discover.getHitCountInt(); expect(hitCount).to.be.greaterThan(0); diff --git a/x-pack/test/stack_functional_integration/apps/packetbeat/_packetbeat.ts b/x-pack/test/stack_functional_integration/apps/packetbeat/_packetbeat.ts index 367f7a34f7003..f34d38280280d 100644 --- a/x-pack/test/stack_functional_integration/apps/packetbeat/_packetbeat.ts +++ b/x-pack/test/stack_functional_integration/apps/packetbeat/_packetbeat.ts @@ -12,6 +12,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const log = getService('log'); const retry = getService('retry'); const browser = getService('browser'); + const kibanaServer = getService('kibanaServer'); const PageObjects = getPageObjects(['common', 'discover', 'timePicker']); const appsMenu = getService('appsMenu'); @@ -22,6 +23,9 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { it('packetbeat- should have hit count GT 0', async function () { const url = await browser.getCurrentUrl(); + await kibanaServer.uiSettings.update({ + 'timepicker:timeDefaults': `{ "from": "now-5y", "to": "now"}`, + }); log.debug(url); if (!url.includes('kibana')) { await PageObjects.common.navigateToApp('discover', { insertTimestamp: false }); @@ -30,7 +34,6 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await appsMenu.clickLink('Discover'); } await PageObjects.discover.selectIndexPattern('packetbeat-*'); - await PageObjects.timePicker.setCommonlyUsedTime('Last_1 year'); await retry.try(async function () { const hitCount = await PageObjects.discover.getHitCountInt(); expect(hitCount).to.be.greaterThan(0); diff --git a/x-pack/test/tsconfig.json b/x-pack/test/tsconfig.json index 7d29b3794ac8a..8c7a2758f8e29 100644 --- a/x-pack/test/tsconfig.json +++ b/x-pack/test/tsconfig.json @@ -146,5 +146,6 @@ "@kbn/ecs", "@kbn/coloring", "@kbn/es", + "@kbn/metrics-data-access-plugin", ] } diff --git a/x-pack/test_serverless/api_integration/services/alerting_api.ts b/x-pack/test_serverless/api_integration/services/alerting_api.ts index 668dcdab82aa0..6f47757a6e30b 100644 --- a/x-pack/test_serverless/api_integration/services/alerting_api.ts +++ b/x-pack/test_serverless/api_integration/services/alerting_api.ts @@ -12,7 +12,7 @@ import type { import { MetricThresholdParams } from '@kbn/infra-plugin/common/alerting/metrics'; import { ThresholdParams } from '@kbn/observability-plugin/common/custom_threshold_rule/types'; - +import { SloBurnRateRuleParams } from './slo_api'; import { FtrProviderContext } from '../ftr_provider_context'; export function AlertingApiProvider({ getService }: FtrProviderContext) { @@ -117,7 +117,7 @@ export function AlertingApiProvider({ getService }: FtrProviderContext) { }: { ruleTypeId: string; name: string; - params: MetricThresholdParams | ThresholdParams; + params: MetricThresholdParams | ThresholdParams | SloBurnRateRuleParams; actions?: any[]; tags?: any[]; schedule?: { interval: string }; @@ -140,5 +140,16 @@ export function AlertingApiProvider({ getService }: FtrProviderContext) { }); return body; }, + + async findRule(ruleId: string) { + if (!ruleId) { + throw new Error(`'ruleId' is undefined`); + } + const response = await supertest + .get('/api/alerting/rules/_find') + .set('kbn-xsrf', 'foo') + .set('x-elastic-internal-origin', 'foo'); + return response.body.data.find((obj: any) => obj.id === ruleId); + }, }; } diff --git a/x-pack/test_serverless/api_integration/services/index.ts b/x-pack/test_serverless/api_integration/services/index.ts index dd59c42545c03..00be2fa67fbd7 100644 --- a/x-pack/test_serverless/api_integration/services/index.ts +++ b/x-pack/test_serverless/api_integration/services/index.ts @@ -13,6 +13,7 @@ import { AlertingApiProvider } from './alerting_api'; import { SamlToolsProvider } from './saml_tools'; import { DataViewApiProvider } from './data_view_api'; import { SvlCasesServiceProvider } from './svl_cases'; +import { SloApiProvider } from './slo_api'; export const services = { // deployment agnostic FTR services @@ -24,6 +25,7 @@ export const services = { samlTools: SamlToolsProvider, dataViewApi: DataViewApiProvider, svlCases: SvlCasesServiceProvider, + sloApi: SloApiProvider, }; export type InheritedFtrProviderContext = GenericFtrProviderContext; diff --git a/x-pack/test_serverless/api_integration/services/slo_api.ts b/x-pack/test_serverless/api_integration/services/slo_api.ts new file mode 100644 index 0000000000000..da3ec1710a56b --- /dev/null +++ b/x-pack/test_serverless/api_integration/services/slo_api.ts @@ -0,0 +1,89 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrProviderContext } from '../ftr_provider_context'; + +type DurationUnit = 'm' | 'h' | 'd' | 'w' | 'M'; + +interface Duration { + value: number; + unit: DurationUnit; +} + +interface WindowSchema { + id: string; + burnRateThreshold: number; + maxBurnRateThreshold: number; + longWindow: Duration; + shortWindow: Duration; + actionGroup: string; +} + +export interface SloBurnRateRuleParams { + sloId: string; + windows: WindowSchema[]; +} + +interface SloParams { + id: string; + name: string; + description: string; + indicator: { + type: 'sli.kql.custom'; + params: { + index: string; + good: string; + total: string; + timestampField: string; + }; + }; + timeWindow: { + duration: string; + type: string; + }; + budgetingMethod: string; + objective: { + target: number; + }; + groupBy: string; +} + +export function SloApiProvider({ getService }: FtrProviderContext) { + const supertest = getService('supertest'); + const retry = getService('retry'); + const requestTimeout = 30 * 1000; + const retryTimeout = 120 * 1000; + + return { + async create(slo: SloParams) { + const { body } = await supertest + .post(`/api/observability/slos`) + .set('kbn-xsrf', 'foo') + .set('x-elastic-internal-origin', 'foo') + .send(slo); + + return body; + }, + + async delete() {}, + + async waitForSloCreated({ sloId }: { sloId: string }) { + if (!sloId) { + throw new Error(`'sloId is undefined`); + } + return await retry.tryForTime(retryTimeout, async () => { + const response = await supertest + .get(`/api/observability/slos/${sloId}`) + .set('kbn-xsrf', 'foo') + .set('x-elastic-internal-origin', 'foo') + .timeout(requestTimeout); + + return response.body; + }); + }, + }; +} diff --git a/x-pack/test_serverless/api_integration/test_suites/common/alerting/alert_documents.ts b/x-pack/test_serverless/api_integration/test_suites/common/alerting/alert_documents.ts index 4069f4d63d9eb..feddf08dc39b1 100644 --- a/x-pack/test_serverless/api_integration/test_suites/common/alerting/alert_documents.ts +++ b/x-pack/test_serverless/api_integration/test_suites/common/alerting/alert_documents.ts @@ -164,7 +164,7 @@ export default function ({ getService }: FtrProviderContext) { groupBy: 'all', searchType: 'esQuery', }, - [ALERT_RULE_PRODUCER]: 'stackAlerts', + [ALERT_RULE_PRODUCER]: hits1[ALERT_RULE_PRODUCER], [ALERT_RULE_REVISION]: 0, [ALERT_RULE_TYPE_ID]: '.es-query', [ALERT_RULE_TAGS]: [], diff --git a/x-pack/test_serverless/api_integration/test_suites/common/alerting/helpers/alerting_api_helper.ts b/x-pack/test_serverless/api_integration/test_suites/common/alerting/helpers/alerting_api_helper.ts index d20eda10fbf68..171ac839da4bc 100644 --- a/x-pack/test_serverless/api_integration/test_suites/common/alerting/helpers/alerting_api_helper.ts +++ b/x-pack/test_serverless/api_integration/test_suites/common/alerting/helpers/alerting_api_helper.ts @@ -437,3 +437,20 @@ export async function snoozeRule({ .expect(204); return body; } + +export async function findRule({ + supertest, + ruleId, +}: { + supertest: SuperTest; + ruleId: string; +}) { + if (!ruleId) { + throw new Error(`'ruleId' is undefined`); + } + const response = await supertest + .get(`/api/alerting/rule/${ruleId}`) + .set('kbn-xsrf', 'foo') + .set('x-elastic-internal-origin', 'foo'); + return response.body || {}; +} diff --git a/x-pack/test_serverless/api_integration/test_suites/common/alerting/helpers/alerting_wait_for_helpers.ts b/x-pack/test_serverless/api_integration/test_suites/common/alerting/helpers/alerting_wait_for_helpers.ts index e69e5303e1d8f..00b746697cd23 100644 --- a/x-pack/test_serverless/api_integration/test_suites/common/alerting/helpers/alerting_wait_for_helpers.ts +++ b/x-pack/test_serverless/api_integration/test_suites/common/alerting/helpers/alerting_wait_for_helpers.ts @@ -17,15 +17,35 @@ import { runRule } from './alerting_api_helper'; export async function waitForDocumentInIndex({ esClient, indexName, + ruleId, num = 1, + sort = 'desc', }: { esClient: Client; indexName: string; + ruleId: string; num?: number; + sort?: 'asc' | 'desc'; }): Promise { return await pRetry( async () => { - const response = await esClient.search({ index: indexName, sort: 'date:desc' }); + const response = await esClient.search({ + index: indexName, + sort: `date:${sort}`, + body: { + query: { + bool: { + must: [ + { + term: { + 'ruleId.keyword': ruleId, + }, + }, + ], + }, + }, + }, + }); if (response.hits.hits.length < num) { throw new Error(`Only found ${response.hits.hits.length} / ${num} documents`); } @@ -38,11 +58,28 @@ export async function waitForDocumentInIndex({ export async function getDocumentsInIndex({ esClient, indexName, + ruleId, }: { esClient: Client; indexName: string; + ruleId: string; }): Promise { - return await esClient.search({ index: indexName }); + return await esClient.search({ + index: indexName, + body: { + query: { + bool: { + must: [ + { + term: { + 'ruleId.keyword': ruleId, + }, + }, + ], + }, + }, + }, + }); } export async function createIndex({ diff --git a/x-pack/test_serverless/api_integration/test_suites/common/alerting/rules.ts b/x-pack/test_serverless/api_integration/test_suites/common/alerting/rules.ts index 9efc2025210c5..b0813a55325f1 100644 --- a/x-pack/test_serverless/api_integration/test_suites/common/alerting/rules.ts +++ b/x-pack/test_serverless/api_integration/test_suites/common/alerting/rules.ts @@ -41,12 +41,12 @@ export default function ({ getService }: FtrProviderContext) { this.tags(['failsOnMKI']); const RULE_TYPE_ID = '.es-query'; const ALERT_ACTION_INDEX = 'alert-action-es-query'; - let actionId: string; + let connectorId: string; let ruleId: string; afterEach(async () => { await supertest - .delete(`/api/actions/connector/${actionId}`) + .delete(`/api/actions/connector/${connectorId}`) .set('kbn-xsrf', 'foo') .set('x-elastic-internal-origin', 'foo'); await supertest @@ -64,12 +64,12 @@ export default function ({ getService }: FtrProviderContext) { it('should schedule task, run rule and schedule actions when appropriate', async () => { const testStart = new Date(); - const createdAction = await createIndexConnector({ + const createdConnector = await createIndexConnector({ supertest, name: 'Index Connector: Alerting API test', indexName: ALERT_ACTION_INDEX, }); - actionId = createdAction.id; + connectorId = createdConnector.id; const createdRule = await createEsQueryRule({ supertest, @@ -89,7 +89,7 @@ export default function ({ getService }: FtrProviderContext) { actions: [ { group: 'query matched', - id: actionId, + id: connectorId, params: { documents: [ { @@ -120,6 +120,7 @@ export default function ({ getService }: FtrProviderContext) { const resp = await waitForDocumentInIndex({ esClient, indexName: ALERT_ACTION_INDEX, + ruleId, }); expect(resp.hits.hits.length).to.be(1); @@ -157,12 +158,12 @@ export default function ({ getService }: FtrProviderContext) { it('should pass updated rule params to executor', async () => { const testStart = new Date(); - const createdAction = await createIndexConnector({ + const createdConnector = await createIndexConnector({ supertest, name: 'Index Connector: Alerting API test', indexName: ALERT_ACTION_INDEX, }); - actionId = createdAction.id; + connectorId = createdConnector.id; const createdRule = await createEsQueryRule({ supertest, @@ -182,7 +183,7 @@ export default function ({ getService }: FtrProviderContext) { actions: [ { group: 'query matched', - id: actionId, + id: connectorId, params: { documents: [ { @@ -213,6 +214,7 @@ export default function ({ getService }: FtrProviderContext) { const resp = await waitForDocumentInIndex({ esClient, indexName: ALERT_ACTION_INDEX, + ruleId, }); expect(resp.hits.hits.length).to.be(1); @@ -253,6 +255,7 @@ export default function ({ getService }: FtrProviderContext) { const resp2 = await waitForDocumentInIndex({ esClient, indexName: ALERT_ACTION_INDEX, + ruleId, num: 2, }); expect(resp2.hits.hits.length).to.be(2); @@ -276,11 +279,11 @@ export default function ({ getService }: FtrProviderContext) { const testStart = new Date(); // Should fail - const createdAction = await createSlackConnector({ + const createdConnector = await createSlackConnector({ supertest, name: 'Slack Connector: Alerting API test', }); - actionId = createdAction.id; + connectorId = createdConnector.id; const createdRule = await createEsQueryRule({ supertest, @@ -300,7 +303,7 @@ export default function ({ getService }: FtrProviderContext) { actions: [ { group: 'query matched', - id: actionId, + id: connectorId, params: { message: `message: {{rule.id}}`, }, @@ -327,12 +330,12 @@ export default function ({ getService }: FtrProviderContext) { it('should throttle alerts when appropriate', async () => { const testStart = new Date(); - const createdAction = await createIndexConnector({ + const createdConnector = await createIndexConnector({ supertest, name: 'Index Connector: Alerting API test', indexName: ALERT_ACTION_INDEX, }); - actionId = createdAction.id; + connectorId = createdConnector.id; const createdRule = await createEsQueryRule({ supertest, @@ -354,7 +357,7 @@ export default function ({ getService }: FtrProviderContext) { actions: [ { group: 'query matched', - id: actionId, + id: connectorId, params: { documents: [ { @@ -394,6 +397,7 @@ export default function ({ getService }: FtrProviderContext) { const resp = await waitForDocumentInIndex({ esClient, indexName: ALERT_ACTION_INDEX, + ruleId, }); expect(resp.hits.hits.length).to.be(1); }); @@ -401,12 +405,12 @@ export default function ({ getService }: FtrProviderContext) { it('should throttle alerts with throttled action when appropriate', async () => { const testStart = new Date(); - const createdAction = await createIndexConnector({ + const createdConnector = await createIndexConnector({ supertest, name: 'Index Connector: Alerting API test', indexName: ALERT_ACTION_INDEX, }); - actionId = createdAction.id; + connectorId = createdConnector.id; const createdRule = await createEsQueryRule({ supertest, @@ -427,7 +431,7 @@ export default function ({ getService }: FtrProviderContext) { actions: [ { group: 'query matched', - id: actionId, + id: connectorId, params: { documents: [ { @@ -472,6 +476,7 @@ export default function ({ getService }: FtrProviderContext) { const resp = await waitForDocumentInIndex({ esClient, indexName: ALERT_ACTION_INDEX, + ruleId, }); expect(resp.hits.hits.length).to.be(1); }); @@ -479,12 +484,12 @@ export default function ({ getService }: FtrProviderContext) { it('should reset throttle window when not firing and should not throttle when changing groups', async () => { const testStart = new Date(); - const createdAction = await createIndexConnector({ + const createdConnector = await createIndexConnector({ supertest, name: 'Index Connector: Alerting API test', indexName: ALERT_ACTION_INDEX, }); - actionId = createdAction.id; + connectorId = createdConnector.id; const createdRule = await createEsQueryRule({ supertest, @@ -505,7 +510,7 @@ export default function ({ getService }: FtrProviderContext) { actions: [ { group: 'query matched', - id: actionId, + id: connectorId, params: { documents: [ { @@ -530,7 +535,7 @@ export default function ({ getService }: FtrProviderContext) { }, { group: 'recovered', - id: actionId, + id: connectorId, params: { documents: [ { @@ -561,6 +566,7 @@ export default function ({ getService }: FtrProviderContext) { const resp = await waitForDocumentInIndex({ esClient, indexName: ALERT_ACTION_INDEX, + ruleId, }); expect(resp.hits.hits.length).to.be(1); @@ -616,6 +622,7 @@ export default function ({ getService }: FtrProviderContext) { const resp2 = await waitForDocumentInIndex({ esClient, indexName: ALERT_ACTION_INDEX, + ruleId, num: 2, }); expect(resp2.hits.hits.length).to.be(2); @@ -625,12 +632,12 @@ export default function ({ getService }: FtrProviderContext) { const testStart = new Date(); await createIndex({ esClient, indexName: ALERT_ACTION_INDEX }); - const createdAction = await createIndexConnector({ + const createdConnector = await createIndexConnector({ supertest, name: 'Index Connector: Alerting API test', indexName: ALERT_ACTION_INDEX, }); - actionId = createdAction.id; + connectorId = createdConnector.id; const createdRule = await createEsQueryRule({ supertest, @@ -651,7 +658,7 @@ export default function ({ getService }: FtrProviderContext) { actions: [ { group: 'query matched', - id: actionId, + id: connectorId, params: { documents: [ { @@ -707,6 +714,7 @@ export default function ({ getService }: FtrProviderContext) { const resp2 = await getDocumentsInIndex({ esClient, indexName: ALERT_ACTION_INDEX, + ruleId, }); expect(resp2.hits.hits.length).to.be(0); }); @@ -715,12 +723,12 @@ export default function ({ getService }: FtrProviderContext) { const testStart = new Date(); await createIndex({ esClient, indexName: ALERT_ACTION_INDEX }); - const createdAction = await createIndexConnector({ + const createdConnector = await createIndexConnector({ supertest, name: 'Index Connector: Alerting API test', indexName: ALERT_ACTION_INDEX, }); - actionId = createdAction.id; + connectorId = createdConnector.id; const createdRule = await createEsQueryRule({ supertest, @@ -741,7 +749,7 @@ export default function ({ getService }: FtrProviderContext) { actions: [ { group: 'query matched', - id: actionId, + id: connectorId, params: { documents: [ { @@ -798,17 +806,18 @@ export default function ({ getService }: FtrProviderContext) { const resp2 = await getDocumentsInIndex({ esClient, indexName: ALERT_ACTION_INDEX, + ruleId, }); expect(resp2.hits.hits.length).to.be(0); }); it(`should unmute all instances when unmuting an alert`, async () => { - const createdAction = await createIndexConnector({ + const createdConnector = await createIndexConnector({ supertest, name: 'Index Connector: Alerting API test', indexName: ALERT_ACTION_INDEX, }); - actionId = createdAction.id; + connectorId = createdConnector.id; const createdRule = await createEsQueryRule({ supertest, @@ -829,7 +838,7 @@ export default function ({ getService }: FtrProviderContext) { actions: [ { group: 'query matched', - id: actionId, + id: connectorId, params: { documents: [ { @@ -881,6 +890,7 @@ export default function ({ getService }: FtrProviderContext) { const resp = await waitForDocumentInIndex({ esClient, indexName: ALERT_ACTION_INDEX, + ruleId, }); expect(resp.hits.hits.length).to.be(1); }); @@ -962,7 +972,7 @@ function validateEventLog(event: any, params: ValidateEventLogParams) { id: params.ruleId, license: 'basic', category: params.ruleTypeId, - ruleset: 'stackAlerts', + ruleset: event?.rule.ruleset, name: params.name, }); diff --git a/x-pack/test_serverless/api_integration/test_suites/common/alerting/summary_actions.ts b/x-pack/test_serverless/api_integration/test_suites/common/alerting/summary_actions.ts index 1885c951b81f1..9b130040e2340 100644 --- a/x-pack/test_serverless/api_integration/test_suites/common/alerting/summary_actions.ts +++ b/x-pack/test_serverless/api_integration/test_suites/common/alerting/summary_actions.ts @@ -41,13 +41,10 @@ export default function ({ getService }: FtrProviderContext) { const esDeleteAllIndices = getService('esDeleteAllIndices'); describe('Summary actions', function () { - // flaky on MKI, see https://github.com/elastic/kibana/issues/169204 - this.tags(['failsOnMKI']); - const RULE_TYPE_ID = '.es-query'; const ALERT_ACTION_INDEX = 'alert-action-es-query'; const ALERT_INDEX = '.alerts-stack.alerts-default'; - let actionId: string; + let connectorId: string; let ruleId: string; const fields = [ '@timestamp', @@ -67,7 +64,7 @@ export default function ({ getService }: FtrProviderContext) { afterEach(async () => { await supertest - .delete(`/api/actions/connector/${actionId}`) + .delete(`/api/actions/connector/${connectorId}`) .set('kbn-xsrf', 'foo') .set('x-elastic-internal-origin', 'foo') .expect(204); @@ -81,12 +78,12 @@ export default function ({ getService }: FtrProviderContext) { it('should schedule actions for summary of alerts per rule run', async () => { const testStart = new Date(); - const createdAction = await createIndexConnector({ + const createdConnector = await createIndexConnector({ supertest, name: 'Index Connector: Alerting API test', indexName: ALERT_ACTION_INDEX, }); - actionId = createdAction.id; + connectorId = createdConnector.id; const createdRule = await createEsQueryRule({ supertest, @@ -106,7 +103,7 @@ export default function ({ getService }: FtrProviderContext) { actions: [ { group: 'query matched', - id: actionId, + id: connectorId, params: { documents: [ { @@ -120,6 +117,7 @@ export default function ({ getService }: FtrProviderContext) { recoveredIds: '[{{#alerts.recovered.data}}{{kibana.alert.instance.id}},{{/alerts.recovered.data}}]', date: '{{date}}', + ruleId: '{{rule.id}}', }, ], }, @@ -139,6 +137,7 @@ export default function ({ getService }: FtrProviderContext) { const resp = await waitForDocumentInIndex({ esClient, indexName: ALERT_ACTION_INDEX, + ruleId, }); expect(resp.hits.hits.length).to.be(1); @@ -160,6 +159,7 @@ export default function ({ getService }: FtrProviderContext) { ongoingIds: '[]', recovered: '0', recoveredIds: '[]', + ruleId, }); const alertDocument = resp2.hits.hits[0]._source as Record; @@ -190,7 +190,7 @@ export default function ({ getService }: FtrProviderContext) { groupBy: 'all', searchType: 'esQuery', }, - [ALERT_RULE_PRODUCER]: 'stackAlerts', + [ALERT_RULE_PRODUCER]: alertDocument[ALERT_RULE_PRODUCER], [ALERT_RULE_REVISION]: 0, [ALERT_RULE_TYPE_ID]: '.es-query', [ALERT_RULE_TAGS]: [], @@ -202,12 +202,12 @@ export default function ({ getService }: FtrProviderContext) { it('should filter alerts by kql', async () => { const testStart = new Date(); - const createdAction = await createIndexConnector({ + const createdConnector = await createIndexConnector({ supertest, name: 'Index Connector: Alerting API test', indexName: ALERT_ACTION_INDEX, }); - actionId = createdAction.id; + connectorId = createdConnector.id; const createdRule = await createEsQueryRule({ supertest, @@ -227,7 +227,7 @@ export default function ({ getService }: FtrProviderContext) { actions: [ { group: 'query matched', - id: actionId, + id: connectorId, params: { documents: [ { @@ -241,6 +241,7 @@ export default function ({ getService }: FtrProviderContext) { recoveredIds: '[{{#alerts.recovered.data}}{{kibana.alert.instance.id}},{{/alerts.recovered.data}}]', date: '{{date}}', + ruleId: '{{rule.id}}', }, ], }, @@ -260,6 +261,7 @@ export default function ({ getService }: FtrProviderContext) { const resp = await waitForDocumentInIndex({ esClient, indexName: ALERT_ACTION_INDEX, + ruleId, }); expect(resp.hits.hits.length).to.be(1); @@ -281,6 +283,7 @@ export default function ({ getService }: FtrProviderContext) { ongoingIds: '[]', recovered: '0', recoveredIds: '[]', + ruleId, }); const alertDocument = resp2.hits.hits[0]._source as Record; @@ -311,7 +314,7 @@ export default function ({ getService }: FtrProviderContext) { groupBy: 'all', searchType: 'esQuery', }, - [ALERT_RULE_PRODUCER]: 'stackAlerts', + [ALERT_RULE_PRODUCER]: alertDocument[ALERT_RULE_PRODUCER], [ALERT_RULE_REVISION]: 0, [ALERT_RULE_TYPE_ID]: '.es-query', [ALERT_RULE_TAGS]: [], @@ -332,12 +335,12 @@ export default function ({ getService }: FtrProviderContext) { await createIndex({ esClient, indexName: ALERT_ACTION_INDEX }); - const createdAction = await createIndexConnector({ + const createdConnector = await createIndexConnector({ supertest, name: 'Index Connector: Alerting API test', indexName: ALERT_ACTION_INDEX, }); - actionId = createdAction.id; + connectorId = createdConnector.id; const createdRule = await createEsQueryRule({ supertest, @@ -358,7 +361,7 @@ export default function ({ getService }: FtrProviderContext) { actions: [ { group: 'query matched', - id: actionId, + id: connectorId, params: { documents: [ { @@ -372,6 +375,7 @@ export default function ({ getService }: FtrProviderContext) { recoveredIds: '[{{#alerts.recovered.data}}{{kibana.alert.instance.id}},{{/alerts.recovered.data}}]', date: '{{date}}', + ruleId: '{{rule.id}}', }, ], }, @@ -396,18 +400,19 @@ export default function ({ getService }: FtrProviderContext) { const resp = await getDocumentsInIndex({ esClient, indexName: ALERT_ACTION_INDEX, + ruleId, }); expect(resp.hits.hits.length).to.be(0); }); it('should schedule actions for summary of alerts on a custom interval', async () => { const testStart = new Date(); - const createdAction = await createIndexConnector({ + const createdConnector = await createIndexConnector({ supertest, name: 'Index Connector: Alerting API test', indexName: ALERT_ACTION_INDEX, }); - actionId = createdAction.id; + connectorId = createdConnector.id; const createdRule = await createEsQueryRule({ supertest, @@ -428,7 +433,7 @@ export default function ({ getService }: FtrProviderContext) { actions: [ { group: 'query matched', - id: actionId, + id: connectorId, params: { documents: [ { @@ -442,6 +447,7 @@ export default function ({ getService }: FtrProviderContext) { recoveredIds: '[{{#alerts.recovered.data}}{{kibana.alert.instance.id}},{{/alerts.recovered.data}}]', date: '{{date}}', + ruleId: '{{rule.id}}', }, ], }, @@ -458,7 +464,9 @@ export default function ({ getService }: FtrProviderContext) { const resp = await waitForDocumentInIndex({ esClient, indexName: ALERT_ACTION_INDEX, + ruleId, num: 2, + sort: 'asc', }); const resp2 = await waitForAlertInIndex({ @@ -470,7 +478,7 @@ export default function ({ getService }: FtrProviderContext) { }); expect(resp2.hits.hits.length).to.be(1); - const document = resp.hits.hits[1]; + const document = resp.hits.hits[0]; expect(omit(document, '_source.date')._source).to.eql({ all: '1', new: '1', @@ -479,9 +487,10 @@ export default function ({ getService }: FtrProviderContext) { ongoingIds: '[]', recovered: '0', recoveredIds: '[]', + ruleId, }); - const document1 = resp.hits.hits[0]; + const document1 = resp.hits.hits[1]; expect(omit(document1, '_source.date')._source).to.eql({ all: '1', new: '0', @@ -490,6 +499,7 @@ export default function ({ getService }: FtrProviderContext) { ongoingIds: '[query matched,]', recovered: '0', recoveredIds: '[]', + ruleId, }); const alertDocument = resp2.hits.hits[0]._source as Record; @@ -520,7 +530,7 @@ export default function ({ getService }: FtrProviderContext) { groupBy: 'all', searchType: 'esQuery', }, - [ALERT_RULE_PRODUCER]: 'stackAlerts', + [ALERT_RULE_PRODUCER]: alertDocument[ALERT_RULE_PRODUCER], [ALERT_RULE_REVISION]: 0, [ALERT_RULE_TYPE_ID]: '.es-query', [ALERT_RULE_TAGS]: [], diff --git a/x-pack/test_serverless/api_integration/test_suites/observability/burn_rate_rule/burn_rate_rule.ts b/x-pack/test_serverless/api_integration/test_suites/observability/burn_rate_rule/burn_rate_rule.ts new file mode 100644 index 0000000000000..7d863d6cdbc66 --- /dev/null +++ b/x-pack/test_serverless/api_integration/test_suites/observability/burn_rate_rule/burn_rate_rule.ts @@ -0,0 +1,194 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.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 { cleanup, generate } from '@kbn/infra-forge'; +import expect from '@kbn/expect'; +import { FtrProviderContext } from '../../../ftr_provider_context'; + +export default function ({ getService }: FtrProviderContext) { + const esClient = getService('es'); + const supertest = getService('supertest'); + const esDeleteAllIndices = getService('esDeleteAllIndices'); + const logger = getService('log'); + const alertingApi = getService('alertingApi'); + const dataViewApi = getService('dataViewApi'); + const sloApi = getService('sloApi'); + + describe('Burn rate rule', () => { + const RULE_TYPE_ID = 'slo.rules.burnRate'; + // DATE_VIEW should match the index template: + // x-pack/packages/kbn-infra-forge/src/data_sources/composable/template.json + const DATE_VIEW = 'kbn-data-forge-fake_hosts'; + const ALERT_ACTION_INDEX = 'alert-action-slo'; + const DATA_VIEW_ID = 'data-view-id'; + let infraDataIndex: string; + let actionId: string; + let ruleId: string; + + before(async () => { + infraDataIndex = await generate({ esClient, lookback: 'now-15m', logger }); + await dataViewApi.create({ + name: DATE_VIEW, + id: DATA_VIEW_ID, + title: DATE_VIEW, + }); + }); + + after(async () => { + await supertest + .delete(`/api/alerting/rule/${ruleId}`) + .set('kbn-xsrf', 'foo') + .set('x-elastic-internal-origin', 'foo'); + await supertest + .delete(`/api/actions/connector/${actionId}`) + .set('kbn-xsrf', 'foo') + .set('x-elastic-internal-origin', 'foo'); + await esClient.deleteByQuery({ + index: '.kibana-event-log-*', + query: { term: { 'rule.id': ruleId } }, + conflicts: 'proceed', + }); + await dataViewApi.delete({ + id: DATA_VIEW_ID, + }); + await supertest + .delete('/api/observability/slos/my-custom-id') + .set('kbn-xsrf', 'foo') + .set('x-elastic-internal-origin', 'foo'); + + await esDeleteAllIndices([ALERT_ACTION_INDEX, infraDataIndex]); + await cleanup({ esClient, logger }); + }); + + describe('Rule creation', () => { + it('creates rule successfully', async () => { + actionId = await alertingApi.createIndexConnector({ + name: 'Index Connector: Slo Burn rate API test', + indexName: ALERT_ACTION_INDEX, + }); + + await sloApi.create({ + id: 'my-custom-id', + name: 'my custom name', + description: 'my custom description', + indicator: { + type: 'sli.kql.custom', + params: { + index: infraDataIndex, + good: 'system.cpu.total.norm.pct > 1', + total: 'system.cpu.total.norm.pct: *', + timestampField: '@timestamp', + }, + }, + timeWindow: { + duration: '7d', + type: 'rolling', + }, + budgetingMethod: 'occurrences', + objective: { + target: 0.999, + }, + groupBy: '*', + }); + + const createdRule = await alertingApi.createRule({ + tags: ['observability'], + consumer: 'observability', + name: 'SLO Burn Rate rule', + ruleTypeId: RULE_TYPE_ID, + schedule: { + interval: '1m', + }, + params: { + sloId: 'my-custom-id', + windows: [ + { + id: '1', + actionGroup: 'slo.burnRate.alert', + burnRateThreshold: 14.4, + maxBurnRateThreshold: 720, + longWindow: { + value: 1, + unit: 'h', + }, + shortWindow: { + value: 5, + unit: 'm', + }, + }, + { + id: '2', + actionGroup: 'slo.burnRate.high', + burnRateThreshold: 6, + maxBurnRateThreshold: 120, + longWindow: { + value: 6, + unit: 'h', + }, + shortWindow: { + value: 30, + unit: 'm', + }, + }, + { + id: '3', + actionGroup: 'slo.burnRate.medium', + burnRateThreshold: 3, + maxBurnRateThreshold: 30, + longWindow: { + value: 24, + unit: 'h', + }, + shortWindow: { + value: 120, + unit: 'm', + }, + }, + { + id: '4', + actionGroup: 'slo.burnRate.low', + burnRateThreshold: 1, + maxBurnRateThreshold: 10, + longWindow: { + value: 72, + unit: 'h', + }, + shortWindow: { + value: 360, + unit: 'm', + }, + }, + ], + }, + actions: [], + }); + ruleId = createdRule.id; + expect(ruleId).not.to.be(undefined); + }); + + it('should be active', async () => { + const executionStatus = await alertingApi.waitForRuleStatus({ + ruleId, + expectedStatus: 'active', + }); + expect(executionStatus).to.be('active'); + }); + + it('should find the created rule with correct information about the consumer', async () => { + const match = await alertingApi.findRule(ruleId); + expect(match).not.to.be(undefined); + expect(match.consumer).to.be('observability'); + }); + }); + }); +} diff --git a/x-pack/test_serverless/api_integration/test_suites/observability/custom_threshold_rule/avg_pct_fired.ts b/x-pack/test_serverless/api_integration/test_suites/observability/custom_threshold_rule/avg_pct_fired.ts index 90b602900341b..4aea7f5d670db 100644 --- a/x-pack/test_serverless/api_integration/test_suites/observability/custom_threshold_rule/avg_pct_fired.ts +++ b/x-pack/test_serverless/api_integration/test_suites/observability/custom_threshold_rule/avg_pct_fired.ts @@ -82,7 +82,7 @@ export default function ({ getService }: FtrProviderContext) { const createdRule = await alertingApi.createRule({ tags: ['observability'], - consumer: 'apm', + consumer: 'observability', name: 'Threshold rule', ruleTypeId: OBSERVABILITY_THRESHOLD_RULE_TYPE_ID, params: { @@ -139,6 +139,12 @@ export default function ({ getService }: FtrProviderContext) { expect(executionStatus).to.be('active'); }); + it('should find the created rule with correct information about the consumer', async () => { + const match = await alertingApi.findRule(ruleId); + expect(match).not.to.be(undefined); + expect(match.consumer).to.be('observability'); + }); + it('should set correct information in the alert document', async () => { const resp = await alertingApi.waitForAlertInIndex({ indexName: CUSTOM_THRESHOLD_RULE_ALERT_INDEX, @@ -149,7 +155,7 @@ export default function ({ getService }: FtrProviderContext) { 'kibana.alert.rule.category', 'Custom threshold (Technical Preview)' ); - expect(resp.hits.hits[0]._source).property('kibana.alert.rule.consumer', 'apm'); + expect(resp.hits.hits[0]._source).property('kibana.alert.rule.consumer', 'observability'); expect(resp.hits.hits[0]._source).property('kibana.alert.rule.name', 'Threshold rule'); expect(resp.hits.hits[0]._source).property('kibana.alert.rule.producer', 'observability'); expect(resp.hits.hits[0]._source).property('kibana.alert.rule.revision', 0); diff --git a/x-pack/test_serverless/api_integration/test_suites/observability/custom_threshold_rule/avg_pct_no_data.ts b/x-pack/test_serverless/api_integration/test_suites/observability/custom_threshold_rule/avg_pct_no_data.ts index f41aa7c9d3172..2d6e8d63afbf2 100644 --- a/x-pack/test_serverless/api_integration/test_suites/observability/custom_threshold_rule/avg_pct_no_data.ts +++ b/x-pack/test_serverless/api_integration/test_suites/observability/custom_threshold_rule/avg_pct_no_data.ts @@ -68,7 +68,7 @@ export default function ({ getService }: FtrProviderContext) { const createdRule = await alertingApi.createRule({ tags: ['observability'], - consumer: 'apm', + consumer: 'observability', name: 'Threshold rule', ruleTypeId: OBSERVABILITY_THRESHOLD_RULE_TYPE_ID, params: { @@ -125,6 +125,12 @@ export default function ({ getService }: FtrProviderContext) { expect(executionStatus).to.be('active'); }); + it('should find the created rule with correct information about the consumer', async () => { + const match = await alertingApi.findRule(ruleId); + expect(match).not.to.be(undefined); + expect(match.consumer).to.be('observability'); + }); + it('should set correct information in the alert document', async () => { const resp = await alertingApi.waitForAlertInIndex({ indexName: CUSTOM_THRESHOLD_RULE_ALERT_INDEX, @@ -135,7 +141,7 @@ export default function ({ getService }: FtrProviderContext) { 'kibana.alert.rule.category', 'Custom threshold (Technical Preview)' ); - expect(resp.hits.hits[0]._source).property('kibana.alert.rule.consumer', 'apm'); + expect(resp.hits.hits[0]._source).property('kibana.alert.rule.consumer', 'observability'); expect(resp.hits.hits[0]._source).property('kibana.alert.rule.name', 'Threshold rule'); expect(resp.hits.hits[0]._source).property('kibana.alert.rule.producer', 'observability'); expect(resp.hits.hits[0]._source).property('kibana.alert.rule.revision', 0); diff --git a/x-pack/test_serverless/api_integration/test_suites/observability/custom_threshold_rule/custom_eq_avg_bytes_fired.ts b/x-pack/test_serverless/api_integration/test_suites/observability/custom_threshold_rule/custom_eq_avg_bytes_fired.ts index 5aaa276afc25b..1f02377919a8d 100644 --- a/x-pack/test_serverless/api_integration/test_suites/observability/custom_threshold_rule/custom_eq_avg_bytes_fired.ts +++ b/x-pack/test_serverless/api_integration/test_suites/observability/custom_threshold_rule/custom_eq_avg_bytes_fired.ts @@ -84,7 +84,7 @@ export default function ({ getService }: FtrProviderContext) { const createdRule = await alertingApi.createRule({ tags: ['observability'], - consumer: 'apm', + consumer: 'observability', name: 'Threshold rule', ruleTypeId: OBSERVABILITY_THRESHOLD_RULE_TYPE_ID, params: { @@ -143,6 +143,12 @@ export default function ({ getService }: FtrProviderContext) { expect(executionStatus).to.be('active'); }); + it('should find the created rule with correct information about the consumer', async () => { + const match = await alertingApi.findRule(ruleId); + expect(match).not.to.be(undefined); + expect(match.consumer).to.be('observability'); + }); + it('should set correct information in the alert document', async () => { const resp = await alertingApi.waitForAlertInIndex({ indexName: CUSTOM_THRESHOLD_RULE_ALERT_INDEX, @@ -153,7 +159,7 @@ export default function ({ getService }: FtrProviderContext) { 'kibana.alert.rule.category', 'Custom threshold (Technical Preview)' ); - expect(resp.hits.hits[0]._source).property('kibana.alert.rule.consumer', 'apm'); + expect(resp.hits.hits[0]._source).property('kibana.alert.rule.consumer', 'observability'); expect(resp.hits.hits[0]._source).property('kibana.alert.rule.name', 'Threshold rule'); expect(resp.hits.hits[0]._source).property('kibana.alert.rule.producer', 'observability'); expect(resp.hits.hits[0]._source).property('kibana.alert.rule.revision', 0); diff --git a/x-pack/test_serverless/api_integration/test_suites/observability/custom_threshold_rule/documents_count_fired.ts b/x-pack/test_serverless/api_integration/test_suites/observability/custom_threshold_rule/documents_count_fired.ts index ee8c266287e20..5c34258de8c15 100644 --- a/x-pack/test_serverless/api_integration/test_suites/observability/custom_threshold_rule/documents_count_fired.ts +++ b/x-pack/test_serverless/api_integration/test_suites/observability/custom_threshold_rule/documents_count_fired.ts @@ -78,7 +78,7 @@ export default function ({ getService }: FtrProviderContext) { const createdRule = await alertingApi.createRule({ tags: ['observability'], - consumer: 'apm', + consumer: 'observability', name: 'Threshold rule', ruleTypeId: OBSERVABILITY_THRESHOLD_RULE_TYPE_ID, params: { @@ -133,6 +133,12 @@ export default function ({ getService }: FtrProviderContext) { expect(executionStatus).to.be('active'); }); + it('should find the created rule with correct information about the consumer', async () => { + const match = await alertingApi.findRule(ruleId); + expect(match).not.to.be(undefined); + expect(match.consumer).to.be('observability'); + }); + it('should set correct information in the alert document', async () => { const resp = await alertingApi.waitForAlertInIndex({ indexName: CUSTOM_THRESHOLD_RULE_ALERT_INDEX, @@ -143,7 +149,7 @@ export default function ({ getService }: FtrProviderContext) { 'kibana.alert.rule.category', 'Custom threshold (Technical Preview)' ); - expect(resp.hits.hits[0]._source).property('kibana.alert.rule.consumer', 'apm'); + expect(resp.hits.hits[0]._source).property('kibana.alert.rule.consumer', 'observability'); expect(resp.hits.hits[0]._source).property('kibana.alert.rule.name', 'Threshold rule'); expect(resp.hits.hits[0]._source).property('kibana.alert.rule.producer', 'observability'); expect(resp.hits.hits[0]._source).property('kibana.alert.rule.revision', 0); diff --git a/x-pack/test_serverless/api_integration/test_suites/observability/custom_threshold_rule/group_by_fired.ts b/x-pack/test_serverless/api_integration/test_suites/observability/custom_threshold_rule/group_by_fired.ts index 3139b40587ddf..864b35de6f3d4 100644 --- a/x-pack/test_serverless/api_integration/test_suites/observability/custom_threshold_rule/group_by_fired.ts +++ b/x-pack/test_serverless/api_integration/test_suites/observability/custom_threshold_rule/group_by_fired.ts @@ -88,7 +88,7 @@ export default function ({ getService }: FtrProviderContext) { const createdRule = await alertingApi.createRule({ tags: ['observability'], - consumer: 'apm', + consumer: 'observability', name: 'Threshold rule', ruleTypeId: OBSERVABILITY_THRESHOLD_RULE_TYPE_ID, params: { @@ -150,6 +150,12 @@ export default function ({ getService }: FtrProviderContext) { expect(executionStatus).to.be('active'); }); + it('should find the created rule with correct information about the consumer', async () => { + const match = await alertingApi.findRule(ruleId); + expect(match).not.to.be(undefined); + expect(match.consumer).to.be('observability'); + }); + it('should set correct information in the alert document', async () => { const resp = await alertingApi.waitForAlertInIndex({ indexName: CUSTOM_THRESHOLD_RULE_ALERT_INDEX, @@ -162,7 +168,7 @@ export default function ({ getService }: FtrProviderContext) { 'kibana.alert.rule.category', 'Custom threshold (Technical Preview)' ); - expect(resp.hits.hits[0]._source).property('kibana.alert.rule.consumer', 'apm'); + expect(resp.hits.hits[0]._source).property('kibana.alert.rule.consumer', 'observability'); expect(resp.hits.hits[0]._source).property('kibana.alert.rule.name', 'Threshold rule'); expect(resp.hits.hits[0]._source).property('kibana.alert.rule.producer', 'observability'); expect(resp.hits.hits[0]._source).property('kibana.alert.rule.revision', 0); diff --git a/x-pack/test_serverless/api_integration/test_suites/observability/es_query_rule/es_query_rule.ts b/x-pack/test_serverless/api_integration/test_suites/observability/es_query_rule/es_query_rule.ts new file mode 100644 index 0000000000000..9f7c72889623b --- /dev/null +++ b/x-pack/test_serverless/api_integration/test_suites/observability/es_query_rule/es_query_rule.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. + */ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import expect from '@kbn/expect'; +import { FtrProviderContext } from '../../../ftr_provider_context'; +import { createEsQueryRule } from '../../common/alerting/helpers/alerting_api_helper'; +export default function ({ getService }: FtrProviderContext) { + const esClient = getService('es'); + const supertest = getService('supertest'); + const esDeleteAllIndices = getService('esDeleteAllIndices'); + const alertingApi = getService('alertingApi'); + + describe('ElasticSearch query rule', () => { + const RULE_TYPE_ID = '.es-query'; + const ALERT_ACTION_INDEX = 'alert-action-es-query'; + let actionId: string; + let ruleId: string; + + after(async () => { + await supertest + .delete(`/api/alerting/rule/${ruleId}`) + .set('kbn-xsrf', 'foo') + .set('x-elastic-internal-origin', 'foo'); + await supertest + .delete(`/api/actions/connector/${actionId}`) + .set('kbn-xsrf', 'foo') + .set('x-elastic-internal-origin', 'foo'); + await esClient.deleteByQuery({ + index: '.kibana-event-log-*', + query: { term: { 'rule.id': ruleId } }, + conflicts: 'proceed', + }); + await esDeleteAllIndices([ALERT_ACTION_INDEX]); + }); + + describe('Rule creation', () => { + it('creates rule successfully', async () => { + actionId = await alertingApi.createIndexConnector({ + name: 'Index Connector: Alerting API test', + indexName: ALERT_ACTION_INDEX, + }); + + const createdRule = await createEsQueryRule({ + supertest, + consumer: 'observability', + name: 'always fire', + ruleTypeId: RULE_TYPE_ID, + params: { + size: 100, + thresholdComparator: '>', + threshold: [-1], + index: ['alert-test-data'], + timeField: 'date', + esQuery: `{\n \"query\":{\n \"match_all\" : {}\n }\n}`, + timeWindowSize: 20, + timeWindowUnit: 's', + }, + actions: [ + { + group: 'query matched', + id: actionId, + params: { + documents: [ + { + ruleId: '{{rule.id}}', + ruleName: '{{rule.name}}', + ruleParams: '{{rule.params}}', + spaceId: '{{rule.spaceId}}', + tags: '{{rule.tags}}', + alertId: '{{alert.id}}', + alertActionGroup: '{{alert.actionGroup}}', + instanceContextValue: '{{context.instanceContextValue}}', + instanceStateValue: '{{state.instanceStateValue}}', + }, + ], + }, + frequency: { + notify_when: 'onActiveAlert', + throttle: null, + summary: false, + }, + }, + ], + }); + ruleId = createdRule.id; + expect(ruleId).not.to.be(undefined); + }); + + it('should be active', async () => { + const executionStatus = await alertingApi.waitForRuleStatus({ + ruleId, + expectedStatus: 'active', + }); + expect(executionStatus).to.be('active'); + }); + + it('should find the created rule with correct information about the consumer', async () => { + const match = await alertingApi.findRule(ruleId); + expect(match).not.to.be(undefined); + expect(match.consumer).to.be('observability'); + }); + }); + }); +} diff --git a/x-pack/test_serverless/api_integration/test_suites/observability/index.ts b/x-pack/test_serverless/api_integration/test_suites/observability/index.ts index 72cb01c03fd2f..54d4e41c1f892 100644 --- a/x-pack/test_serverless/api_integration/test_suites/observability/index.ts +++ b/x-pack/test_serverless/api_integration/test_suites/observability/index.ts @@ -16,5 +16,7 @@ export default function ({ loadTestFile }: FtrProviderContext) { loadTestFile(require.resolve('./telemetry/telemetry_config')); loadTestFile(require.resolve('./apm_api_integration/feature_flags.ts')); loadTestFile(require.resolve('./cases')); + loadTestFile(require.resolve('./burn_rate_rule/burn_rate_rule')); + loadTestFile(require.resolve('./es_query_rule/es_query_rule')); }); } diff --git a/x-pack/test_serverless/functional/test_suites/observability/observability_log_explorer/flyout.ts b/x-pack/test_serverless/functional/test_suites/observability/observability_log_explorer/flyout.ts new file mode 100644 index 0000000000000..79f241c8948b6 --- /dev/null +++ b/x-pack/test_serverless/functional/test_suites/observability/observability_log_explorer/flyout.ts @@ -0,0 +1,93 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import { FtrProviderContext } from '../../../ftr_provider_context'; + +const DATASET_NAME = 'flyout'; +const NAMESPACE = 'default'; +const DATA_STREAM_NAME = `logs-${DATASET_NAME}-${NAMESPACE}`; +const NOW = Date.now(); + +const sharedDoc = { + logFilepath: '/flyout.log', + serviceName: DATASET_NAME, + datasetName: DATASET_NAME, + namespace: NAMESPACE, +}; + +const docs = [ + { + ...sharedDoc, + time: NOW + 1000, + message: 'full document', + logLevel: 'info', + }, + { + ...sharedDoc, + time: NOW, + }, +]; + +export default function ({ getService, getPageObjects }: FtrProviderContext) { + const dataGrid = getService('dataGrid'); + const testSubjects = getService('testSubjects'); + const PageObjects = getPageObjects(['observabilityLogExplorer', 'svlCommonPage']); + + describe('Flyout content customization', () => { + let cleanupDataStreamSetup: () => Promise; + + before('initialize tests', async () => { + cleanupDataStreamSetup = await PageObjects.observabilityLogExplorer.setupDataStream( + DATASET_NAME, + NAMESPACE + ); + await PageObjects.observabilityLogExplorer.ingestLogEntries(DATA_STREAM_NAME, docs); + await PageObjects.svlCommonPage.login(); + }); + + beforeEach(async () => { + await PageObjects.observabilityLogExplorer.navigateTo({ + from: new Date(NOW - 60_000).toISOString(), + to: new Date(NOW + 60_000).toISOString(), + }); + }); + + after('clean up archives', async () => { + await PageObjects.svlCommonPage.forceLogout(); + if (cleanupDataStreamSetup) { + cleanupDataStreamSetup(); + } + }); + + it('should mount the flyout customization content', async () => { + await dataGrid.clickRowToggle(); + await testSubjects.existOrFail('logExplorerFlyoutDetail'); + }); + + it('should display a timestamp badge', async () => { + await dataGrid.clickRowToggle(); + await testSubjects.existOrFail('logExplorerFlyoutLogTimestamp'); + }); + + it('should display a log level badge when available', async () => { + await dataGrid.clickRowToggle(); + await testSubjects.existOrFail('logExplorerFlyoutLogLevel'); + await dataGrid.closeFlyout(); + + await dataGrid.clickRowToggle({ rowIndex: 1 }); + await testSubjects.missingOrFail('logExplorerFlyoutLogLevel'); + }); + + it('should display a message code block when available', async () => { + await dataGrid.clickRowToggle(); + await testSubjects.existOrFail('logExplorerFlyoutLogMessage'); + await dataGrid.closeFlyout(); + + await dataGrid.clickRowToggle({ rowIndex: 1 }); + await testSubjects.missingOrFail('logExplorerFlyoutLogMessage'); + }); + }); +} diff --git a/x-pack/test_serverless/functional/test_suites/observability/observability_log_explorer/index.ts b/x-pack/test_serverless/functional/test_suites/observability/observability_log_explorer/index.ts index 77f89dad01f77..6e0b650869680 100644 --- a/x-pack/test_serverless/functional/test_suites/observability/observability_log_explorer/index.ts +++ b/x-pack/test_serverless/functional/test_suites/observability/observability_log_explorer/index.ts @@ -14,6 +14,7 @@ export default function ({ loadTestFile }: FtrProviderContext) { loadTestFile(require.resolve('./dataset_selection_state')); loadTestFile(require.resolve('./dataset_selector')); loadTestFile(require.resolve('./filter_controls')); + loadTestFile(require.resolve('./flyout')); loadTestFile(require.resolve('./header_menu')); }); } diff --git a/x-pack/test_serverless/functional/test_suites/observability/rules/rules_list.ts b/x-pack/test_serverless/functional/test_suites/observability/rules/rules_list.ts index 4b78147ef4941..917e953cb2aec 100644 --- a/x-pack/test_serverless/functional/test_suites/observability/rules/rules_list.ts +++ b/x-pack/test_serverless/functional/test_suites/observability/rules/rules_list.ts @@ -15,6 +15,7 @@ import { createIndexConnector, snoozeRule, createLatencyThresholdRule, + createEsQueryRule, } from '../../../../api_integration/test_suites/common/alerting/helpers/alerting_api_helper'; export default ({ getPageObject, getService }: FtrProviderContext) => { @@ -90,6 +91,64 @@ export default ({ getPageObject, getService }: FtrProviderContext) => { await svlCommonPage.forceLogout(); }); + it('should create an ES Query Rule and display it when consumer is observability', async () => { + const esQuery = await createEsQueryRule({ + supertest, + name: 'ES Query', + consumer: 'observability', + ruleTypeId: '.es-query', + params: { + size: 100, + thresholdComparator: '>', + threshold: [-1], + index: ['alert-test-data'], + timeField: 'date', + esQuery: `{\n \"query\":{\n \"match_all\" : {}\n }\n}`, + timeWindowSize: 20, + timeWindowUnit: 's', + }, + }); + ruleIdList = [esQuery.id]; + + await refreshRulesList(); + const searchResults = await svlTriggersActionsUI.getRulesList(); + expect(searchResults.length).toEqual(1); + expect(searchResults[0].name).toEqual('ES QueryElasticsearch query'); + }); + + it('should create an ES Query rule but not display it when consumer is stackAlerts', async () => { + const esQuery = await createEsQueryRule({ + supertest, + name: 'ES Query', + consumer: 'stackAlerts', + ruleTypeId: '.es-query', + params: { + size: 100, + thresholdComparator: '>', + threshold: [-1], + index: ['alert-test-data'], + timeField: 'date', + esQuery: `{\n \"query\":{\n \"match_all\" : {}\n }\n}`, + timeWindowSize: 20, + timeWindowUnit: 's', + }, + }); + ruleIdList = [esQuery.id]; + + await refreshRulesList(); + await testSubjects.missingOrFail('rule-row'); + }); + + it('should create and display an APM latency rule', async () => { + const apmLatency = await createLatencyThresholdRule({ supertest, name: 'Apm latency' }); + ruleIdList = [apmLatency.id]; + + await refreshRulesList(); + const searchResults = await svlTriggersActionsUI.getRulesList(); + expect(searchResults.length).toEqual(1); + expect(searchResults[0].name).toEqual('Apm latencyLatency threshold'); + }); + it('should display rules in alphabetical order', async () => { const rule1 = await createRule({ supertest, @@ -600,7 +659,9 @@ export default ({ getPageObject, getService }: FtrProviderContext) => { await testSubjects.click('ruleTypeFilterButton'); } - expect(await (await testSubjects.find('ruleType0Group')).getVisibleText()).toEqual('Apm'); + expect(await (await testSubjects.find('ruleType0Group')).getVisibleText()).toEqual( + 'Observability' + ); }); await testSubjects.click('ruleTypeapm.anomalyFilterOption'); diff --git a/x-pack/test_serverless/shared/lib/security/kibana_roles/project_controller_security_roles.yml b/x-pack/test_serverless/shared/lib/security/kibana_roles/project_controller_security_roles.yml index 1444b818b10ee..a8f7adfc85777 100644 --- a/x-pack/test_serverless/shared/lib/security/kibana_roles/project_controller_security_roles.yml +++ b/x-pack/test_serverless/shared/lib/security/kibana_roles/project_controller_security_roles.yml @@ -43,9 +43,16 @@ viewer: - feature_siem.read_alerts - feature_siem.endpoint_list_read - feature_securitySolutionCases.read + - feature_securitySolutionAssistant.all - feature_actions.read - feature_builtInAlerts.read - feature_osquery.read + - feature_discover.all + - feature_dashboard.all + - feature_canvas.all + - feature_graph.all + - feature_maps.all + - feature_visualize.all resources: "*" run_as: [] @@ -105,9 +112,16 @@ editor: - feature_siem.actions_log_management_all # Response actions history - feature_siem.file_operations_all - feature_securitySolutionCases.all + - feature_securitySolutionAssistant.all - feature_actions.read - feature_builtInAlerts.all - feature_osquery.all + - feature_discover.all + - feature_dashboard.all + - feature_canvas.all + - feature_graph.all + - feature_maps.all + - feature_visualize.all resources: "*" run_as: [] @@ -144,10 +158,17 @@ t1_analyst: - feature_siem.read_alerts - feature_siem.endpoint_list_read - feature_securitySolutionCases.read + - feature_securitySolutionAssistant.all - feature_actions.read - feature_builtInAlerts.read - feature_osquery.read - feature_osquery.run_saved_queries + - feature_discover.all + - feature_dashboard.all + - feature_canvas.all + - feature_graph.all + - feature_maps.all + - feature_visualize.all resources: "*" t2_analyst: @@ -185,10 +206,17 @@ t2_analyst: - feature_siem.read_alerts - feature_siem.endpoint_list_read - feature_securitySolutionCases.all + - feature_securitySolutionAssistant.all - feature_actions.read - feature_builtInAlerts.read - feature_osquery.read - feature_osquery.run_saved_queries + - feature_discover.all + - feature_dashboard.all + - feature_canvas.all + - feature_graph.all + - feature_maps.all + - feature_visualize.all resources: "*" t3_analyst: @@ -243,9 +271,16 @@ t3_analyst: - feature_siem.actions_log_management_all # Response actions history - feature_siem.file_operations_all - feature_securitySolutionCases.all + - feature_securitySolutionAssistant.all - feature_actions.read - feature_builtInAlerts.all - feature_osquery.all + - feature_discover.all + - feature_dashboard.all + - feature_canvas.all + - feature_graph.all + - feature_maps.all + - feature_visualize.all resources: "*" threat_intelligence_analyst: @@ -287,9 +322,16 @@ threat_intelligence_analyst: - feature_siem.endpoint_list_read - feature_siem.blocklist_all - feature_securitySolutionCases.all + - feature_securitySolutionAssistant.all - feature_actions.read - feature_builtInAlerts.read - feature_osquery.all + - feature_discover.all + - feature_dashboard.all + - feature_canvas.all + - feature_graph.all + - feature_maps.all + - feature_visualize.all resources: "*" rule_author: @@ -345,9 +387,16 @@ rule_author: - feature_siem.blocklist_all # Elastic Defend Policy Management - feature_siem.actions_log_management_read - feature_securitySolutionCases.all + - feature_securitySolutionAssistant.all - feature_actions.read - feature_builtInAlerts.all - feature_osquery.all + - feature_discover.all + - feature_dashboard.all + - feature_canvas.all + - feature_graph.all + - feature_maps.all + - feature_visualize.all resources: "*" soc_manager: @@ -406,10 +455,17 @@ soc_manager: - feature_siem.file_operations_all - feature_siem.execute_operations_all - feature_securitySolutionCases.all + - feature_securitySolutionAssistant.all - feature_actions.all - feature_builtInAlerts.all - feature_osquery.all - feature_indexPatterns.all + - feature_discover.all + - feature_dashboard.all + - feature_canvas.all + - feature_graph.all + - feature_maps.all + - feature_visualize.all resources: "*" detections_admin: @@ -452,9 +508,16 @@ detections_admin: - feature_siem.read_alerts - feature_siem.crud_alerts - feature_securitySolutionCases.all + - feature_securitySolutionAssistant.all - feature_actions.all - feature_builtInAlerts.all - feature_dev_tools.all + - feature_discover.all + - feature_dashboard.all + - feature_canvas.all + - feature_graph.all + - feature_maps.all + - feature_visualize.all resources: "*" platform_engineer: @@ -494,12 +557,19 @@ platform_engineer: - feature_siem.blocklist_all # Elastic Defend Policy Management - feature_siem.actions_log_management_read - feature_securitySolutionCases.all + - feature_securitySolutionAssistant.all - feature_actions.all - feature_builtInAlerts.all - feature_fleet.all - feature_fleetv2.all - feature_osquery.all - feature_indexPatterns.all + - feature_discover.all + - feature_dashboard.all + - feature_canvas.all + - feature_graph.all + - feature_maps.all + - feature_visualize.all resources: "*" endpoint_operations_analyst: @@ -551,11 +621,18 @@ endpoint_operations_analyst: - feature_siem.file_operations_all - feature_siem.execute_operations_all # Execute - feature_securitySolutionCases.all + - feature_securitySolutionAssistant.all - feature_actions.all - feature_builtInAlerts.all - feature_osquery.all - feature_fleet.all - feature_fleetv2.all + - feature_discover.all + - feature_dashboard.all + - feature_canvas.all + - feature_graph.all + - feature_maps.all + - feature_visualize.all resources: "*" endpoint_policy_manager: @@ -604,9 +681,16 @@ endpoint_policy_manager: - feature_siem.host_isolation_exceptions_all - feature_siem.blocklist_all # Elastic Defend Policy Management - feature_securitySolutionCases.all + - feature_securitySolutionAssistant.all - feature_actions.all - feature_builtInAlerts.all - feature_osquery.all - feature_fleet.all - feature_fleetv2.all + - feature_discover.all + - feature_dashboard.all + - feature_canvas.all + - feature_graph.all + - feature_maps.all + - feature_visualize.all resources: "*" diff --git a/yarn.lock b/yarn.lock index 5d989557d0e3d..58959d6e520ad 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5596,15 +5596,7 @@ version "0.0.0" uid "" -"@kbn/shared-ux-button-exit-full-screen-mocks@link:packages/shared-ux/button/exit_full_screen/mocks": - version "0.0.0" - uid "" - -"@kbn/shared-ux-button-exit-full-screen-types@link:packages/shared-ux/button/exit_full_screen/types": - version "0.0.0" - uid "" - -"@kbn/shared-ux-button-exit-full-screen@link:packages/shared-ux/button/exit_full_screen/impl": +"@kbn/shared-ux-button-exit-full-screen@link:packages/shared-ux/button/exit_full_screen": version "0.0.0" uid "" @@ -8706,13 +8698,6 @@ dependencies: "@types/color-convert" "*" -"@types/compression-webpack-plugin@^2.0.2": - version "2.0.2" - resolved "https://registry.yarnpkg.com/@types/compression-webpack-plugin/-/compression-webpack-plugin-2.0.2.tgz#9d8956a542ea974e018ab5dc2316480edbaf17fb" - integrity sha512-4GW0o21FHqRwP/HYC8o7ceiO9duBopo1v5MaTVZy8VqF6nnRRDoG/C6djGxAmC7uyXRBK8AdnB2IVQgkoRokXQ== - dependencies: - "@types/webpack" "*" - "@types/connect-history-api-fallback@^1.3.5": version "1.3.5" resolved "https://registry.yarnpkg.com/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.3.5.tgz#d1f7a8a09d0ed5a57aee5ae9c18ab9b803205dae" @@ -8971,13 +8956,6 @@ dependencies: "@types/node" "*" -"@types/gulp-zip@^4.0.1": - version "4.0.1" - resolved "https://registry.yarnpkg.com/@types/gulp-zip/-/gulp-zip-4.0.1.tgz#96cd0b994219f9ae3bbbec7ec3baa043fba9d9ef" - integrity sha512-dYwGsHmwv4pnMD+jtyuIdZchJ0CIivnl8PIApHC+rYN7FMj01tJSAiQb+YN4T/pOn10pmmucBLEB9wXEhQX2Ug== - dependencies: - "@types/node" "*" - "@types/gulp@^4.0.6": version "4.0.6" resolved "https://registry.yarnpkg.com/@types/gulp/-/gulp-4.0.6.tgz#68fe0e1f0ff3657cfca46fb564806b744a1bf899" @@ -12291,7 +12269,7 @@ cacache@^12.0.2: unique-filename "^1.1.1" y18n "^4.0.0" -cacache@^15.0.3, cacache@^15.0.4, cacache@^15.0.5, cacache@^15.2.0: +cacache@^15.0.4, cacache@^15.0.5, cacache@^15.2.0: version "15.3.0" resolved "https://registry.yarnpkg.com/cacache/-/cacache-15.3.0.tgz#dc85380fb2f556fe3dda4c719bfa0ec875a7f1eb" integrity sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ== @@ -12731,10 +12709,10 @@ chrome-trace-event@^1.0.2: dependencies: tslib "^1.9.0" -chromedriver@^117.0.3: - version "117.0.3" - resolved "https://registry.yarnpkg.com/chromedriver/-/chromedriver-117.0.3.tgz#4a14cc992d572367b99b53c772adcc4c19078e1e" - integrity sha512-c2rk2eGK5zZFBJMdviUlAJfQEBuPNIKfal4+rTFVYAmrWbMPYAqPozB+rIkc1lDP/Ryw44lPiqKglrI01ILhTQ== +chromedriver@^119.0.0: + version "119.0.0" + resolved "https://registry.yarnpkg.com/chromedriver/-/chromedriver-119.0.0.tgz#f250c442e72266f3e28d2b1eebc6a671a8629340" + integrity sha512-3TmabGT7xg57/Jbsg6B/Kqk3HaSbCP1ZHkR5zNft5vT/IWKjZCAGTH9waMI+i5KHSEiMH0zOw/WF98l+1Npkpw== dependencies: "@testim/chrome-version" "^1.1.3" axios "^1.4.0" @@ -13178,17 +13156,6 @@ compressible@~2.0.16: dependencies: mime-db ">= 1.40.0 < 2" -compression-webpack-plugin@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/compression-webpack-plugin/-/compression-webpack-plugin-4.0.0.tgz#7599f592050002a49cd3ad3ee18ae7371e266bca" - integrity sha512-DRoFQNTkQ8gadlk117Y2wxANU+MDY56b1FIZj/yJXucBOTViTHXjthM7G9ocnitksk4kLzt1N2RLF0gDjxI+hg== - dependencies: - cacache "^15.0.3" - find-cache-dir "^3.3.1" - schema-utils "^2.6.6" - serialize-javascript "^3.0.0" - webpack-sources "^1.4.3" - compression@^1.7.4: version "1.7.4" resolved "https://registry.yarnpkg.com/compression/-/compression-1.7.4.tgz#95523eff170ca57c29a0ca41e6fe131f41e5bb8f" @@ -17762,17 +17729,6 @@ gulp-terser@^2.1.0: through2 "^4.0.2" vinyl-sourcemaps-apply "^0.2.1" -gulp-zip@^5.0.2: - version "5.0.2" - resolved "https://registry.yarnpkg.com/gulp-zip/-/gulp-zip-5.0.2.tgz#2edf797ec842e770f4dfde8bef97d139015b1972" - integrity sha512-rZd0Ppuc8Bf7J2/WzcdNaeb+lcEXf1R8mV/PJ9Kdu7PmnInWVeLSmiXIka/2QSe6uhAsGVFAMffWSaMzAPGTBg== - dependencies: - get-stream "^5.1.0" - plugin-error "^1.0.1" - through2 "^3.0.1" - vinyl "^2.1.0" - yazl "^2.5.1" - gzip-size@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-6.0.0.tgz#065367fd50c239c0671cbcbad5be3e2eeb10e462" @@ -26791,7 +26747,7 @@ scheduler@^0.20.2: loose-envify "^1.1.0" object-assign "^4.1.1" -schema-utils@2.7.0, schema-utils@^2.0.0, schema-utils@^2.0.1, schema-utils@^2.5.0, schema-utils@^2.6.5, schema-utils@^2.6.6, schema-utils@^2.7.0: +schema-utils@2.7.0, schema-utils@^2.0.0, schema-utils@^2.0.1, schema-utils@^2.5.0, schema-utils@^2.6.5, schema-utils@^2.7.0: version "2.7.0" resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.7.0.tgz#17151f76d8eae67fbbf77960c33c676ad9f4efc7" integrity sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A== @@ -26948,7 +26904,7 @@ serialize-javascript@6.0.0, serialize-javascript@^6.0.0: dependencies: randombytes "^2.1.0" -serialize-javascript@^3.0.0, serialize-javascript@^3.1.0: +serialize-javascript@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-3.1.0.tgz#8bf3a9170712664ef2561b44b691eafe399214ea" integrity sha512-JIJT1DGiWmIKhzRsG91aS6Ze4sFUrYbltlkg2onR5OrnNM02Kl/hnY/T4FN2omvyeBbQmMJv+K4cPOpGzOTFBg== @@ -30325,7 +30281,7 @@ vinyl-sourcemaps-apply@^0.2.1: dependencies: source-map "^0.5.1" -vinyl@^2.1.0, vinyl@^2.2.0: +vinyl@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-2.2.0.tgz#d85b07da96e458d25b2ffe19fece9f2caa13ed86" integrity sha512-MBH+yP0kC/GQ5GwBqrTPTzEfiiLjta7hTtvQtbxBgTeSXsmKQRQecjibMbxIXzVT3Y9KJK+drOz1/k+vsu8Nkg==