diff --git a/.buildkite/ftr_configs.yml b/.buildkite/ftr_configs.yml index ac53265b1c979..5b1734613c0f6 100644 --- a/.buildkite/ftr_configs.yml +++ b/.buildkite/ftr_configs.yml @@ -403,7 +403,9 @@ enabled: - 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/integrations_feature_flag.config.ts - x-pack/test/security_solution_endpoint/serverless.integrations.config.ts + - x-pack/test/security_solution_endpoint/serverless.integrations_feature_flag.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/scripts/steps/fips/smoke_test.sh b/.buildkite/scripts/steps/fips/smoke_test.sh index 7026c7bab941c..5c70e8c2057df 100755 --- a/.buildkite/scripts/steps/fips/smoke_test.sh +++ b/.buildkite/scripts/steps/fips/smoke_test.sh @@ -36,9 +36,9 @@ for config in "${configs[@]}"; do echo "^^^ +++" if [[ "$failedConfigs" ]]; then - failedConfigs="${failedConfigs}"$'\n'"$config" + failedConfigs="${failedConfigs}"$'\n'"- ${config}" else - failedConfigs="$config" + failedConfigs="### Failed FTR Configs"$'\n'"- ${config}" fi fi done diff --git a/.buildkite/scripts/steps/package_testing/test.sh b/.buildkite/scripts/steps/package_testing/test.sh index 99750529815c8..4917932e05228 100755 --- a/.buildkite/scripts/steps/package_testing/test.sh +++ b/.buildkite/scripts/steps/package_testing/test.sh @@ -58,12 +58,16 @@ trap "echoKibanaLogs" EXIT if [[ "$TEST_PACKAGE" == "fips" ]]; then set +e vagrant ssh $TEST_PACKAGE -t -c "/home/vagrant/kibana/.buildkite/scripts/steps/fips/smoke_test.sh" + exitCode=$? + vagrant ssh $TEST_PACKAGE -t -c "cat /home/vagrant/ftr_failed_configs 2>/dev/null" >ftr_failed_configs set -e if [ -s ftr_failed_configs ]; then - buildkite-agent meta-data set "ftr-failed-configs" <./ftr_failed_configs + cat ftr_failed_configs | buildkite-agent annotate --style "error" fi + + exit $exitCode else vagrant provision "$TEST_PACKAGE" diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 726e9c2223d39..d160dda238f8d 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -390,6 +390,7 @@ src/plugins/embeddable @elastic/kibana-presentation x-pack/examples/embedded_lens_example @elastic/kibana-visualizations x-pack/plugins/encrypted_saved_objects @elastic/kibana-security x-pack/plugins/enterprise_search @elastic/enterprise-search-frontend +x-pack/packages/kbn-entities-schema @elastic/obs-knowledge-team examples/error_boundary @elastic/appex-sharedux packages/kbn-es @elastic/kibana-operations packages/kbn-es-archiver @elastic/kibana-operations @elastic/appex-qa @@ -1278,6 +1279,10 @@ x-pack/plugins/cloud_integrations/cloud_full_story/server/config.ts @elastic/kib /src/dev/eslint/security_eslint_rule_tests.ts @elastic/kibana-security /src/core/server/integration_tests/config/check_dynamic_config.test.ts @elastic/kibana-security /src/plugins/telemetry/server/config/telemetry_labels.ts @elastic/kibana-security +/packages/kbn-std/src/is_internal_url.test.ts @elastic/kibana-core @elastic/kibana-security +/packages/kbn-std/src/is_internal_url.ts @elastic/kibana-core @elastic/kibana-security +/packages/kbn-std/src/parse_next_url.test.ts @elastic/kibana-core @elastic/kibana-security +/packages/kbn-std/src/parse_next_url.ts @elastic/kibana-core @elastic/kibana-security /test/interactive_setup_api_integration/ @elastic/kibana-security /test/interactive_setup_functional/ @elastic/kibana-security /test/plugin_functional/test_suites/core_plugins/rendering.ts @elastic/kibana-security diff --git a/.github/workflows/project-assigner.yml b/.github/workflows/project-assigner.yml index 8c381dd1ecdef..a5fe7c736ad3a 100644 --- a/.github/workflows/project-assigner.yml +++ b/.github/workflows/project-assigner.yml @@ -13,7 +13,6 @@ jobs: with: issue-mappings: | [ - {"label": "Feature:Lens", "projectNumber": 32, "columnName": "Long-term goals"}, {"label": "Team:DataDiscovery", "projectNumber": 44, "columnName": "Inbox"}, {"label": "Feature:Canvas", "projectNumber": 38, "columnName": "Inbox"}, {"label": "Feature:Dashboard", "projectNumber": 68, "columnName": "Inbox"}, diff --git a/api_docs/actions.mdx b/api_docs/actions.mdx index 6d677b0619e15..bd4c6daf1fec6 100644 --- a/api_docs/actions.mdx +++ b/api_docs/actions.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/actions title: "actions" image: https://source.unsplash.com/400x175/?github description: API docs for the actions plugin -date: 2024-05-16 +date: 2024-05-17 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 bc6c6c7e388fa..09e4690e3fdd6 100644 --- a/api_docs/advanced_settings.mdx +++ b/api_docs/advanced_settings.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/advancedSettings title: "advancedSettings" image: https://source.unsplash.com/400x175/?github description: API docs for the advancedSettings plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'advancedSettings'] --- import advancedSettingsObj from './advanced_settings.devdocs.json'; diff --git a/api_docs/ai_assistant_management_selection.mdx b/api_docs/ai_assistant_management_selection.mdx index f04c826eef9a3..bc1c1d15d84a6 100644 --- a/api_docs/ai_assistant_management_selection.mdx +++ b/api_docs/ai_assistant_management_selection.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/aiAssistantManagementSelection title: "aiAssistantManagementSelection" image: https://source.unsplash.com/400x175/?github description: API docs for the aiAssistantManagementSelection plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'aiAssistantManagementSelection'] --- import aiAssistantManagementSelectionObj from './ai_assistant_management_selection.devdocs.json'; diff --git a/api_docs/aiops.mdx b/api_docs/aiops.mdx index e73af6333db7e..3aace4647dc51 100644 --- a/api_docs/aiops.mdx +++ b/api_docs/aiops.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/aiops title: "aiops" image: https://source.unsplash.com/400x175/?github description: API docs for the aiops plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'aiops'] --- import aiopsObj from './aiops.devdocs.json'; diff --git a/api_docs/alerting.mdx b/api_docs/alerting.mdx index 9903181b6fa6a..e7bd15cb4ae46 100644 --- a/api_docs/alerting.mdx +++ b/api_docs/alerting.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/alerting title: "alerting" image: https://source.unsplash.com/400x175/?github description: API docs for the alerting plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'alerting'] --- import alertingObj from './alerting.devdocs.json'; diff --git a/api_docs/apm.mdx b/api_docs/apm.mdx index b2b1e56b77543..a64ba108febbb 100644 --- a/api_docs/apm.mdx +++ b/api_docs/apm.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/apm title: "apm" image: https://source.unsplash.com/400x175/?github description: API docs for the apm plugin -date: 2024-05-16 +date: 2024-05-17 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 6ed0b95daa8ad..3eb0fb077b621 100644 --- a/api_docs/apm_data_access.mdx +++ b/api_docs/apm_data_access.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/apmDataAccess title: "apmDataAccess" image: https://source.unsplash.com/400x175/?github description: API docs for the apmDataAccess plugin -date: 2024-05-16 +date: 2024-05-17 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 b872e815d58a7..6a9910f2e96be 100644 --- a/api_docs/asset_manager.mdx +++ b/api_docs/asset_manager.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/assetManager title: "assetManager" image: https://source.unsplash.com/400x175/?github description: API docs for the assetManager plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'assetManager'] --- import assetManagerObj from './asset_manager.devdocs.json'; diff --git a/api_docs/assets_data_access.mdx b/api_docs/assets_data_access.mdx index 43ad957a1dbd6..3fee86c44aa02 100644 --- a/api_docs/assets_data_access.mdx +++ b/api_docs/assets_data_access.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/assetsDataAccess title: "assetsDataAccess" image: https://source.unsplash.com/400x175/?github description: API docs for the assetsDataAccess plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'assetsDataAccess'] --- import assetsDataAccessObj from './assets_data_access.devdocs.json'; diff --git a/api_docs/banners.mdx b/api_docs/banners.mdx index 63df940e00978..c6ab529c57b83 100644 --- a/api_docs/banners.mdx +++ b/api_docs/banners.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/banners title: "banners" image: https://source.unsplash.com/400x175/?github description: API docs for the banners plugin -date: 2024-05-16 +date: 2024-05-17 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 627a850f3d091..c2b9f25fab6bb 100644 --- a/api_docs/bfetch.mdx +++ b/api_docs/bfetch.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/bfetch title: "bfetch" image: https://source.unsplash.com/400x175/?github description: API docs for the bfetch plugin -date: 2024-05-16 +date: 2024-05-17 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 5a1e7b6f469a8..63cc7252173ce 100644 --- a/api_docs/canvas.mdx +++ b/api_docs/canvas.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/canvas title: "canvas" image: https://source.unsplash.com/400x175/?github description: API docs for the canvas plugin -date: 2024-05-16 +date: 2024-05-17 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 9a483c551c21a..6f8b7d61134c7 100644 --- a/api_docs/cases.mdx +++ b/api_docs/cases.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cases title: "cases" image: https://source.unsplash.com/400x175/?github description: API docs for the cases plugin -date: 2024-05-16 +date: 2024-05-17 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 f4e7cb47fcbe8..fe35f776247fc 100644 --- a/api_docs/charts.mdx +++ b/api_docs/charts.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/charts title: "charts" image: https://source.unsplash.com/400x175/?github description: API docs for the charts plugin -date: 2024-05-16 +date: 2024-05-17 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 6aec0b9d434c3..23e62de0022b3 100644 --- a/api_docs/cloud.mdx +++ b/api_docs/cloud.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cloud title: "cloud" image: https://source.unsplash.com/400x175/?github description: API docs for the cloud plugin -date: 2024-05-16 +date: 2024-05-17 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 67c7128daecdf..7feb497f580a1 100644 --- a/api_docs/cloud_data_migration.mdx +++ b/api_docs/cloud_data_migration.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cloudDataMigration title: "cloudDataMigration" image: https://source.unsplash.com/400x175/?github description: API docs for the cloudDataMigration plugin -date: 2024-05-16 +date: 2024-05-17 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 3d7d64c78461a..6b18520da551e 100644 --- a/api_docs/cloud_defend.mdx +++ b/api_docs/cloud_defend.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cloudDefend title: "cloudDefend" image: https://source.unsplash.com/400x175/?github description: API docs for the cloudDefend plugin -date: 2024-05-16 +date: 2024-05-17 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 f9e1df34e94a2..b21626de958e8 100644 --- a/api_docs/cloud_experiments.mdx +++ b/api_docs/cloud_experiments.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cloudExperiments title: "cloudExperiments" image: https://source.unsplash.com/400x175/?github description: API docs for the cloudExperiments plugin -date: 2024-05-16 +date: 2024-05-17 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 0413b5651fbb2..e140dabf9ab3e 100644 --- a/api_docs/cloud_security_posture.mdx +++ b/api_docs/cloud_security_posture.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cloudSecurityPosture title: "cloudSecurityPosture" image: https://source.unsplash.com/400x175/?github description: API docs for the cloudSecurityPosture plugin -date: 2024-05-16 +date: 2024-05-17 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 08883611c4695..59c564b3f8047 100644 --- a/api_docs/console.mdx +++ b/api_docs/console.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/console title: "console" image: https://source.unsplash.com/400x175/?github description: API docs for the console plugin -date: 2024-05-16 +date: 2024-05-17 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 15204bfbaaef6..6116675bb8397 100644 --- a/api_docs/content_management.mdx +++ b/api_docs/content_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/contentManagement title: "contentManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the contentManagement plugin -date: 2024-05-16 +date: 2024-05-17 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 ccd3afd2d7b93..c21fd05767f82 100644 --- a/api_docs/controls.mdx +++ b/api_docs/controls.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/controls title: "controls" image: https://source.unsplash.com/400x175/?github description: API docs for the controls plugin -date: 2024-05-16 +date: 2024-05-17 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 fae2434757ca3..57bc015bc7f73 100644 --- a/api_docs/custom_integrations.mdx +++ b/api_docs/custom_integrations.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/customIntegrations title: "customIntegrations" image: https://source.unsplash.com/400x175/?github description: API docs for the customIntegrations plugin -date: 2024-05-16 +date: 2024-05-17 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 f583cf499cd61..9f709be16a1c4 100644 --- a/api_docs/dashboard.mdx +++ b/api_docs/dashboard.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dashboard title: "dashboard" image: https://source.unsplash.com/400x175/?github description: API docs for the dashboard plugin -date: 2024-05-16 +date: 2024-05-17 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 41def7fc2c39a..6be582e182c80 100644 --- a/api_docs/dashboard_enhanced.mdx +++ b/api_docs/dashboard_enhanced.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dashboardEnhanced title: "dashboardEnhanced" image: https://source.unsplash.com/400x175/?github description: API docs for the dashboardEnhanced plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dashboardEnhanced'] --- import dashboardEnhancedObj from './dashboard_enhanced.devdocs.json'; diff --git a/api_docs/data.mdx b/api_docs/data.mdx index 3460a1db5878c..7e8e9eed0172e 100644 --- a/api_docs/data.mdx +++ b/api_docs/data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/data title: "data" image: https://source.unsplash.com/400x175/?github description: API docs for the data plugin -date: 2024-05-16 +date: 2024-05-17 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 814f2e6e33409..4cb3068d7056a 100644 --- a/api_docs/data_query.mdx +++ b/api_docs/data_query.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/data-query title: "data.query" image: https://source.unsplash.com/400x175/?github description: API docs for the data.query plugin -date: 2024-05-16 +date: 2024-05-17 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 7816b8061baa8..f69f1c34659a9 100644 --- a/api_docs/data_search.mdx +++ b/api_docs/data_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/data-search title: "data.search" image: https://source.unsplash.com/400x175/?github description: API docs for the data.search plugin -date: 2024-05-16 +date: 2024-05-17 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 357d0c5ec4331..31b7853e199cd 100644 --- a/api_docs/data_view_editor.mdx +++ b/api_docs/data_view_editor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataViewEditor title: "dataViewEditor" image: https://source.unsplash.com/400x175/?github description: API docs for the dataViewEditor plugin -date: 2024-05-16 +date: 2024-05-17 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 af308874cf2f5..e7837b9a482cb 100644 --- a/api_docs/data_view_field_editor.mdx +++ b/api_docs/data_view_field_editor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataViewFieldEditor title: "dataViewFieldEditor" image: https://source.unsplash.com/400x175/?github description: API docs for the dataViewFieldEditor plugin -date: 2024-05-16 +date: 2024-05-17 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 9297b18e77dba..936c8ac9463bc 100644 --- a/api_docs/data_view_management.mdx +++ b/api_docs/data_view_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataViewManagement title: "dataViewManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the dataViewManagement plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataViewManagement'] --- import dataViewManagementObj from './data_view_management.devdocs.json'; diff --git a/api_docs/data_views.mdx b/api_docs/data_views.mdx index 49f3fa11de8e3..d9f103a31e961 100644 --- a/api_docs/data_views.mdx +++ b/api_docs/data_views.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataViews title: "dataViews" image: https://source.unsplash.com/400x175/?github description: API docs for the dataViews plugin -date: 2024-05-16 +date: 2024-05-17 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 8894797458689..3aa500f2d848e 100644 --- a/api_docs/data_visualizer.mdx +++ b/api_docs/data_visualizer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataVisualizer title: "dataVisualizer" image: https://source.unsplash.com/400x175/?github description: API docs for the dataVisualizer plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataVisualizer'] --- import dataVisualizerObj from './data_visualizer.devdocs.json'; diff --git a/api_docs/dataset_quality.mdx b/api_docs/dataset_quality.mdx index 611341551695d..1fbe2ddba8870 100644 --- a/api_docs/dataset_quality.mdx +++ b/api_docs/dataset_quality.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/datasetQuality title: "datasetQuality" image: https://source.unsplash.com/400x175/?github description: API docs for the datasetQuality plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'datasetQuality'] --- import datasetQualityObj from './dataset_quality.devdocs.json'; diff --git a/api_docs/deprecations_by_api.mdx b/api_docs/deprecations_by_api.mdx index a75ee0249320a..3484b1ce59e17 100644 --- a/api_docs/deprecations_by_api.mdx +++ b/api_docs/deprecations_by_api.mdx @@ -7,7 +7,7 @@ id: kibDevDocsDeprecationsByApi slug: /kibana-dev-docs/api-meta/deprecated-api-list-by-api title: Deprecated API usage by API description: A list of deprecated APIs, which plugins are still referencing them, and when they need to be removed by. -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- diff --git a/api_docs/deprecations_by_plugin.mdx b/api_docs/deprecations_by_plugin.mdx index 6d48bf1b4664b..d3e015c7dfb5e 100644 --- a/api_docs/deprecations_by_plugin.mdx +++ b/api_docs/deprecations_by_plugin.mdx @@ -7,7 +7,7 @@ id: kibDevDocsDeprecationsByPlugin slug: /kibana-dev-docs/api-meta/deprecated-api-list-by-plugin title: Deprecated API usage by plugin description: A list of deprecated APIs, which plugins are still referencing them, and when they need to be removed by. -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- diff --git a/api_docs/deprecations_by_team.mdx b/api_docs/deprecations_by_team.mdx index 2ad775a309d1e..2f894b503ca2e 100644 --- a/api_docs/deprecations_by_team.mdx +++ b/api_docs/deprecations_by_team.mdx @@ -7,7 +7,7 @@ id: kibDevDocsDeprecationsDueByTeam slug: /kibana-dev-docs/api-meta/deprecations-due-by-team title: Deprecated APIs due to be removed, by team description: Lists the teams that are referencing deprecated APIs with a remove by date. -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- diff --git a/api_docs/dev_tools.mdx b/api_docs/dev_tools.mdx index b1e08d753d260..c5d5c207bb7e5 100644 --- a/api_docs/dev_tools.mdx +++ b/api_docs/dev_tools.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/devTools title: "devTools" image: https://source.unsplash.com/400x175/?github description: API docs for the devTools plugin -date: 2024-05-16 +date: 2024-05-17 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 a51c6e121bc7c..a573d3acffed7 100644 --- a/api_docs/discover.mdx +++ b/api_docs/discover.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/discover title: "discover" image: https://source.unsplash.com/400x175/?github description: API docs for the discover plugin -date: 2024-05-16 +date: 2024-05-17 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 941e41441a33c..39a7df34b14a9 100644 --- a/api_docs/discover_enhanced.mdx +++ b/api_docs/discover_enhanced.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/discoverEnhanced title: "discoverEnhanced" image: https://source.unsplash.com/400x175/?github description: API docs for the discoverEnhanced plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'discoverEnhanced'] --- import discoverEnhancedObj from './discover_enhanced.devdocs.json'; diff --git a/api_docs/discover_shared.mdx b/api_docs/discover_shared.mdx index baf360a03c07e..9bb1f8432c587 100644 --- a/api_docs/discover_shared.mdx +++ b/api_docs/discover_shared.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/discoverShared title: "discoverShared" image: https://source.unsplash.com/400x175/?github description: API docs for the discoverShared plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'discoverShared'] --- import discoverSharedObj from './discover_shared.devdocs.json'; diff --git a/api_docs/ecs_data_quality_dashboard.mdx b/api_docs/ecs_data_quality_dashboard.mdx index 53b45384bf92f..6f35f8bcd50ff 100644 --- a/api_docs/ecs_data_quality_dashboard.mdx +++ b/api_docs/ecs_data_quality_dashboard.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/ecsDataQualityDashboard title: "ecsDataQualityDashboard" image: https://source.unsplash.com/400x175/?github description: API docs for the ecsDataQualityDashboard plugin -date: 2024-05-16 +date: 2024-05-17 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 c44e9b4170178..d19fec0143b78 100644 --- a/api_docs/elastic_assistant.mdx +++ b/api_docs/elastic_assistant.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/elasticAssistant title: "elasticAssistant" image: https://source.unsplash.com/400x175/?github description: API docs for the elasticAssistant plugin -date: 2024-05-16 +date: 2024-05-17 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 66e0d04cfa183..31852010bdf93 100644 --- a/api_docs/embeddable.mdx +++ b/api_docs/embeddable.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/embeddable title: "embeddable" image: https://source.unsplash.com/400x175/?github description: API docs for the embeddable plugin -date: 2024-05-16 +date: 2024-05-17 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 04015ef4a968d..8b5df61a78310 100644 --- a/api_docs/embeddable_enhanced.mdx +++ b/api_docs/embeddable_enhanced.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/embeddableEnhanced title: "embeddableEnhanced" image: https://source.unsplash.com/400x175/?github description: API docs for the embeddableEnhanced plugin -date: 2024-05-16 +date: 2024-05-17 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 5f50b6d2a374f..f873b8b7ea452 100644 --- a/api_docs/encrypted_saved_objects.mdx +++ b/api_docs/encrypted_saved_objects.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/encryptedSavedObjects title: "encryptedSavedObjects" image: https://source.unsplash.com/400x175/?github description: API docs for the encryptedSavedObjects plugin -date: 2024-05-16 +date: 2024-05-17 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 a56395e3551fd..12f63298f1e8a 100644 --- a/api_docs/enterprise_search.mdx +++ b/api_docs/enterprise_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/enterpriseSearch title: "enterpriseSearch" image: https://source.unsplash.com/400x175/?github description: API docs for the enterpriseSearch plugin -date: 2024-05-16 +date: 2024-05-17 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 350d16f962335..38f793e6e3cf3 100644 --- a/api_docs/es_ui_shared.mdx +++ b/api_docs/es_ui_shared.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/esUiShared title: "esUiShared" image: https://source.unsplash.com/400x175/?github description: API docs for the esUiShared plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'esUiShared'] --- import esUiSharedObj from './es_ui_shared.devdocs.json'; diff --git a/api_docs/event_annotation.mdx b/api_docs/event_annotation.mdx index 1dc957e6d2d6a..4b58558077372 100644 --- a/api_docs/event_annotation.mdx +++ b/api_docs/event_annotation.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/eventAnnotation title: "eventAnnotation" image: https://source.unsplash.com/400x175/?github description: API docs for the eventAnnotation plugin -date: 2024-05-16 +date: 2024-05-17 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 b60e428341af6..c4e36759ebcb0 100644 --- a/api_docs/event_annotation_listing.mdx +++ b/api_docs/event_annotation_listing.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/eventAnnotationListing title: "eventAnnotationListing" image: https://source.unsplash.com/400x175/?github description: API docs for the eventAnnotationListing plugin -date: 2024-05-16 +date: 2024-05-17 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 b63dba1e6cf2e..aa4cac38c3367 100644 --- a/api_docs/event_log.mdx +++ b/api_docs/event_log.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/eventLog title: "eventLog" image: https://source.unsplash.com/400x175/?github description: API docs for the eventLog plugin -date: 2024-05-16 +date: 2024-05-17 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 220f4967a081d..d5c33b0355bfd 100644 --- a/api_docs/exploratory_view.mdx +++ b/api_docs/exploratory_view.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/exploratoryView title: "exploratoryView" image: https://source.unsplash.com/400x175/?github description: API docs for the exploratoryView plugin -date: 2024-05-16 +date: 2024-05-17 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 73045b4468e1e..92fb61102ed82 100644 --- a/api_docs/expression_error.mdx +++ b/api_docs/expression_error.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionError title: "expressionError" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionError plugin -date: 2024-05-16 +date: 2024-05-17 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 61a1d71f765d6..64c30900fea0e 100644 --- a/api_docs/expression_gauge.mdx +++ b/api_docs/expression_gauge.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionGauge title: "expressionGauge" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionGauge plugin -date: 2024-05-16 +date: 2024-05-17 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 523a114e1e2cb..97ce394d13297 100644 --- a/api_docs/expression_heatmap.mdx +++ b/api_docs/expression_heatmap.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionHeatmap title: "expressionHeatmap" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionHeatmap plugin -date: 2024-05-16 +date: 2024-05-17 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 6afb86526b829..f999ef8c264a3 100644 --- a/api_docs/expression_image.mdx +++ b/api_docs/expression_image.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionImage title: "expressionImage" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionImage plugin -date: 2024-05-16 +date: 2024-05-17 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 6ffb985dd5a99..3e85f5c33d4f7 100644 --- a/api_docs/expression_legacy_metric_vis.mdx +++ b/api_docs/expression_legacy_metric_vis.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionLegacyMetricVis title: "expressionLegacyMetricVis" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionLegacyMetricVis plugin -date: 2024-05-16 +date: 2024-05-17 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 980a58c757f0b..f44bd480a43a8 100644 --- a/api_docs/expression_metric.mdx +++ b/api_docs/expression_metric.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionMetric title: "expressionMetric" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionMetric plugin -date: 2024-05-16 +date: 2024-05-17 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 829a73965f30f..9fde2f242ea24 100644 --- a/api_docs/expression_metric_vis.mdx +++ b/api_docs/expression_metric_vis.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionMetricVis title: "expressionMetricVis" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionMetricVis plugin -date: 2024-05-16 +date: 2024-05-17 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 73fd6d03e5ecb..9b2d015678da7 100644 --- a/api_docs/expression_partition_vis.mdx +++ b/api_docs/expression_partition_vis.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionPartitionVis title: "expressionPartitionVis" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionPartitionVis plugin -date: 2024-05-16 +date: 2024-05-17 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 94526867e6148..ee9bed795bece 100644 --- a/api_docs/expression_repeat_image.mdx +++ b/api_docs/expression_repeat_image.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionRepeatImage title: "expressionRepeatImage" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionRepeatImage plugin -date: 2024-05-16 +date: 2024-05-17 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 fa5f044da787a..4ff15f37e6ce1 100644 --- a/api_docs/expression_reveal_image.mdx +++ b/api_docs/expression_reveal_image.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionRevealImage title: "expressionRevealImage" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionRevealImage plugin -date: 2024-05-16 +date: 2024-05-17 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 d9e44a4da3710..ba12b8c7a6dbe 100644 --- a/api_docs/expression_shape.mdx +++ b/api_docs/expression_shape.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionShape title: "expressionShape" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionShape plugin -date: 2024-05-16 +date: 2024-05-17 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 5939e46f6936f..da8162d419510 100644 --- a/api_docs/expression_tagcloud.mdx +++ b/api_docs/expression_tagcloud.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionTagcloud title: "expressionTagcloud" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionTagcloud plugin -date: 2024-05-16 +date: 2024-05-17 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 f5b7aa5cd5845..b365a68b9e3ba 100644 --- a/api_docs/expression_x_y.mdx +++ b/api_docs/expression_x_y.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionXY title: "expressionXY" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionXY plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionXY'] --- import expressionXYObj from './expression_x_y.devdocs.json'; diff --git a/api_docs/expressions.mdx b/api_docs/expressions.mdx index 16e98c2ae7717..24d787922f307 100644 --- a/api_docs/expressions.mdx +++ b/api_docs/expressions.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressions title: "expressions" image: https://source.unsplash.com/400x175/?github description: API docs for the expressions plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressions'] --- import expressionsObj from './expressions.devdocs.json'; diff --git a/api_docs/features.mdx b/api_docs/features.mdx index 6923aa2754f6f..af9e00aea4fa7 100644 --- a/api_docs/features.mdx +++ b/api_docs/features.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/features title: "features" image: https://source.unsplash.com/400x175/?github description: API docs for the features plugin -date: 2024-05-16 +date: 2024-05-17 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 4bf756dd1d889..e28bd87d9bf89 100644 --- a/api_docs/field_formats.mdx +++ b/api_docs/field_formats.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/fieldFormats title: "fieldFormats" image: https://source.unsplash.com/400x175/?github description: API docs for the fieldFormats plugin -date: 2024-05-16 +date: 2024-05-17 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 f5de1a1f85ada..ae49a90838b4f 100644 --- a/api_docs/file_upload.mdx +++ b/api_docs/file_upload.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/fileUpload title: "fileUpload" image: https://source.unsplash.com/400x175/?github description: API docs for the fileUpload plugin -date: 2024-05-16 +date: 2024-05-17 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 182acfe1b6390..bacb2f50b06c8 100644 --- a/api_docs/files.mdx +++ b/api_docs/files.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/files title: "files" image: https://source.unsplash.com/400x175/?github description: API docs for the files plugin -date: 2024-05-16 +date: 2024-05-17 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 a6e62076dc23d..ae74197ed4f54 100644 --- a/api_docs/files_management.mdx +++ b/api_docs/files_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/filesManagement title: "filesManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the filesManagement plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'filesManagement'] --- import filesManagementObj from './files_management.devdocs.json'; diff --git a/api_docs/fleet.mdx b/api_docs/fleet.mdx index b2f676f7a579b..751cbae29e833 100644 --- a/api_docs/fleet.mdx +++ b/api_docs/fleet.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/fleet title: "fleet" image: https://source.unsplash.com/400x175/?github description: API docs for the fleet plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'fleet'] --- import fleetObj from './fleet.devdocs.json'; diff --git a/api_docs/global_search.mdx b/api_docs/global_search.mdx index 671520298f10b..5c7dc5d236ad4 100644 --- a/api_docs/global_search.mdx +++ b/api_docs/global_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/globalSearch title: "globalSearch" image: https://source.unsplash.com/400x175/?github description: API docs for the globalSearch plugin -date: 2024-05-16 +date: 2024-05-17 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 0be56866276c1..ed6a32669c69a 100644 --- a/api_docs/guided_onboarding.mdx +++ b/api_docs/guided_onboarding.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/guidedOnboarding title: "guidedOnboarding" image: https://source.unsplash.com/400x175/?github description: API docs for the guidedOnboarding plugin -date: 2024-05-16 +date: 2024-05-17 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 c4c76a646a278..d926b11b5e58b 100644 --- a/api_docs/home.mdx +++ b/api_docs/home.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/home title: "home" image: https://source.unsplash.com/400x175/?github description: API docs for the home plugin -date: 2024-05-16 +date: 2024-05-17 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 226c0c9d79faa..3b22ff101a23f 100644 --- a/api_docs/image_embeddable.mdx +++ b/api_docs/image_embeddable.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/imageEmbeddable title: "imageEmbeddable" image: https://source.unsplash.com/400x175/?github description: API docs for the imageEmbeddable plugin -date: 2024-05-16 +date: 2024-05-17 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 ac1ed0d7ef227..b828ecd95544b 100644 --- a/api_docs/index_lifecycle_management.mdx +++ b/api_docs/index_lifecycle_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/indexLifecycleManagement title: "indexLifecycleManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the indexLifecycleManagement plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'indexLifecycleManagement'] --- import indexLifecycleManagementObj from './index_lifecycle_management.devdocs.json'; diff --git a/api_docs/index_management.mdx b/api_docs/index_management.mdx index be5ab07e36a86..b04192c743b00 100644 --- a/api_docs/index_management.mdx +++ b/api_docs/index_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/indexManagement title: "indexManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the indexManagement plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'indexManagement'] --- import indexManagementObj from './index_management.devdocs.json'; diff --git a/api_docs/infra.mdx b/api_docs/infra.mdx index 5deea1da49242..61b4b7618a6c7 100644 --- a/api_docs/infra.mdx +++ b/api_docs/infra.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/infra title: "infra" image: https://source.unsplash.com/400x175/?github description: API docs for the infra plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'infra'] --- import infraObj from './infra.devdocs.json'; diff --git a/api_docs/ingest_pipelines.mdx b/api_docs/ingest_pipelines.mdx index 0c0d2ca29758b..a5715b95db34c 100644 --- a/api_docs/ingest_pipelines.mdx +++ b/api_docs/ingest_pipelines.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/ingestPipelines title: "ingestPipelines" image: https://source.unsplash.com/400x175/?github description: API docs for the ingestPipelines plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'ingestPipelines'] --- import ingestPipelinesObj from './ingest_pipelines.devdocs.json'; diff --git a/api_docs/inspector.mdx b/api_docs/inspector.mdx index 91f4cc6bbec82..c5cd5225f7637 100644 --- a/api_docs/inspector.mdx +++ b/api_docs/inspector.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/inspector title: "inspector" image: https://source.unsplash.com/400x175/?github description: API docs for the inspector plugin -date: 2024-05-16 +date: 2024-05-17 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 e281d483c7394..ddd13e1a073ba 100644 --- a/api_docs/interactive_setup.mdx +++ b/api_docs/interactive_setup.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/interactiveSetup title: "interactiveSetup" image: https://source.unsplash.com/400x175/?github description: API docs for the interactiveSetup plugin -date: 2024-05-16 +date: 2024-05-17 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 484093a43dd35..30f7ce873c9ae 100644 --- a/api_docs/kbn_ace.mdx +++ b/api_docs/kbn_ace.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ace title: "@kbn/ace" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ace plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ace'] --- import kbnAceObj from './kbn_ace.devdocs.json'; diff --git a/api_docs/kbn_actions_types.mdx b/api_docs/kbn_actions_types.mdx index 3dadb854124c5..03d955a3b37de 100644 --- a/api_docs/kbn_actions_types.mdx +++ b/api_docs/kbn_actions_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-actions-types title: "@kbn/actions-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/actions-types plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/actions-types'] --- import kbnActionsTypesObj from './kbn_actions_types.devdocs.json'; diff --git a/api_docs/kbn_aiops_components.mdx b/api_docs/kbn_aiops_components.mdx index b5e1c5457fa94..46642c9d949dc 100644 --- a/api_docs/kbn_aiops_components.mdx +++ b/api_docs/kbn_aiops_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-aiops-components title: "@kbn/aiops-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/aiops-components plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/aiops-components'] --- import kbnAiopsComponentsObj from './kbn_aiops_components.devdocs.json'; diff --git a/api_docs/kbn_aiops_log_pattern_analysis.mdx b/api_docs/kbn_aiops_log_pattern_analysis.mdx index 1f94eddb6a674..6f0457631edbe 100644 --- a/api_docs/kbn_aiops_log_pattern_analysis.mdx +++ b/api_docs/kbn_aiops_log_pattern_analysis.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-aiops-log-pattern-analysis title: "@kbn/aiops-log-pattern-analysis" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/aiops-log-pattern-analysis plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/aiops-log-pattern-analysis'] --- import kbnAiopsLogPatternAnalysisObj from './kbn_aiops_log_pattern_analysis.devdocs.json'; diff --git a/api_docs/kbn_aiops_log_rate_analysis.mdx b/api_docs/kbn_aiops_log_rate_analysis.mdx index 0a2b8d0ffda8b..24fc602af53b6 100644 --- a/api_docs/kbn_aiops_log_rate_analysis.mdx +++ b/api_docs/kbn_aiops_log_rate_analysis.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-aiops-log-rate-analysis title: "@kbn/aiops-log-rate-analysis" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/aiops-log-rate-analysis plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/aiops-log-rate-analysis'] --- import kbnAiopsLogRateAnalysisObj from './kbn_aiops_log_rate_analysis.devdocs.json'; diff --git a/api_docs/kbn_alerting_api_integration_helpers.mdx b/api_docs/kbn_alerting_api_integration_helpers.mdx index c80416028ed38..2670f7c9dd54a 100644 --- a/api_docs/kbn_alerting_api_integration_helpers.mdx +++ b/api_docs/kbn_alerting_api_integration_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-alerting-api-integration-helpers title: "@kbn/alerting-api-integration-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/alerting-api-integration-helpers plugin -date: 2024-05-16 +date: 2024-05-17 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 1f9abea4f1533..0cc112d0e9d9d 100644 --- a/api_docs/kbn_alerting_state_types.mdx +++ b/api_docs/kbn_alerting_state_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-alerting-state-types title: "@kbn/alerting-state-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/alerting-state-types plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/alerting-state-types'] --- import kbnAlertingStateTypesObj from './kbn_alerting_state_types.devdocs.json'; diff --git a/api_docs/kbn_alerting_types.mdx b/api_docs/kbn_alerting_types.mdx index 5451c5ddcd328..f2d2d22d9d8e7 100644 --- a/api_docs/kbn_alerting_types.mdx +++ b/api_docs/kbn_alerting_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-alerting-types title: "@kbn/alerting-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/alerting-types plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/alerting-types'] --- import kbnAlertingTypesObj from './kbn_alerting_types.devdocs.json'; diff --git a/api_docs/kbn_alerts_as_data_utils.mdx b/api_docs/kbn_alerts_as_data_utils.mdx index 22579c3f822d2..7732611408b01 100644 --- a/api_docs/kbn_alerts_as_data_utils.mdx +++ b/api_docs/kbn_alerts_as_data_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-alerts-as-data-utils title: "@kbn/alerts-as-data-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/alerts-as-data-utils plugin -date: 2024-05-16 +date: 2024-05-17 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 41281828da834..8d6ebe5c7762f 100644 --- a/api_docs/kbn_alerts_ui_shared.mdx +++ b/api_docs/kbn_alerts_ui_shared.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-alerts-ui-shared title: "@kbn/alerts-ui-shared" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/alerts-ui-shared plugin -date: 2024-05-16 +date: 2024-05-17 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 167d70babc516..9fcffd5e7be8b 100644 --- a/api_docs/kbn_analytics.mdx +++ b/api_docs/kbn_analytics.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics title: "@kbn/analytics" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics'] --- import kbnAnalyticsObj from './kbn_analytics.devdocs.json'; diff --git a/api_docs/kbn_analytics_client.mdx b/api_docs/kbn_analytics_client.mdx index 8af754a8a8134..5a88ed83b0aba 100644 --- a/api_docs/kbn_analytics_client.mdx +++ b/api_docs/kbn_analytics_client.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-client title: "@kbn/analytics-client" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-client plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-client'] --- import kbnAnalyticsClientObj from './kbn_analytics_client.devdocs.json'; diff --git a/api_docs/kbn_analytics_collection_utils.mdx b/api_docs/kbn_analytics_collection_utils.mdx index 4bd2e6f8f9de8..81601781c2317 100644 --- a/api_docs/kbn_analytics_collection_utils.mdx +++ b/api_docs/kbn_analytics_collection_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-collection-utils title: "@kbn/analytics-collection-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-collection-utils plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-collection-utils'] --- import kbnAnalyticsCollectionUtilsObj from './kbn_analytics_collection_utils.devdocs.json'; diff --git a/api_docs/kbn_analytics_shippers_elastic_v3_browser.mdx b/api_docs/kbn_analytics_shippers_elastic_v3_browser.mdx index 5e94d8b84521b..0d56eae4685f7 100644 --- a/api_docs/kbn_analytics_shippers_elastic_v3_browser.mdx +++ b/api_docs/kbn_analytics_shippers_elastic_v3_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-shippers-elastic-v3-browser title: "@kbn/analytics-shippers-elastic-v3-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-shippers-elastic-v3-browser plugin -date: 2024-05-16 +date: 2024-05-17 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 b7f15489d259b..f786c68a5ff22 100644 --- a/api_docs/kbn_analytics_shippers_elastic_v3_common.mdx +++ b/api_docs/kbn_analytics_shippers_elastic_v3_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-shippers-elastic-v3-common title: "@kbn/analytics-shippers-elastic-v3-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-shippers-elastic-v3-common plugin -date: 2024-05-16 +date: 2024-05-17 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 778d494d098d6..9fc226fb8f7cc 100644 --- a/api_docs/kbn_analytics_shippers_elastic_v3_server.mdx +++ b/api_docs/kbn_analytics_shippers_elastic_v3_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-shippers-elastic-v3-server title: "@kbn/analytics-shippers-elastic-v3-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-shippers-elastic-v3-server plugin -date: 2024-05-16 +date: 2024-05-17 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 e74508d4deb8d..f32cc8f9bd387 100644 --- a/api_docs/kbn_analytics_shippers_fullstory.mdx +++ b/api_docs/kbn_analytics_shippers_fullstory.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-shippers-fullstory title: "@kbn/analytics-shippers-fullstory" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-shippers-fullstory plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-shippers-fullstory'] --- import kbnAnalyticsShippersFullstoryObj from './kbn_analytics_shippers_fullstory.devdocs.json'; diff --git a/api_docs/kbn_apm_config_loader.mdx b/api_docs/kbn_apm_config_loader.mdx index 88eefe81fb0e1..e2ea3e17b41fd 100644 --- a/api_docs/kbn_apm_config_loader.mdx +++ b/api_docs/kbn_apm_config_loader.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-apm-config-loader title: "@kbn/apm-config-loader" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/apm-config-loader plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/apm-config-loader'] --- import kbnApmConfigLoaderObj from './kbn_apm_config_loader.devdocs.json'; diff --git a/api_docs/kbn_apm_data_view.mdx b/api_docs/kbn_apm_data_view.mdx index 1d825bbf4cb1c..f8eb7ad7e13ac 100644 --- a/api_docs/kbn_apm_data_view.mdx +++ b/api_docs/kbn_apm_data_view.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-apm-data-view title: "@kbn/apm-data-view" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/apm-data-view plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/apm-data-view'] --- import kbnApmDataViewObj from './kbn_apm_data_view.devdocs.json'; diff --git a/api_docs/kbn_apm_synthtrace.mdx b/api_docs/kbn_apm_synthtrace.mdx index 0d07b1a2e3948..a36fffb38f5ac 100644 --- a/api_docs/kbn_apm_synthtrace.mdx +++ b/api_docs/kbn_apm_synthtrace.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-apm-synthtrace title: "@kbn/apm-synthtrace" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/apm-synthtrace plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/apm-synthtrace'] --- import kbnApmSynthtraceObj from './kbn_apm_synthtrace.devdocs.json'; diff --git a/api_docs/kbn_apm_synthtrace_client.devdocs.json b/api_docs/kbn_apm_synthtrace_client.devdocs.json index 8b1bb3e1fbd0f..935496013d4fc 100644 --- a/api_docs/kbn_apm_synthtrace_client.devdocs.json +++ b/api_docs/kbn_apm_synthtrace_client.devdocs.json @@ -2632,7 +2632,9 @@ " | ", "PodMetricsDocument", " | ", - "ContainerMetricsDocument" + "DockerContainerMetricsDocument", + " | ", + "K8sContainerMetricsDocument" ], "path": "packages/kbn-apm-synthtrace-client/src/lib/infra/index.ts", "deprecated": false, @@ -2926,14 +2928,43 @@ }, { "parentPluginId": "@kbn/apm-synthtrace-client", - "id": "def-common.infra.container", + "id": "def-common.infra.dockerContainer", + "type": "Function", + "tags": [], + "label": "dockerContainer", + "description": [], + "signature": [ + "(id: string) => ", + "DockerContainer" + ], + "path": "packages/kbn-apm-synthtrace-client/src/lib/infra/index.ts", + "deprecated": false, + "trackAdoption": false, + "returnComment": [], + "children": [ + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.infra.dockerContainer.$1", + "type": "string", + "tags": [], + "label": "id", + "description": [], + "path": "packages/kbn-apm-synthtrace-client/src/lib/infra/docker_container.ts", + "deprecated": false, + "trackAdoption": false + } + ] + }, + { + "parentPluginId": "@kbn/apm-synthtrace-client", + "id": "def-common.infra.k8sContainer", "type": "Function", "tags": [], - "label": "container", + "label": "k8sContainer", "description": [], "signature": [ "(id: string, uid: string, nodeName: string) => ", - "Container" + "K8sContainer" ], "path": "packages/kbn-apm-synthtrace-client/src/lib/infra/index.ts", "deprecated": false, @@ -2942,34 +2973,34 @@ "children": [ { "parentPluginId": "@kbn/apm-synthtrace-client", - "id": "def-common.infra.container.$1", + "id": "def-common.infra.k8sContainer.$1", "type": "string", "tags": [], "label": "id", "description": [], - "path": "packages/kbn-apm-synthtrace-client/src/lib/infra/container.ts", + "path": "packages/kbn-apm-synthtrace-client/src/lib/infra/k8s_container.ts", "deprecated": false, "trackAdoption": false }, { "parentPluginId": "@kbn/apm-synthtrace-client", - "id": "def-common.infra.container.$2", + "id": "def-common.infra.k8sContainer.$2", "type": "string", "tags": [], "label": "uid", "description": [], - "path": "packages/kbn-apm-synthtrace-client/src/lib/infra/container.ts", + "path": "packages/kbn-apm-synthtrace-client/src/lib/infra/k8s_container.ts", "deprecated": false, "trackAdoption": false }, { "parentPluginId": "@kbn/apm-synthtrace-client", - "id": "def-common.infra.container.$3", + "id": "def-common.infra.k8sContainer.$3", "type": "string", "tags": [], "label": "nodeName", "description": [], - "path": "packages/kbn-apm-synthtrace-client/src/lib/infra/container.ts", + "path": "packages/kbn-apm-synthtrace-client/src/lib/infra/k8s_container.ts", "deprecated": false, "trackAdoption": false } diff --git a/api_docs/kbn_apm_synthtrace_client.mdx b/api_docs/kbn_apm_synthtrace_client.mdx index f7b8e921503ca..924b71a3c3b58 100644 --- a/api_docs/kbn_apm_synthtrace_client.mdx +++ b/api_docs/kbn_apm_synthtrace_client.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-apm-synthtrace-client title: "@kbn/apm-synthtrace-client" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/apm-synthtrace-client plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/apm-synthtrace-client'] --- import kbnApmSynthtraceClientObj from './kbn_apm_synthtrace_client.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/obs-ux-infra_services-team](https://github.com/orgs/elastic/te | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 191 | 0 | 191 | 28 | +| 193 | 0 | 193 | 30 | ## Common diff --git a/api_docs/kbn_apm_utils.mdx b/api_docs/kbn_apm_utils.mdx index 26a1b65232fb1..34610cc4c7edc 100644 --- a/api_docs/kbn_apm_utils.mdx +++ b/api_docs/kbn_apm_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-apm-utils title: "@kbn/apm-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/apm-utils plugin -date: 2024-05-16 +date: 2024-05-17 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 313225279f097..50e6cc3ef7c2f 100644 --- a/api_docs/kbn_axe_config.mdx +++ b/api_docs/kbn_axe_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-axe-config title: "@kbn/axe-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/axe-config plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/axe-config'] --- import kbnAxeConfigObj from './kbn_axe_config.devdocs.json'; diff --git a/api_docs/kbn_bfetch_error.mdx b/api_docs/kbn_bfetch_error.mdx index dd189e1f404ab..5cd5ec708a014 100644 --- a/api_docs/kbn_bfetch_error.mdx +++ b/api_docs/kbn_bfetch_error.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-bfetch-error title: "@kbn/bfetch-error" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/bfetch-error plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/bfetch-error'] --- import kbnBfetchErrorObj from './kbn_bfetch_error.devdocs.json'; diff --git a/api_docs/kbn_calculate_auto.mdx b/api_docs/kbn_calculate_auto.mdx index 4f34e2d02b964..7afaf74f92c67 100644 --- a/api_docs/kbn_calculate_auto.mdx +++ b/api_docs/kbn_calculate_auto.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-calculate-auto title: "@kbn/calculate-auto" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/calculate-auto plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/calculate-auto'] --- import kbnCalculateAutoObj from './kbn_calculate_auto.devdocs.json'; diff --git a/api_docs/kbn_calculate_width_from_char_count.mdx b/api_docs/kbn_calculate_width_from_char_count.mdx index 78998c799a362..7851e09d50cd7 100644 --- a/api_docs/kbn_calculate_width_from_char_count.mdx +++ b/api_docs/kbn_calculate_width_from_char_count.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-calculate-width-from-char-count title: "@kbn/calculate-width-from-char-count" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/calculate-width-from-char-count plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/calculate-width-from-char-count'] --- import kbnCalculateWidthFromCharCountObj from './kbn_calculate_width_from_char_count.devdocs.json'; diff --git a/api_docs/kbn_cases_components.mdx b/api_docs/kbn_cases_components.mdx index 90d5c01339d3c..83778f073195a 100644 --- a/api_docs/kbn_cases_components.mdx +++ b/api_docs/kbn_cases_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-cases-components title: "@kbn/cases-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/cases-components plugin -date: 2024-05-16 +date: 2024-05-17 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 27c57d4fcc10e..87e310c222a71 100644 --- a/api_docs/kbn_cell_actions.mdx +++ b/api_docs/kbn_cell_actions.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-cell-actions title: "@kbn/cell-actions" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/cell-actions plugin -date: 2024-05-16 +date: 2024-05-17 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 50714ad160bd6..e7d049233b283 100644 --- a/api_docs/kbn_chart_expressions_common.mdx +++ b/api_docs/kbn_chart_expressions_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-chart-expressions-common title: "@kbn/chart-expressions-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/chart-expressions-common plugin -date: 2024-05-16 +date: 2024-05-17 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 c51b6f749cd2c..2c0ebb2d261c8 100644 --- a/api_docs/kbn_chart_icons.mdx +++ b/api_docs/kbn_chart_icons.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-chart-icons title: "@kbn/chart-icons" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/chart-icons plugin -date: 2024-05-16 +date: 2024-05-17 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 86d11ebad8aad..52da0031d1edd 100644 --- a/api_docs/kbn_ci_stats_core.mdx +++ b/api_docs/kbn_ci_stats_core.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ci-stats-core title: "@kbn/ci-stats-core" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ci-stats-core plugin -date: 2024-05-16 +date: 2024-05-17 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 6dc2a213ae99b..f79e1e4960232 100644 --- a/api_docs/kbn_ci_stats_performance_metrics.mdx +++ b/api_docs/kbn_ci_stats_performance_metrics.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ci-stats-performance-metrics title: "@kbn/ci-stats-performance-metrics" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ci-stats-performance-metrics plugin -date: 2024-05-16 +date: 2024-05-17 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 b57dbea34a842..d1ca6d47206ab 100644 --- a/api_docs/kbn_ci_stats_reporter.mdx +++ b/api_docs/kbn_ci_stats_reporter.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ci-stats-reporter title: "@kbn/ci-stats-reporter" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ci-stats-reporter plugin -date: 2024-05-16 +date: 2024-05-17 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 e582564a36996..832c857a3c70a 100644 --- a/api_docs/kbn_cli_dev_mode.mdx +++ b/api_docs/kbn_cli_dev_mode.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-cli-dev-mode title: "@kbn/cli-dev-mode" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/cli-dev-mode plugin -date: 2024-05-16 +date: 2024-05-17 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 4297a71a9ec2e..e8c7440314002 100644 --- a/api_docs/kbn_code_editor.mdx +++ b/api_docs/kbn_code_editor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-code-editor title: "@kbn/code-editor" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/code-editor plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/code-editor'] --- import kbnCodeEditorObj from './kbn_code_editor.devdocs.json'; diff --git a/api_docs/kbn_code_editor_mock.mdx b/api_docs/kbn_code_editor_mock.mdx index 44fcdb779f497..23f3964423438 100644 --- a/api_docs/kbn_code_editor_mock.mdx +++ b/api_docs/kbn_code_editor_mock.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-code-editor-mock title: "@kbn/code-editor-mock" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/code-editor-mock plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/code-editor-mock'] --- import kbnCodeEditorMockObj from './kbn_code_editor_mock.devdocs.json'; diff --git a/api_docs/kbn_code_owners.mdx b/api_docs/kbn_code_owners.mdx index ac9e07ebee19e..864375cf36638 100644 --- a/api_docs/kbn_code_owners.mdx +++ b/api_docs/kbn_code_owners.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-code-owners title: "@kbn/code-owners" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/code-owners plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/code-owners'] --- import kbnCodeOwnersObj from './kbn_code_owners.devdocs.json'; diff --git a/api_docs/kbn_coloring.mdx b/api_docs/kbn_coloring.mdx index 6148173599693..075b3a5ace7a1 100644 --- a/api_docs/kbn_coloring.mdx +++ b/api_docs/kbn_coloring.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-coloring title: "@kbn/coloring" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/coloring plugin -date: 2024-05-16 +date: 2024-05-17 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 dc387b234aea5..53a6425bbae11 100644 --- a/api_docs/kbn_config.mdx +++ b/api_docs/kbn_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-config title: "@kbn/config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/config plugin -date: 2024-05-16 +date: 2024-05-17 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 fe91e549c307a..ec1939de9dd08 100644 --- a/api_docs/kbn_config_mocks.mdx +++ b/api_docs/kbn_config_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-config-mocks title: "@kbn/config-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/config-mocks plugin -date: 2024-05-16 +date: 2024-05-17 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 3dce17613c957..f52378ce30825 100644 --- a/api_docs/kbn_config_schema.mdx +++ b/api_docs/kbn_config_schema.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-config-schema title: "@kbn/config-schema" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/config-schema plugin -date: 2024-05-16 +date: 2024-05-17 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 93755213ba306..78a5af84bc23d 100644 --- a/api_docs/kbn_content_management_content_editor.mdx +++ b/api_docs/kbn_content_management_content_editor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-content-management-content-editor title: "@kbn/content-management-content-editor" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/content-management-content-editor plugin -date: 2024-05-16 +date: 2024-05-17 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 4402b754c1272..eb5ad8fe281c2 100644 --- a/api_docs/kbn_content_management_tabbed_table_list_view.mdx +++ b/api_docs/kbn_content_management_tabbed_table_list_view.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-content-management-tabbed-table-list-view title: "@kbn/content-management-tabbed-table-list-view" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/content-management-tabbed-table-list-view plugin -date: 2024-05-16 +date: 2024-05-17 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 d9d45d6991243..39f5af2044f3d 100644 --- a/api_docs/kbn_content_management_table_list_view.mdx +++ b/api_docs/kbn_content_management_table_list_view.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-content-management-table-list-view title: "@kbn/content-management-table-list-view" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/content-management-table-list-view plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/content-management-table-list-view'] --- import kbnContentManagementTableListViewObj from './kbn_content_management_table_list_view.devdocs.json'; diff --git a/api_docs/kbn_content_management_table_list_view_common.mdx b/api_docs/kbn_content_management_table_list_view_common.mdx index e9857b3581be8..5645e2aed47af 100644 --- a/api_docs/kbn_content_management_table_list_view_common.mdx +++ b/api_docs/kbn_content_management_table_list_view_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-content-management-table-list-view-common title: "@kbn/content-management-table-list-view-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/content-management-table-list-view-common plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/content-management-table-list-view-common'] --- import kbnContentManagementTableListViewCommonObj from './kbn_content_management_table_list_view_common.devdocs.json'; diff --git a/api_docs/kbn_content_management_table_list_view_table.mdx b/api_docs/kbn_content_management_table_list_view_table.mdx index 8217caf36ae13..102af47f1424f 100644 --- a/api_docs/kbn_content_management_table_list_view_table.mdx +++ b/api_docs/kbn_content_management_table_list_view_table.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-content-management-table-list-view-table title: "@kbn/content-management-table-list-view-table" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/content-management-table-list-view-table plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/content-management-table-list-view-table'] --- import kbnContentManagementTableListViewTableObj from './kbn_content_management_table_list_view_table.devdocs.json'; diff --git a/api_docs/kbn_content_management_utils.mdx b/api_docs/kbn_content_management_utils.mdx index c7b8b882c2215..debaedfd82209 100644 --- a/api_docs/kbn_content_management_utils.mdx +++ b/api_docs/kbn_content_management_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-content-management-utils title: "@kbn/content-management-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/content-management-utils plugin -date: 2024-05-16 +date: 2024-05-17 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 f0fe7b8c52948..e20b8d790ce59 100644 --- a/api_docs/kbn_core_analytics_browser.mdx +++ b/api_docs/kbn_core_analytics_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-browser title: "@kbn/core-analytics-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-browser plugin -date: 2024-05-16 +date: 2024-05-17 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 e71219c579a22..b0ce2b675bdc7 100644 --- a/api_docs/kbn_core_analytics_browser_internal.mdx +++ b/api_docs/kbn_core_analytics_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-browser-internal title: "@kbn/core-analytics-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-browser-internal plugin -date: 2024-05-16 +date: 2024-05-17 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 eadf7948210a1..58eee0729b485 100644 --- a/api_docs/kbn_core_analytics_browser_mocks.mdx +++ b/api_docs/kbn_core_analytics_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-browser-mocks title: "@kbn/core-analytics-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-browser-mocks plugin -date: 2024-05-16 +date: 2024-05-17 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 bf2762d21b99e..287e16f66f98c 100644 --- a/api_docs/kbn_core_analytics_server.mdx +++ b/api_docs/kbn_core_analytics_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-server title: "@kbn/core-analytics-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-server plugin -date: 2024-05-16 +date: 2024-05-17 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 75b6528cb9b2f..1d41d6166b9c9 100644 --- a/api_docs/kbn_core_analytics_server_internal.mdx +++ b/api_docs/kbn_core_analytics_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-server-internal title: "@kbn/core-analytics-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-server-internal plugin -date: 2024-05-16 +date: 2024-05-17 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 690edc92ea703..e2fb6d368d8a9 100644 --- a/api_docs/kbn_core_analytics_server_mocks.mdx +++ b/api_docs/kbn_core_analytics_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-server-mocks title: "@kbn/core-analytics-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-server-mocks plugin -date: 2024-05-16 +date: 2024-05-17 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 a689e6fb469dc..2d973e83c6272 100644 --- a/api_docs/kbn_core_application_browser.mdx +++ b/api_docs/kbn_core_application_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-application-browser title: "@kbn/core-application-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-application-browser plugin -date: 2024-05-16 +date: 2024-05-17 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 e9ed2cae9ffca..a12850d472dfa 100644 --- a/api_docs/kbn_core_application_browser_internal.mdx +++ b/api_docs/kbn_core_application_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-application-browser-internal title: "@kbn/core-application-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-application-browser-internal plugin -date: 2024-05-16 +date: 2024-05-17 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 78384126a9f3c..fae52641dd835 100644 --- a/api_docs/kbn_core_application_browser_mocks.mdx +++ b/api_docs/kbn_core_application_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-application-browser-mocks title: "@kbn/core-application-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-application-browser-mocks plugin -date: 2024-05-16 +date: 2024-05-17 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 0071968858c41..145c7dc0bfadd 100644 --- a/api_docs/kbn_core_application_common.mdx +++ b/api_docs/kbn_core_application_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-application-common title: "@kbn/core-application-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-application-common plugin -date: 2024-05-16 +date: 2024-05-17 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 b888233b0643d..2801523677cc4 100644 --- a/api_docs/kbn_core_apps_browser_internal.mdx +++ b/api_docs/kbn_core_apps_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-apps-browser-internal title: "@kbn/core-apps-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-apps-browser-internal plugin -date: 2024-05-16 +date: 2024-05-17 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 92697fa71bb4c..bc570e7bf164e 100644 --- a/api_docs/kbn_core_apps_browser_mocks.mdx +++ b/api_docs/kbn_core_apps_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-apps-browser-mocks title: "@kbn/core-apps-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-apps-browser-mocks plugin -date: 2024-05-16 +date: 2024-05-17 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 d705949c429a4..9b3cbf61aa6ca 100644 --- a/api_docs/kbn_core_apps_server_internal.mdx +++ b/api_docs/kbn_core_apps_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-apps-server-internal title: "@kbn/core-apps-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-apps-server-internal plugin -date: 2024-05-16 +date: 2024-05-17 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 f549850c9770a..7627419367883 100644 --- a/api_docs/kbn_core_base_browser_mocks.mdx +++ b/api_docs/kbn_core_base_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-base-browser-mocks title: "@kbn/core-base-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-base-browser-mocks plugin -date: 2024-05-16 +date: 2024-05-17 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 cd6f3e99ffd46..f08d68804083b 100644 --- a/api_docs/kbn_core_base_common.mdx +++ b/api_docs/kbn_core_base_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-base-common title: "@kbn/core-base-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-base-common plugin -date: 2024-05-16 +date: 2024-05-17 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 a6508dd639ae3..57ce3a2178cb1 100644 --- a/api_docs/kbn_core_base_server_internal.mdx +++ b/api_docs/kbn_core_base_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-base-server-internal title: "@kbn/core-base-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-base-server-internal plugin -date: 2024-05-16 +date: 2024-05-17 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 9e6d1e512012a..d1cf83c623e6e 100644 --- a/api_docs/kbn_core_base_server_mocks.mdx +++ b/api_docs/kbn_core_base_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-base-server-mocks title: "@kbn/core-base-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-base-server-mocks plugin -date: 2024-05-16 +date: 2024-05-17 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 3725941fd9159..7a41e807c96ab 100644 --- a/api_docs/kbn_core_capabilities_browser_mocks.mdx +++ b/api_docs/kbn_core_capabilities_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-capabilities-browser-mocks title: "@kbn/core-capabilities-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-capabilities-browser-mocks plugin -date: 2024-05-16 +date: 2024-05-17 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 069c27e6956ad..a62930001d10f 100644 --- a/api_docs/kbn_core_capabilities_common.mdx +++ b/api_docs/kbn_core_capabilities_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-capabilities-common title: "@kbn/core-capabilities-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-capabilities-common plugin -date: 2024-05-16 +date: 2024-05-17 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 69557c67d6398..952dc0d6c883d 100644 --- a/api_docs/kbn_core_capabilities_server.mdx +++ b/api_docs/kbn_core_capabilities_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-capabilities-server title: "@kbn/core-capabilities-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-capabilities-server plugin -date: 2024-05-16 +date: 2024-05-17 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 1b05c031a3c2a..54891af50baa5 100644 --- a/api_docs/kbn_core_capabilities_server_mocks.mdx +++ b/api_docs/kbn_core_capabilities_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-capabilities-server-mocks title: "@kbn/core-capabilities-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-capabilities-server-mocks plugin -date: 2024-05-16 +date: 2024-05-17 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 2938229af5cf6..6953f7d7d0f4f 100644 --- a/api_docs/kbn_core_chrome_browser.mdx +++ b/api_docs/kbn_core_chrome_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-chrome-browser title: "@kbn/core-chrome-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-chrome-browser plugin -date: 2024-05-16 +date: 2024-05-17 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 55af2a2b04052..b32e5193792ab 100644 --- a/api_docs/kbn_core_chrome_browser_mocks.mdx +++ b/api_docs/kbn_core_chrome_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-chrome-browser-mocks title: "@kbn/core-chrome-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-chrome-browser-mocks plugin -date: 2024-05-16 +date: 2024-05-17 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 20a905c16d1f7..890949aff2242 100644 --- a/api_docs/kbn_core_config_server_internal.mdx +++ b/api_docs/kbn_core_config_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-config-server-internal title: "@kbn/core-config-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-config-server-internal plugin -date: 2024-05-16 +date: 2024-05-17 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 7c5fed8bab505..33d93db3c8073 100644 --- a/api_docs/kbn_core_custom_branding_browser.mdx +++ b/api_docs/kbn_core_custom_branding_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-custom-branding-browser title: "@kbn/core-custom-branding-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-custom-branding-browser plugin -date: 2024-05-16 +date: 2024-05-17 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 daef39e0961f0..53209feb48ce2 100644 --- a/api_docs/kbn_core_custom_branding_browser_internal.mdx +++ b/api_docs/kbn_core_custom_branding_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-custom-branding-browser-internal title: "@kbn/core-custom-branding-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-custom-branding-browser-internal plugin -date: 2024-05-16 +date: 2024-05-17 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 c5118b4045ccb..165ad578c62fc 100644 --- a/api_docs/kbn_core_custom_branding_browser_mocks.mdx +++ b/api_docs/kbn_core_custom_branding_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-custom-branding-browser-mocks title: "@kbn/core-custom-branding-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-custom-branding-browser-mocks plugin -date: 2024-05-16 +date: 2024-05-17 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 16075136e3749..32b06c26014a2 100644 --- a/api_docs/kbn_core_custom_branding_common.mdx +++ b/api_docs/kbn_core_custom_branding_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-custom-branding-common title: "@kbn/core-custom-branding-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-custom-branding-common plugin -date: 2024-05-16 +date: 2024-05-17 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 f1e01b6677e3e..f4d974f9de9c6 100644 --- a/api_docs/kbn_core_custom_branding_server.mdx +++ b/api_docs/kbn_core_custom_branding_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-custom-branding-server title: "@kbn/core-custom-branding-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-custom-branding-server plugin -date: 2024-05-16 +date: 2024-05-17 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 af6e37d34a5c7..be2bf300e3925 100644 --- a/api_docs/kbn_core_custom_branding_server_internal.mdx +++ b/api_docs/kbn_core_custom_branding_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-custom-branding-server-internal title: "@kbn/core-custom-branding-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-custom-branding-server-internal plugin -date: 2024-05-16 +date: 2024-05-17 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 2f77ee18b1d37..aa172000d1049 100644 --- a/api_docs/kbn_core_custom_branding_server_mocks.mdx +++ b/api_docs/kbn_core_custom_branding_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-custom-branding-server-mocks title: "@kbn/core-custom-branding-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-custom-branding-server-mocks plugin -date: 2024-05-16 +date: 2024-05-17 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 0868460e0e143..aa5f0790d8f5f 100644 --- a/api_docs/kbn_core_deprecations_browser.mdx +++ b/api_docs/kbn_core_deprecations_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-browser title: "@kbn/core-deprecations-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-browser plugin -date: 2024-05-16 +date: 2024-05-17 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 510e1180c8b09..eb4c341edb4ff 100644 --- a/api_docs/kbn_core_deprecations_browser_internal.mdx +++ b/api_docs/kbn_core_deprecations_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-browser-internal title: "@kbn/core-deprecations-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-browser-internal plugin -date: 2024-05-16 +date: 2024-05-17 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 c378305c3f22d..f1090608dd2ae 100644 --- a/api_docs/kbn_core_deprecations_browser_mocks.mdx +++ b/api_docs/kbn_core_deprecations_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-browser-mocks title: "@kbn/core-deprecations-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-browser-mocks plugin -date: 2024-05-16 +date: 2024-05-17 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 a0ca24961ac62..baa21e365d46b 100644 --- a/api_docs/kbn_core_deprecations_common.mdx +++ b/api_docs/kbn_core_deprecations_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-common title: "@kbn/core-deprecations-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-common plugin -date: 2024-05-16 +date: 2024-05-17 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 781ef5417f39f..e24d0ef503027 100644 --- a/api_docs/kbn_core_deprecations_server.mdx +++ b/api_docs/kbn_core_deprecations_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-server title: "@kbn/core-deprecations-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-server plugin -date: 2024-05-16 +date: 2024-05-17 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 997c63f4a5ca4..2154818b01d8a 100644 --- a/api_docs/kbn_core_deprecations_server_internal.mdx +++ b/api_docs/kbn_core_deprecations_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-server-internal title: "@kbn/core-deprecations-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-server-internal plugin -date: 2024-05-16 +date: 2024-05-17 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 cdd061bfc78b2..dad4f89e0cccd 100644 --- a/api_docs/kbn_core_deprecations_server_mocks.mdx +++ b/api_docs/kbn_core_deprecations_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-server-mocks title: "@kbn/core-deprecations-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-server-mocks plugin -date: 2024-05-16 +date: 2024-05-17 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 7499cc93a3cc8..2cd5268a964ef 100644 --- a/api_docs/kbn_core_doc_links_browser.mdx +++ b/api_docs/kbn_core_doc_links_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-doc-links-browser title: "@kbn/core-doc-links-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-doc-links-browser plugin -date: 2024-05-16 +date: 2024-05-17 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 745a9e38124e1..b29ce0544b5e3 100644 --- a/api_docs/kbn_core_doc_links_browser_mocks.mdx +++ b/api_docs/kbn_core_doc_links_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-doc-links-browser-mocks title: "@kbn/core-doc-links-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-doc-links-browser-mocks plugin -date: 2024-05-16 +date: 2024-05-17 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 6d91445f12e7c..86c9175ef6d95 100644 --- a/api_docs/kbn_core_doc_links_server.mdx +++ b/api_docs/kbn_core_doc_links_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-doc-links-server title: "@kbn/core-doc-links-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-doc-links-server plugin -date: 2024-05-16 +date: 2024-05-17 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 ccecbcb9385b0..3613ecccc8385 100644 --- a/api_docs/kbn_core_doc_links_server_mocks.mdx +++ b/api_docs/kbn_core_doc_links_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-doc-links-server-mocks title: "@kbn/core-doc-links-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-doc-links-server-mocks plugin -date: 2024-05-16 +date: 2024-05-17 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 8d7fb99524dc8..c40f3fc9c7b2d 100644 --- a/api_docs/kbn_core_elasticsearch_client_server_internal.mdx +++ b/api_docs/kbn_core_elasticsearch_client_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-elasticsearch-client-server-internal title: "@kbn/core-elasticsearch-client-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-elasticsearch-client-server-internal plugin -date: 2024-05-16 +date: 2024-05-17 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 f08650bad383a..7dd24162f9d2e 100644 --- a/api_docs/kbn_core_elasticsearch_client_server_mocks.mdx +++ b/api_docs/kbn_core_elasticsearch_client_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-elasticsearch-client-server-mocks title: "@kbn/core-elasticsearch-client-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-elasticsearch-client-server-mocks plugin -date: 2024-05-16 +date: 2024-05-17 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 31d7dca79e9c5..ebc3b396b431f 100644 --- a/api_docs/kbn_core_elasticsearch_server.mdx +++ b/api_docs/kbn_core_elasticsearch_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-elasticsearch-server title: "@kbn/core-elasticsearch-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-elasticsearch-server plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-elasticsearch-server'] --- import kbnCoreElasticsearchServerObj from './kbn_core_elasticsearch_server.devdocs.json'; diff --git a/api_docs/kbn_core_elasticsearch_server_internal.mdx b/api_docs/kbn_core_elasticsearch_server_internal.mdx index 3bb354475ff7c..1caf9502145c0 100644 --- a/api_docs/kbn_core_elasticsearch_server_internal.mdx +++ b/api_docs/kbn_core_elasticsearch_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-elasticsearch-server-internal title: "@kbn/core-elasticsearch-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-elasticsearch-server-internal plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-elasticsearch-server-internal'] --- import kbnCoreElasticsearchServerInternalObj from './kbn_core_elasticsearch_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_elasticsearch_server_mocks.mdx b/api_docs/kbn_core_elasticsearch_server_mocks.mdx index 0906d107519e0..e164374cc04cf 100644 --- a/api_docs/kbn_core_elasticsearch_server_mocks.mdx +++ b/api_docs/kbn_core_elasticsearch_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-elasticsearch-server-mocks title: "@kbn/core-elasticsearch-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-elasticsearch-server-mocks plugin -date: 2024-05-16 +date: 2024-05-17 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 c55c038bc5a74..eec2b260e2a6e 100644 --- a/api_docs/kbn_core_environment_server_internal.mdx +++ b/api_docs/kbn_core_environment_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-environment-server-internal title: "@kbn/core-environment-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-environment-server-internal plugin -date: 2024-05-16 +date: 2024-05-17 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 84bcfe562c0d8..c3bda240aeb4e 100644 --- a/api_docs/kbn_core_environment_server_mocks.mdx +++ b/api_docs/kbn_core_environment_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-environment-server-mocks title: "@kbn/core-environment-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-environment-server-mocks plugin -date: 2024-05-16 +date: 2024-05-17 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 03350ba3d06a4..fe4fab1c4dabb 100644 --- a/api_docs/kbn_core_execution_context_browser.mdx +++ b/api_docs/kbn_core_execution_context_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-browser title: "@kbn/core-execution-context-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-browser plugin -date: 2024-05-16 +date: 2024-05-17 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 8950e76ac4739..dd7325027af17 100644 --- a/api_docs/kbn_core_execution_context_browser_internal.mdx +++ b/api_docs/kbn_core_execution_context_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-browser-internal title: "@kbn/core-execution-context-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-browser-internal plugin -date: 2024-05-16 +date: 2024-05-17 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 32aaeea7ed062..197e043669fa3 100644 --- a/api_docs/kbn_core_execution_context_browser_mocks.mdx +++ b/api_docs/kbn_core_execution_context_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-browser-mocks title: "@kbn/core-execution-context-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-browser-mocks plugin -date: 2024-05-16 +date: 2024-05-17 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 508e18c979d2b..ec0e3fddb3eaa 100644 --- a/api_docs/kbn_core_execution_context_common.mdx +++ b/api_docs/kbn_core_execution_context_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-common title: "@kbn/core-execution-context-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-common plugin -date: 2024-05-16 +date: 2024-05-17 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 bd6a6c7b30ce1..d1abda6c5e842 100644 --- a/api_docs/kbn_core_execution_context_server.mdx +++ b/api_docs/kbn_core_execution_context_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-server title: "@kbn/core-execution-context-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-server plugin -date: 2024-05-16 +date: 2024-05-17 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 824ceb81a22d3..466c3f1a1756a 100644 --- a/api_docs/kbn_core_execution_context_server_internal.mdx +++ b/api_docs/kbn_core_execution_context_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-server-internal title: "@kbn/core-execution-context-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-server-internal plugin -date: 2024-05-16 +date: 2024-05-17 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 fe462fd32358d..22b77ef36f28b 100644 --- a/api_docs/kbn_core_execution_context_server_mocks.mdx +++ b/api_docs/kbn_core_execution_context_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-server-mocks title: "@kbn/core-execution-context-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-server-mocks plugin -date: 2024-05-16 +date: 2024-05-17 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 bd3e38f873af2..676cacaade35c 100644 --- a/api_docs/kbn_core_fatal_errors_browser.mdx +++ b/api_docs/kbn_core_fatal_errors_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-fatal-errors-browser title: "@kbn/core-fatal-errors-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-fatal-errors-browser plugin -date: 2024-05-16 +date: 2024-05-17 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 71a814a919c61..9ea657253981e 100644 --- a/api_docs/kbn_core_fatal_errors_browser_mocks.mdx +++ b/api_docs/kbn_core_fatal_errors_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-fatal-errors-browser-mocks title: "@kbn/core-fatal-errors-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-fatal-errors-browser-mocks plugin -date: 2024-05-16 +date: 2024-05-17 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 74d54f95b306f..c51d6a3cf4edf 100644 --- a/api_docs/kbn_core_http_browser.mdx +++ b/api_docs/kbn_core_http_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-browser title: "@kbn/core-http-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-browser plugin -date: 2024-05-16 +date: 2024-05-17 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 d4e471d6c15c1..9865b20124ab3 100644 --- a/api_docs/kbn_core_http_browser_internal.mdx +++ b/api_docs/kbn_core_http_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-browser-internal title: "@kbn/core-http-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-browser-internal plugin -date: 2024-05-16 +date: 2024-05-17 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 13fc9e5b743ad..3be1dda990d74 100644 --- a/api_docs/kbn_core_http_browser_mocks.mdx +++ b/api_docs/kbn_core_http_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-browser-mocks title: "@kbn/core-http-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-browser-mocks plugin -date: 2024-05-16 +date: 2024-05-17 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 9cb9cc0201c09..4844bcfeefb43 100644 --- a/api_docs/kbn_core_http_common.mdx +++ b/api_docs/kbn_core_http_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-common title: "@kbn/core-http-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-common plugin -date: 2024-05-16 +date: 2024-05-17 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 08190d1483573..f8aaf5607e0a8 100644 --- a/api_docs/kbn_core_http_context_server_mocks.mdx +++ b/api_docs/kbn_core_http_context_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-context-server-mocks title: "@kbn/core-http-context-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-context-server-mocks plugin -date: 2024-05-16 +date: 2024-05-17 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 b2e5c49847b70..5d6cee9bc751a 100644 --- a/api_docs/kbn_core_http_request_handler_context_server.mdx +++ b/api_docs/kbn_core_http_request_handler_context_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-request-handler-context-server title: "@kbn/core-http-request-handler-context-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-request-handler-context-server plugin -date: 2024-05-16 +date: 2024-05-17 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 143757c9a5c52..1d09c57a356cb 100644 --- a/api_docs/kbn_core_http_resources_server.mdx +++ b/api_docs/kbn_core_http_resources_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-resources-server title: "@kbn/core-http-resources-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-resources-server plugin -date: 2024-05-16 +date: 2024-05-17 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 e800eb4157bc3..186c39943cc25 100644 --- a/api_docs/kbn_core_http_resources_server_internal.mdx +++ b/api_docs/kbn_core_http_resources_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-resources-server-internal title: "@kbn/core-http-resources-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-resources-server-internal plugin -date: 2024-05-16 +date: 2024-05-17 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 c663c3c117c52..432112834ff9b 100644 --- a/api_docs/kbn_core_http_resources_server_mocks.mdx +++ b/api_docs/kbn_core_http_resources_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-resources-server-mocks title: "@kbn/core-http-resources-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-resources-server-mocks plugin -date: 2024-05-16 +date: 2024-05-17 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 d748890aaa800..0e75476165972 100644 --- a/api_docs/kbn_core_http_router_server_internal.mdx +++ b/api_docs/kbn_core_http_router_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-router-server-internal title: "@kbn/core-http-router-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-router-server-internal plugin -date: 2024-05-16 +date: 2024-05-17 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 a6931d53482ab..48eb2177866fa 100644 --- a/api_docs/kbn_core_http_router_server_mocks.mdx +++ b/api_docs/kbn_core_http_router_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-router-server-mocks title: "@kbn/core-http-router-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-router-server-mocks plugin -date: 2024-05-16 +date: 2024-05-17 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 35e4843e88499..67868d64c110c 100644 --- a/api_docs/kbn_core_http_server.devdocs.json +++ b/api_docs/kbn_core_http_server.devdocs.json @@ -3632,11 +3632,11 @@ }, { "plugin": "security", - "path": "x-pack/plugins/security/server/routes/indices/get_fields.ts" + "path": "x-pack/plugins/security/server/routes/feature_check/feature_check.ts" }, { "plugin": "security", - "path": "x-pack/plugins/security/server/routes/role_mapping/feature_check.ts" + "path": "x-pack/plugins/security/server/routes/indices/get_fields.ts" }, { "plugin": "security", @@ -4574,6 +4574,10 @@ "plugin": "serverlessSearch", "path": "x-pack/plugins/serverless_search/server/routes/mapping_routes.ts" }, + { + "plugin": "serverlessSearch", + "path": "x-pack/plugins/serverless_search/server/routes/ingest_pipeline_routes.ts" + }, { "plugin": "snapshotRestore", "path": "x-pack/plugins/snapshot_restore/server/routes/api/app.ts" @@ -5824,11 +5828,11 @@ }, { "plugin": "security", - "path": "x-pack/plugins/security/server/routes/indices/get_fields.test.ts" + "path": "x-pack/plugins/security/server/routes/feature_check/feature_check.test.ts" }, { "plugin": "security", - "path": "x-pack/plugins/security/server/routes/role_mapping/feature_check.test.ts" + "path": "x-pack/plugins/security/server/routes/indices/get_fields.test.ts" }, { "plugin": "security", diff --git a/api_docs/kbn_core_http_server.mdx b/api_docs/kbn_core_http_server.mdx index 2f0741b73882e..4348a86af7122 100644 --- a/api_docs/kbn_core_http_server.mdx +++ b/api_docs/kbn_core_http_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-server title: "@kbn/core-http-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-server plugin -date: 2024-05-16 +date: 2024-05-17 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 74d82823865ac..a47a274e52fd3 100644 --- a/api_docs/kbn_core_http_server_internal.mdx +++ b/api_docs/kbn_core_http_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-server-internal title: "@kbn/core-http-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-server-internal plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-server-internal'] --- import kbnCoreHttpServerInternalObj from './kbn_core_http_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_http_server_mocks.mdx b/api_docs/kbn_core_http_server_mocks.mdx index 71d2d9056a41a..afd0796644c50 100644 --- a/api_docs/kbn_core_http_server_mocks.mdx +++ b/api_docs/kbn_core_http_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-server-mocks title: "@kbn/core-http-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-server-mocks plugin -date: 2024-05-16 +date: 2024-05-17 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 01a0c79507592..a9ff67fdf2bce 100644 --- a/api_docs/kbn_core_i18n_browser.mdx +++ b/api_docs/kbn_core_i18n_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-i18n-browser title: "@kbn/core-i18n-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-i18n-browser plugin -date: 2024-05-16 +date: 2024-05-17 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 7d0404dc61a8e..63157c9ff0bc8 100644 --- a/api_docs/kbn_core_i18n_browser_mocks.mdx +++ b/api_docs/kbn_core_i18n_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-i18n-browser-mocks title: "@kbn/core-i18n-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-i18n-browser-mocks plugin -date: 2024-05-16 +date: 2024-05-17 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 bb2353baf29cb..9754f2c9aa01e 100644 --- a/api_docs/kbn_core_i18n_server.mdx +++ b/api_docs/kbn_core_i18n_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-i18n-server title: "@kbn/core-i18n-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-i18n-server plugin -date: 2024-05-16 +date: 2024-05-17 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 c8b381e62b708..56aca483c6266 100644 --- a/api_docs/kbn_core_i18n_server_internal.mdx +++ b/api_docs/kbn_core_i18n_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-i18n-server-internal title: "@kbn/core-i18n-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-i18n-server-internal plugin -date: 2024-05-16 +date: 2024-05-17 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 e7e2f8282fa68..f6e17011b4cdf 100644 --- a/api_docs/kbn_core_i18n_server_mocks.mdx +++ b/api_docs/kbn_core_i18n_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-i18n-server-mocks title: "@kbn/core-i18n-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-i18n-server-mocks plugin -date: 2024-05-16 +date: 2024-05-17 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 cbac2e832e608..cd0ae16dbba28 100644 --- a/api_docs/kbn_core_injected_metadata_browser_mocks.mdx +++ b/api_docs/kbn_core_injected_metadata_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-injected-metadata-browser-mocks title: "@kbn/core-injected-metadata-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-injected-metadata-browser-mocks plugin -date: 2024-05-16 +date: 2024-05-17 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 c45db8af105ae..6b9b52bfebf3b 100644 --- a/api_docs/kbn_core_integrations_browser_internal.mdx +++ b/api_docs/kbn_core_integrations_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-integrations-browser-internal title: "@kbn/core-integrations-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-integrations-browser-internal plugin -date: 2024-05-16 +date: 2024-05-17 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 dbf54f2de2589..047cf3fc3c66e 100644 --- a/api_docs/kbn_core_integrations_browser_mocks.mdx +++ b/api_docs/kbn_core_integrations_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-integrations-browser-mocks title: "@kbn/core-integrations-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-integrations-browser-mocks plugin -date: 2024-05-16 +date: 2024-05-17 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 6b24171594fd6..3b26e82d44729 100644 --- a/api_docs/kbn_core_lifecycle_browser.mdx +++ b/api_docs/kbn_core_lifecycle_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-lifecycle-browser title: "@kbn/core-lifecycle-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-lifecycle-browser plugin -date: 2024-05-16 +date: 2024-05-17 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 a6f3e1349b4e6..b04bc6a4a798d 100644 --- a/api_docs/kbn_core_lifecycle_browser_mocks.mdx +++ b/api_docs/kbn_core_lifecycle_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-lifecycle-browser-mocks title: "@kbn/core-lifecycle-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-lifecycle-browser-mocks plugin -date: 2024-05-16 +date: 2024-05-17 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 d28c80ddfbd2e..4f0893326e926 100644 --- a/api_docs/kbn_core_lifecycle_server.mdx +++ b/api_docs/kbn_core_lifecycle_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-lifecycle-server title: "@kbn/core-lifecycle-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-lifecycle-server plugin -date: 2024-05-16 +date: 2024-05-17 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 0598d9c2b8db2..1904590978be8 100644 --- a/api_docs/kbn_core_lifecycle_server_mocks.mdx +++ b/api_docs/kbn_core_lifecycle_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-lifecycle-server-mocks title: "@kbn/core-lifecycle-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-lifecycle-server-mocks plugin -date: 2024-05-16 +date: 2024-05-17 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 754d285784bf9..c72c3bf34c9ca 100644 --- a/api_docs/kbn_core_logging_browser_mocks.mdx +++ b/api_docs/kbn_core_logging_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-logging-browser-mocks title: "@kbn/core-logging-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-logging-browser-mocks plugin -date: 2024-05-16 +date: 2024-05-17 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 590893a90cb57..1861471055c85 100644 --- a/api_docs/kbn_core_logging_common_internal.mdx +++ b/api_docs/kbn_core_logging_common_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-logging-common-internal title: "@kbn/core-logging-common-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-logging-common-internal plugin -date: 2024-05-16 +date: 2024-05-17 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 c8a2b600eaa04..d6a816663a6fc 100644 --- a/api_docs/kbn_core_logging_server.mdx +++ b/api_docs/kbn_core_logging_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-logging-server title: "@kbn/core-logging-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-logging-server plugin -date: 2024-05-16 +date: 2024-05-17 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 6b249c791d4ec..f51c8fff6d086 100644 --- a/api_docs/kbn_core_logging_server_internal.mdx +++ b/api_docs/kbn_core_logging_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-logging-server-internal title: "@kbn/core-logging-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-logging-server-internal plugin -date: 2024-05-16 +date: 2024-05-17 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 2989480912a13..07e970fc6205d 100644 --- a/api_docs/kbn_core_logging_server_mocks.mdx +++ b/api_docs/kbn_core_logging_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-logging-server-mocks title: "@kbn/core-logging-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-logging-server-mocks plugin -date: 2024-05-16 +date: 2024-05-17 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 e836d03adce60..d9d0308e46ac9 100644 --- a/api_docs/kbn_core_metrics_collectors_server_internal.mdx +++ b/api_docs/kbn_core_metrics_collectors_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-metrics-collectors-server-internal title: "@kbn/core-metrics-collectors-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-metrics-collectors-server-internal plugin -date: 2024-05-16 +date: 2024-05-17 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 65344413b0abb..36cd196ca79d1 100644 --- a/api_docs/kbn_core_metrics_collectors_server_mocks.mdx +++ b/api_docs/kbn_core_metrics_collectors_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-metrics-collectors-server-mocks title: "@kbn/core-metrics-collectors-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-metrics-collectors-server-mocks plugin -date: 2024-05-16 +date: 2024-05-17 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 c8bf769ee1c0a..1cb761eec2aad 100644 --- a/api_docs/kbn_core_metrics_server.mdx +++ b/api_docs/kbn_core_metrics_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-metrics-server title: "@kbn/core-metrics-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-metrics-server plugin -date: 2024-05-16 +date: 2024-05-17 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 88cd5aad5e94b..f998c39a8aa50 100644 --- a/api_docs/kbn_core_metrics_server_internal.mdx +++ b/api_docs/kbn_core_metrics_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-metrics-server-internal title: "@kbn/core-metrics-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-metrics-server-internal plugin -date: 2024-05-16 +date: 2024-05-17 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 0ba5087c39f72..97e4a3d7b4451 100644 --- a/api_docs/kbn_core_metrics_server_mocks.mdx +++ b/api_docs/kbn_core_metrics_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-metrics-server-mocks title: "@kbn/core-metrics-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-metrics-server-mocks plugin -date: 2024-05-16 +date: 2024-05-17 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 3269c9a08ec78..fe689c4044816 100644 --- a/api_docs/kbn_core_mount_utils_browser.mdx +++ b/api_docs/kbn_core_mount_utils_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-mount-utils-browser title: "@kbn/core-mount-utils-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-mount-utils-browser plugin -date: 2024-05-16 +date: 2024-05-17 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 ba40766b91324..c96722cb19796 100644 --- a/api_docs/kbn_core_node_server.mdx +++ b/api_docs/kbn_core_node_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-node-server title: "@kbn/core-node-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-node-server plugin -date: 2024-05-16 +date: 2024-05-17 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 efcc8448e2f08..cf6b57c5a728d 100644 --- a/api_docs/kbn_core_node_server_internal.mdx +++ b/api_docs/kbn_core_node_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-node-server-internal title: "@kbn/core-node-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-node-server-internal plugin -date: 2024-05-16 +date: 2024-05-17 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 163ccd3de0a5c..bf53167682f82 100644 --- a/api_docs/kbn_core_node_server_mocks.mdx +++ b/api_docs/kbn_core_node_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-node-server-mocks title: "@kbn/core-node-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-node-server-mocks plugin -date: 2024-05-16 +date: 2024-05-17 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 724f3304476e3..4e86f9e5dd2d5 100644 --- a/api_docs/kbn_core_notifications_browser.mdx +++ b/api_docs/kbn_core_notifications_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-notifications-browser title: "@kbn/core-notifications-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-notifications-browser plugin -date: 2024-05-16 +date: 2024-05-17 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 2a5904ad34273..36da3408c86d0 100644 --- a/api_docs/kbn_core_notifications_browser_internal.mdx +++ b/api_docs/kbn_core_notifications_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-notifications-browser-internal title: "@kbn/core-notifications-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-notifications-browser-internal plugin -date: 2024-05-16 +date: 2024-05-17 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 f91de95813ed9..b312b6e0b56ed 100644 --- a/api_docs/kbn_core_notifications_browser_mocks.mdx +++ b/api_docs/kbn_core_notifications_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-notifications-browser-mocks title: "@kbn/core-notifications-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-notifications-browser-mocks plugin -date: 2024-05-16 +date: 2024-05-17 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 32205b46dd043..87b524dafa5f2 100644 --- a/api_docs/kbn_core_overlays_browser.mdx +++ b/api_docs/kbn_core_overlays_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-overlays-browser title: "@kbn/core-overlays-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-overlays-browser plugin -date: 2024-05-16 +date: 2024-05-17 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 792172a4c18e8..f4767a032fe97 100644 --- a/api_docs/kbn_core_overlays_browser_internal.mdx +++ b/api_docs/kbn_core_overlays_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-overlays-browser-internal title: "@kbn/core-overlays-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-overlays-browser-internal plugin -date: 2024-05-16 +date: 2024-05-17 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 8c14d60c0fbc6..01140f554987c 100644 --- a/api_docs/kbn_core_overlays_browser_mocks.mdx +++ b/api_docs/kbn_core_overlays_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-overlays-browser-mocks title: "@kbn/core-overlays-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-overlays-browser-mocks plugin -date: 2024-05-16 +date: 2024-05-17 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 0b8b77c7af6a0..5518ab165afb8 100644 --- a/api_docs/kbn_core_plugins_browser.mdx +++ b/api_docs/kbn_core_plugins_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-plugins-browser title: "@kbn/core-plugins-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-plugins-browser plugin -date: 2024-05-16 +date: 2024-05-17 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 bf6c4692d7885..cb728794046be 100644 --- a/api_docs/kbn_core_plugins_browser_mocks.mdx +++ b/api_docs/kbn_core_plugins_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-plugins-browser-mocks title: "@kbn/core-plugins-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-plugins-browser-mocks plugin -date: 2024-05-16 +date: 2024-05-17 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 ec79b1c0d06ec..c5c5e1dc81d37 100644 --- a/api_docs/kbn_core_plugins_contracts_browser.mdx +++ b/api_docs/kbn_core_plugins_contracts_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-plugins-contracts-browser title: "@kbn/core-plugins-contracts-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-plugins-contracts-browser plugin -date: 2024-05-16 +date: 2024-05-17 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 12d9a451b5251..9b7f1ce9a3408 100644 --- a/api_docs/kbn_core_plugins_contracts_server.mdx +++ b/api_docs/kbn_core_plugins_contracts_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-plugins-contracts-server title: "@kbn/core-plugins-contracts-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-plugins-contracts-server plugin -date: 2024-05-16 +date: 2024-05-17 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 3dbccd7d57226..4d7a5ad49c4f9 100644 --- a/api_docs/kbn_core_plugins_server.mdx +++ b/api_docs/kbn_core_plugins_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-plugins-server title: "@kbn/core-plugins-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-plugins-server plugin -date: 2024-05-16 +date: 2024-05-17 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 983a333cdfd89..04dcec58add15 100644 --- a/api_docs/kbn_core_plugins_server_mocks.mdx +++ b/api_docs/kbn_core_plugins_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-plugins-server-mocks title: "@kbn/core-plugins-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-plugins-server-mocks plugin -date: 2024-05-16 +date: 2024-05-17 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 28651dda40c51..d3b7c99aa427a 100644 --- a/api_docs/kbn_core_preboot_server.mdx +++ b/api_docs/kbn_core_preboot_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-preboot-server title: "@kbn/core-preboot-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-preboot-server plugin -date: 2024-05-16 +date: 2024-05-17 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 942f49342587b..5a065851508cc 100644 --- a/api_docs/kbn_core_preboot_server_mocks.mdx +++ b/api_docs/kbn_core_preboot_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-preboot-server-mocks title: "@kbn/core-preboot-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-preboot-server-mocks plugin -date: 2024-05-16 +date: 2024-05-17 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 614849ea3a7c3..7148a5d0e7aa7 100644 --- a/api_docs/kbn_core_rendering_browser_mocks.mdx +++ b/api_docs/kbn_core_rendering_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-rendering-browser-mocks title: "@kbn/core-rendering-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-rendering-browser-mocks plugin -date: 2024-05-16 +date: 2024-05-17 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 1f0294bedf94e..f3438dcafabec 100644 --- a/api_docs/kbn_core_rendering_server_internal.mdx +++ b/api_docs/kbn_core_rendering_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-rendering-server-internal title: "@kbn/core-rendering-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-rendering-server-internal plugin -date: 2024-05-16 +date: 2024-05-17 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 7bae2adb00007..c5018fd07c5a3 100644 --- a/api_docs/kbn_core_rendering_server_mocks.mdx +++ b/api_docs/kbn_core_rendering_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-rendering-server-mocks title: "@kbn/core-rendering-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-rendering-server-mocks plugin -date: 2024-05-16 +date: 2024-05-17 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 beee3376da0a7..0b5e4f399f08d 100644 --- a/api_docs/kbn_core_root_server_internal.mdx +++ b/api_docs/kbn_core_root_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-root-server-internal title: "@kbn/core-root-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-root-server-internal plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-root-server-internal'] --- import kbnCoreRootServerInternalObj from './kbn_core_root_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_api_browser.mdx b/api_docs/kbn_core_saved_objects_api_browser.mdx index 173e104c2bada..ee3bbc755c0ba 100644 --- a/api_docs/kbn_core_saved_objects_api_browser.mdx +++ b/api_docs/kbn_core_saved_objects_api_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-api-browser title: "@kbn/core-saved-objects-api-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-api-browser plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-api-browser'] --- import kbnCoreSavedObjectsApiBrowserObj from './kbn_core_saved_objects_api_browser.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_api_server.mdx b/api_docs/kbn_core_saved_objects_api_server.mdx index 7501f41dac5f6..de15923802341 100644 --- a/api_docs/kbn_core_saved_objects_api_server.mdx +++ b/api_docs/kbn_core_saved_objects_api_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-api-server title: "@kbn/core-saved-objects-api-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-api-server plugin -date: 2024-05-16 +date: 2024-05-17 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 d89c3daddb95c..4346109d0559b 100644 --- a/api_docs/kbn_core_saved_objects_api_server_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_api_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-api-server-mocks title: "@kbn/core-saved-objects-api-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-api-server-mocks plugin -date: 2024-05-16 +date: 2024-05-17 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 8d4b1bada6a17..e365514b2bab8 100644 --- a/api_docs/kbn_core_saved_objects_base_server_internal.mdx +++ b/api_docs/kbn_core_saved_objects_base_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-base-server-internal title: "@kbn/core-saved-objects-base-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-base-server-internal plugin -date: 2024-05-16 +date: 2024-05-17 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 ad76fb69c6b3e..93c5f03ec53b7 100644 --- a/api_docs/kbn_core_saved_objects_base_server_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_base_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-base-server-mocks title: "@kbn/core-saved-objects-base-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-base-server-mocks plugin -date: 2024-05-16 +date: 2024-05-17 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 a41ef025bc393..e53010fbd4dca 100644 --- a/api_docs/kbn_core_saved_objects_browser.mdx +++ b/api_docs/kbn_core_saved_objects_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-browser title: "@kbn/core-saved-objects-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-browser plugin -date: 2024-05-16 +date: 2024-05-17 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 eea26e1d6f2a8..786c6f12754f0 100644 --- a/api_docs/kbn_core_saved_objects_browser_internal.mdx +++ b/api_docs/kbn_core_saved_objects_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-browser-internal title: "@kbn/core-saved-objects-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-browser-internal plugin -date: 2024-05-16 +date: 2024-05-17 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 ee912df1d5ade..c32e1807716e4 100644 --- a/api_docs/kbn_core_saved_objects_browser_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-browser-mocks title: "@kbn/core-saved-objects-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-browser-mocks plugin -date: 2024-05-16 +date: 2024-05-17 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 d675cdeb9ee42..82c0f60dccfd2 100644 --- a/api_docs/kbn_core_saved_objects_common.mdx +++ b/api_docs/kbn_core_saved_objects_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-common title: "@kbn/core-saved-objects-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-common plugin -date: 2024-05-16 +date: 2024-05-17 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 3e50096fc8a58..85edc07df625d 100644 --- a/api_docs/kbn_core_saved_objects_import_export_server_internal.mdx +++ b/api_docs/kbn_core_saved_objects_import_export_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-import-export-server-internal title: "@kbn/core-saved-objects-import-export-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-import-export-server-internal plugin -date: 2024-05-16 +date: 2024-05-17 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 949b094522ef1..446f50d59ce73 100644 --- a/api_docs/kbn_core_saved_objects_import_export_server_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_import_export_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-import-export-server-mocks title: "@kbn/core-saved-objects-import-export-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-import-export-server-mocks plugin -date: 2024-05-16 +date: 2024-05-17 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 2177b1b8373e5..c2b8752a9447e 100644 --- a/api_docs/kbn_core_saved_objects_migration_server_internal.mdx +++ b/api_docs/kbn_core_saved_objects_migration_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-migration-server-internal title: "@kbn/core-saved-objects-migration-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-migration-server-internal plugin -date: 2024-05-16 +date: 2024-05-17 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 0a061496ea2dc..56bb789213994 100644 --- a/api_docs/kbn_core_saved_objects_migration_server_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_migration_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-migration-server-mocks title: "@kbn/core-saved-objects-migration-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-migration-server-mocks plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-migration-server-mocks'] --- import kbnCoreSavedObjectsMigrationServerMocksObj from './kbn_core_saved_objects_migration_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_server.mdx b/api_docs/kbn_core_saved_objects_server.mdx index 9f977ef8a647e..69527cbfeb374 100644 --- a/api_docs/kbn_core_saved_objects_server.mdx +++ b/api_docs/kbn_core_saved_objects_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-server title: "@kbn/core-saved-objects-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-server plugin -date: 2024-05-16 +date: 2024-05-17 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 bb4d385dd23d1..75cefa3e46691 100644 --- a/api_docs/kbn_core_saved_objects_server_internal.mdx +++ b/api_docs/kbn_core_saved_objects_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-server-internal title: "@kbn/core-saved-objects-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-server-internal plugin -date: 2024-05-16 +date: 2024-05-17 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 3c4ca5fb11135..434d2739c0042 100644 --- a/api_docs/kbn_core_saved_objects_server_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-server-mocks title: "@kbn/core-saved-objects-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-server-mocks plugin -date: 2024-05-16 +date: 2024-05-17 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 5985c2bb53d43..05b59b51d235c 100644 --- a/api_docs/kbn_core_saved_objects_utils_server.mdx +++ b/api_docs/kbn_core_saved_objects_utils_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-utils-server title: "@kbn/core-saved-objects-utils-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-utils-server plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-utils-server'] --- import kbnCoreSavedObjectsUtilsServerObj from './kbn_core_saved_objects_utils_server.devdocs.json'; diff --git a/api_docs/kbn_core_security_browser.mdx b/api_docs/kbn_core_security_browser.mdx index 4ae30030a7bcc..df94f80adfa8d 100644 --- a/api_docs/kbn_core_security_browser.mdx +++ b/api_docs/kbn_core_security_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-security-browser title: "@kbn/core-security-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-security-browser plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-security-browser'] --- import kbnCoreSecurityBrowserObj from './kbn_core_security_browser.devdocs.json'; diff --git a/api_docs/kbn_core_security_browser_internal.mdx b/api_docs/kbn_core_security_browser_internal.mdx index 464dbeeb78c55..7e2098d979b22 100644 --- a/api_docs/kbn_core_security_browser_internal.mdx +++ b/api_docs/kbn_core_security_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-security-browser-internal title: "@kbn/core-security-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-security-browser-internal plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-security-browser-internal'] --- import kbnCoreSecurityBrowserInternalObj from './kbn_core_security_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_security_browser_mocks.mdx b/api_docs/kbn_core_security_browser_mocks.mdx index 1bfe8202f819d..1b7ba91fc4441 100644 --- a/api_docs/kbn_core_security_browser_mocks.mdx +++ b/api_docs/kbn_core_security_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-security-browser-mocks title: "@kbn/core-security-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-security-browser-mocks plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-security-browser-mocks'] --- import kbnCoreSecurityBrowserMocksObj from './kbn_core_security_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_security_common.mdx b/api_docs/kbn_core_security_common.mdx index 550c7ee2d174c..880bde21b83c8 100644 --- a/api_docs/kbn_core_security_common.mdx +++ b/api_docs/kbn_core_security_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-security-common title: "@kbn/core-security-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-security-common plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-security-common'] --- import kbnCoreSecurityCommonObj from './kbn_core_security_common.devdocs.json'; diff --git a/api_docs/kbn_core_security_server.mdx b/api_docs/kbn_core_security_server.mdx index a47d088d95071..6b41a3fb8f7a5 100644 --- a/api_docs/kbn_core_security_server.mdx +++ b/api_docs/kbn_core_security_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-security-server title: "@kbn/core-security-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-security-server plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-security-server'] --- import kbnCoreSecurityServerObj from './kbn_core_security_server.devdocs.json'; diff --git a/api_docs/kbn_core_security_server_internal.mdx b/api_docs/kbn_core_security_server_internal.mdx index 976685c74fe2f..7b70ea6f08071 100644 --- a/api_docs/kbn_core_security_server_internal.mdx +++ b/api_docs/kbn_core_security_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-security-server-internal title: "@kbn/core-security-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-security-server-internal plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-security-server-internal'] --- import kbnCoreSecurityServerInternalObj from './kbn_core_security_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_security_server_mocks.mdx b/api_docs/kbn_core_security_server_mocks.mdx index 8f89a2db2c49d..eb16fe4be2a99 100644 --- a/api_docs/kbn_core_security_server_mocks.mdx +++ b/api_docs/kbn_core_security_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-security-server-mocks title: "@kbn/core-security-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-security-server-mocks plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-security-server-mocks'] --- import kbnCoreSecurityServerMocksObj from './kbn_core_security_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_status_common.mdx b/api_docs/kbn_core_status_common.mdx index 213ad98bd2e3c..bdc9fbd11e79d 100644 --- a/api_docs/kbn_core_status_common.mdx +++ b/api_docs/kbn_core_status_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-status-common title: "@kbn/core-status-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-status-common plugin -date: 2024-05-16 +date: 2024-05-17 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 37ff44574b2dd..df8dda07c1269 100644 --- a/api_docs/kbn_core_status_common_internal.mdx +++ b/api_docs/kbn_core_status_common_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-status-common-internal title: "@kbn/core-status-common-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-status-common-internal plugin -date: 2024-05-16 +date: 2024-05-17 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 91f9295cbc5be..469c0e0159e26 100644 --- a/api_docs/kbn_core_status_server.mdx +++ b/api_docs/kbn_core_status_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-status-server title: "@kbn/core-status-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-status-server plugin -date: 2024-05-16 +date: 2024-05-17 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 e54304728bb19..30b1260c0babe 100644 --- a/api_docs/kbn_core_status_server_internal.mdx +++ b/api_docs/kbn_core_status_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-status-server-internal title: "@kbn/core-status-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-status-server-internal plugin -date: 2024-05-16 +date: 2024-05-17 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 7c5cab677b63d..5262b060c6dfa 100644 --- a/api_docs/kbn_core_status_server_mocks.mdx +++ b/api_docs/kbn_core_status_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-status-server-mocks title: "@kbn/core-status-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-status-server-mocks plugin -date: 2024-05-16 +date: 2024-05-17 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 2f4139687a853..6d2fea0e23589 100644 --- a/api_docs/kbn_core_test_helpers_deprecations_getters.mdx +++ b/api_docs/kbn_core_test_helpers_deprecations_getters.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-test-helpers-deprecations-getters title: "@kbn/core-test-helpers-deprecations-getters" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-test-helpers-deprecations-getters plugin -date: 2024-05-16 +date: 2024-05-17 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 ebac7a0d19a17..6ce6b03042ffe 100644 --- a/api_docs/kbn_core_test_helpers_http_setup_browser.mdx +++ b/api_docs/kbn_core_test_helpers_http_setup_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-test-helpers-http-setup-browser title: "@kbn/core-test-helpers-http-setup-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-test-helpers-http-setup-browser plugin -date: 2024-05-16 +date: 2024-05-17 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 3cb0613ddcc29..1f09345bf8401 100644 --- a/api_docs/kbn_core_test_helpers_kbn_server.mdx +++ b/api_docs/kbn_core_test_helpers_kbn_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-test-helpers-kbn-server title: "@kbn/core-test-helpers-kbn-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-test-helpers-kbn-server plugin -date: 2024-05-16 +date: 2024-05-17 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 c621428bc5c16..c521630f019be 100644 --- a/api_docs/kbn_core_test_helpers_model_versions.mdx +++ b/api_docs/kbn_core_test_helpers_model_versions.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-test-helpers-model-versions title: "@kbn/core-test-helpers-model-versions" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-test-helpers-model-versions plugin -date: 2024-05-16 +date: 2024-05-17 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 41717d02ebda0..05065243419f9 100644 --- a/api_docs/kbn_core_test_helpers_so_type_serializer.mdx +++ b/api_docs/kbn_core_test_helpers_so_type_serializer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-test-helpers-so-type-serializer title: "@kbn/core-test-helpers-so-type-serializer" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-test-helpers-so-type-serializer plugin -date: 2024-05-16 +date: 2024-05-17 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 5dbd0fe47d419..ae3b7e33a1fff 100644 --- a/api_docs/kbn_core_test_helpers_test_utils.mdx +++ b/api_docs/kbn_core_test_helpers_test_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-test-helpers-test-utils title: "@kbn/core-test-helpers-test-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-test-helpers-test-utils plugin -date: 2024-05-16 +date: 2024-05-17 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 69a121f9d8727..d6ad27b0af131 100644 --- a/api_docs/kbn_core_theme_browser.mdx +++ b/api_docs/kbn_core_theme_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-theme-browser title: "@kbn/core-theme-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-theme-browser plugin -date: 2024-05-16 +date: 2024-05-17 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 bb7e1cb54c324..0187203d4b3e7 100644 --- a/api_docs/kbn_core_theme_browser_mocks.mdx +++ b/api_docs/kbn_core_theme_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-theme-browser-mocks title: "@kbn/core-theme-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-theme-browser-mocks plugin -date: 2024-05-16 +date: 2024-05-17 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 47c96e90f1a56..282060792ed60 100644 --- a/api_docs/kbn_core_ui_settings_browser.mdx +++ b/api_docs/kbn_core_ui_settings_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-browser title: "@kbn/core-ui-settings-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-browser plugin -date: 2024-05-16 +date: 2024-05-17 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 916abc90e50aa..224063b850e52 100644 --- a/api_docs/kbn_core_ui_settings_browser_internal.mdx +++ b/api_docs/kbn_core_ui_settings_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-browser-internal title: "@kbn/core-ui-settings-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-browser-internal plugin -date: 2024-05-16 +date: 2024-05-17 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 babdcecccca13..6b1cfbceb9a10 100644 --- a/api_docs/kbn_core_ui_settings_browser_mocks.mdx +++ b/api_docs/kbn_core_ui_settings_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-browser-mocks title: "@kbn/core-ui-settings-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-browser-mocks plugin -date: 2024-05-16 +date: 2024-05-17 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 9a91bc8af2832..0afaa87646663 100644 --- a/api_docs/kbn_core_ui_settings_common.mdx +++ b/api_docs/kbn_core_ui_settings_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-common title: "@kbn/core-ui-settings-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-common plugin -date: 2024-05-16 +date: 2024-05-17 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 33ac9cd874775..87fa68e2cb3bf 100644 --- a/api_docs/kbn_core_ui_settings_server.mdx +++ b/api_docs/kbn_core_ui_settings_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-server title: "@kbn/core-ui-settings-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-server plugin -date: 2024-05-16 +date: 2024-05-17 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 14c86f96ad64e..794d8871b6f0a 100644 --- a/api_docs/kbn_core_ui_settings_server_internal.mdx +++ b/api_docs/kbn_core_ui_settings_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-server-internal title: "@kbn/core-ui-settings-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-server-internal plugin -date: 2024-05-16 +date: 2024-05-17 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 509bf5ffbd485..d84d6557acc5d 100644 --- a/api_docs/kbn_core_ui_settings_server_mocks.mdx +++ b/api_docs/kbn_core_ui_settings_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-server-mocks title: "@kbn/core-ui-settings-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-server-mocks plugin -date: 2024-05-16 +date: 2024-05-17 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 c64a7e09fb80d..8dfa3c5db3148 100644 --- a/api_docs/kbn_core_usage_data_server.mdx +++ b/api_docs/kbn_core_usage_data_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-usage-data-server title: "@kbn/core-usage-data-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-usage-data-server plugin -date: 2024-05-16 +date: 2024-05-17 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 26122235e86af..7b9a58a3db57d 100644 --- a/api_docs/kbn_core_usage_data_server_internal.mdx +++ b/api_docs/kbn_core_usage_data_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-usage-data-server-internal title: "@kbn/core-usage-data-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-usage-data-server-internal plugin -date: 2024-05-16 +date: 2024-05-17 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 9d09b1b4c8d11..452f67b1e8759 100644 --- a/api_docs/kbn_core_usage_data_server_mocks.mdx +++ b/api_docs/kbn_core_usage_data_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-usage-data-server-mocks title: "@kbn/core-usage-data-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-usage-data-server-mocks plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-usage-data-server-mocks'] --- import kbnCoreUsageDataServerMocksObj from './kbn_core_usage_data_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_user_profile_browser.mdx b/api_docs/kbn_core_user_profile_browser.mdx index 3a423d1392e2e..b9f3503096a8b 100644 --- a/api_docs/kbn_core_user_profile_browser.mdx +++ b/api_docs/kbn_core_user_profile_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-user-profile-browser title: "@kbn/core-user-profile-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-user-profile-browser plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-user-profile-browser'] --- import kbnCoreUserProfileBrowserObj from './kbn_core_user_profile_browser.devdocs.json'; diff --git a/api_docs/kbn_core_user_profile_browser_internal.mdx b/api_docs/kbn_core_user_profile_browser_internal.mdx index 2cacf48a952b6..329f6a2930266 100644 --- a/api_docs/kbn_core_user_profile_browser_internal.mdx +++ b/api_docs/kbn_core_user_profile_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-user-profile-browser-internal title: "@kbn/core-user-profile-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-user-profile-browser-internal plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-user-profile-browser-internal'] --- import kbnCoreUserProfileBrowserInternalObj from './kbn_core_user_profile_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_user_profile_browser_mocks.mdx b/api_docs/kbn_core_user_profile_browser_mocks.mdx index efcab025912a0..63d96666211dc 100644 --- a/api_docs/kbn_core_user_profile_browser_mocks.mdx +++ b/api_docs/kbn_core_user_profile_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-user-profile-browser-mocks title: "@kbn/core-user-profile-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-user-profile-browser-mocks plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-user-profile-browser-mocks'] --- import kbnCoreUserProfileBrowserMocksObj from './kbn_core_user_profile_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_user_profile_common.mdx b/api_docs/kbn_core_user_profile_common.mdx index 704eb2eca7cad..6062054a802a0 100644 --- a/api_docs/kbn_core_user_profile_common.mdx +++ b/api_docs/kbn_core_user_profile_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-user-profile-common title: "@kbn/core-user-profile-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-user-profile-common plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-user-profile-common'] --- import kbnCoreUserProfileCommonObj from './kbn_core_user_profile_common.devdocs.json'; diff --git a/api_docs/kbn_core_user_profile_server.mdx b/api_docs/kbn_core_user_profile_server.mdx index 1051ea1056ab4..d2429e6d7f155 100644 --- a/api_docs/kbn_core_user_profile_server.mdx +++ b/api_docs/kbn_core_user_profile_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-user-profile-server title: "@kbn/core-user-profile-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-user-profile-server plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-user-profile-server'] --- import kbnCoreUserProfileServerObj from './kbn_core_user_profile_server.devdocs.json'; diff --git a/api_docs/kbn_core_user_profile_server_internal.mdx b/api_docs/kbn_core_user_profile_server_internal.mdx index 06aef9bfae569..981663e1a108d 100644 --- a/api_docs/kbn_core_user_profile_server_internal.mdx +++ b/api_docs/kbn_core_user_profile_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-user-profile-server-internal title: "@kbn/core-user-profile-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-user-profile-server-internal plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-user-profile-server-internal'] --- import kbnCoreUserProfileServerInternalObj from './kbn_core_user_profile_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_user_profile_server_mocks.mdx b/api_docs/kbn_core_user_profile_server_mocks.mdx index 35a8a1dad00ec..2f2e2e4613b71 100644 --- a/api_docs/kbn_core_user_profile_server_mocks.mdx +++ b/api_docs/kbn_core_user_profile_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-user-profile-server-mocks title: "@kbn/core-user-profile-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-user-profile-server-mocks plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-user-profile-server-mocks'] --- import kbnCoreUserProfileServerMocksObj from './kbn_core_user_profile_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_user_settings_server.mdx b/api_docs/kbn_core_user_settings_server.mdx index 41c5300faf2f3..7c345921fa97f 100644 --- a/api_docs/kbn_core_user_settings_server.mdx +++ b/api_docs/kbn_core_user_settings_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-user-settings-server title: "@kbn/core-user-settings-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-user-settings-server plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-user-settings-server'] --- import kbnCoreUserSettingsServerObj from './kbn_core_user_settings_server.devdocs.json'; diff --git a/api_docs/kbn_core_user_settings_server_mocks.mdx b/api_docs/kbn_core_user_settings_server_mocks.mdx index ee8688883f053..cac1a8d6199fa 100644 --- a/api_docs/kbn_core_user_settings_server_mocks.mdx +++ b/api_docs/kbn_core_user_settings_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-user-settings-server-mocks title: "@kbn/core-user-settings-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-user-settings-server-mocks plugin -date: 2024-05-16 +date: 2024-05-17 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 5949bd5960c1d..4bdd403edf949 100644 --- a/api_docs/kbn_crypto.mdx +++ b/api_docs/kbn_crypto.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-crypto title: "@kbn/crypto" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/crypto plugin -date: 2024-05-16 +date: 2024-05-17 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 a4ecdcad0cc3d..3beb47205a28f 100644 --- a/api_docs/kbn_crypto_browser.mdx +++ b/api_docs/kbn_crypto_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-crypto-browser title: "@kbn/crypto-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/crypto-browser plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/crypto-browser'] --- import kbnCryptoBrowserObj from './kbn_crypto_browser.devdocs.json'; diff --git a/api_docs/kbn_custom_icons.mdx b/api_docs/kbn_custom_icons.mdx index f7fb94ce846fa..c324f27bff2f9 100644 --- a/api_docs/kbn_custom_icons.mdx +++ b/api_docs/kbn_custom_icons.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-custom-icons title: "@kbn/custom-icons" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/custom-icons plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/custom-icons'] --- import kbnCustomIconsObj from './kbn_custom_icons.devdocs.json'; diff --git a/api_docs/kbn_custom_integrations.mdx b/api_docs/kbn_custom_integrations.mdx index 20780b9f3e6eb..0b0e8f68e8d65 100644 --- a/api_docs/kbn_custom_integrations.mdx +++ b/api_docs/kbn_custom_integrations.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-custom-integrations title: "@kbn/custom-integrations" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/custom-integrations plugin -date: 2024-05-16 +date: 2024-05-17 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 cfec3b57d7313..e7333d9b4fc7a 100644 --- a/api_docs/kbn_cypress_config.mdx +++ b/api_docs/kbn_cypress_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-cypress-config title: "@kbn/cypress-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/cypress-config plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/cypress-config'] --- import kbnCypressConfigObj from './kbn_cypress_config.devdocs.json'; diff --git a/api_docs/kbn_data_forge.mdx b/api_docs/kbn_data_forge.mdx index c907243a61786..ff0526fa8d49b 100644 --- a/api_docs/kbn_data_forge.mdx +++ b/api_docs/kbn_data_forge.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-data-forge title: "@kbn/data-forge" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/data-forge plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/data-forge'] --- import kbnDataForgeObj from './kbn_data_forge.devdocs.json'; diff --git a/api_docs/kbn_data_service.mdx b/api_docs/kbn_data_service.mdx index b82222aaa03a6..038fbc2c29c30 100644 --- a/api_docs/kbn_data_service.mdx +++ b/api_docs/kbn_data_service.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-data-service title: "@kbn/data-service" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/data-service plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/data-service'] --- import kbnDataServiceObj from './kbn_data_service.devdocs.json'; diff --git a/api_docs/kbn_data_stream_adapter.mdx b/api_docs/kbn_data_stream_adapter.mdx index 8b5df9f42372e..3a65054db04e9 100644 --- a/api_docs/kbn_data_stream_adapter.mdx +++ b/api_docs/kbn_data_stream_adapter.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-data-stream-adapter title: "@kbn/data-stream-adapter" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/data-stream-adapter plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/data-stream-adapter'] --- import kbnDataStreamAdapterObj from './kbn_data_stream_adapter.devdocs.json'; diff --git a/api_docs/kbn_data_view_utils.mdx b/api_docs/kbn_data_view_utils.mdx index 50cfefb4d0524..21943540887ec 100644 --- a/api_docs/kbn_data_view_utils.mdx +++ b/api_docs/kbn_data_view_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-data-view-utils title: "@kbn/data-view-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/data-view-utils plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/data-view-utils'] --- import kbnDataViewUtilsObj from './kbn_data_view_utils.devdocs.json'; diff --git a/api_docs/kbn_datemath.mdx b/api_docs/kbn_datemath.mdx index 7f6779a772c18..211ebb9d30c6d 100644 --- a/api_docs/kbn_datemath.mdx +++ b/api_docs/kbn_datemath.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-datemath title: "@kbn/datemath" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/datemath plugin -date: 2024-05-16 +date: 2024-05-17 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 13c43496b9e5d..6cd32e3a8216a 100644 --- a/api_docs/kbn_deeplinks_analytics.mdx +++ b/api_docs/kbn_deeplinks_analytics.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-deeplinks-analytics title: "@kbn/deeplinks-analytics" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/deeplinks-analytics plugin -date: 2024-05-16 +date: 2024-05-17 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 b600b5be8ad2e..0ebf82aed75c3 100644 --- a/api_docs/kbn_deeplinks_devtools.mdx +++ b/api_docs/kbn_deeplinks_devtools.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-deeplinks-devtools title: "@kbn/deeplinks-devtools" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/deeplinks-devtools plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/deeplinks-devtools'] --- import kbnDeeplinksDevtoolsObj from './kbn_deeplinks_devtools.devdocs.json'; diff --git a/api_docs/kbn_deeplinks_fleet.mdx b/api_docs/kbn_deeplinks_fleet.mdx index 0b4123bbc1a7d..6ecd0720cd545 100644 --- a/api_docs/kbn_deeplinks_fleet.mdx +++ b/api_docs/kbn_deeplinks_fleet.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-deeplinks-fleet title: "@kbn/deeplinks-fleet" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/deeplinks-fleet plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/deeplinks-fleet'] --- import kbnDeeplinksFleetObj from './kbn_deeplinks_fleet.devdocs.json'; diff --git a/api_docs/kbn_deeplinks_management.mdx b/api_docs/kbn_deeplinks_management.mdx index 8e16d449af436..338146ed02a70 100644 --- a/api_docs/kbn_deeplinks_management.mdx +++ b/api_docs/kbn_deeplinks_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-deeplinks-management title: "@kbn/deeplinks-management" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/deeplinks-management plugin -date: 2024-05-16 +date: 2024-05-17 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 55f8ba8822713..b7a7df7ad0036 100644 --- a/api_docs/kbn_deeplinks_ml.mdx +++ b/api_docs/kbn_deeplinks_ml.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-deeplinks-ml title: "@kbn/deeplinks-ml" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/deeplinks-ml plugin -date: 2024-05-16 +date: 2024-05-17 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 e91c7b8196936..8b9c5b52fc088 100644 --- a/api_docs/kbn_deeplinks_observability.mdx +++ b/api_docs/kbn_deeplinks_observability.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-deeplinks-observability title: "@kbn/deeplinks-observability" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/deeplinks-observability plugin -date: 2024-05-16 +date: 2024-05-17 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 fcbb77e852a40..caca52bcbef5c 100644 --- a/api_docs/kbn_deeplinks_search.mdx +++ b/api_docs/kbn_deeplinks_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-deeplinks-search title: "@kbn/deeplinks-search" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/deeplinks-search plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/deeplinks-search'] --- import kbnDeeplinksSearchObj from './kbn_deeplinks_search.devdocs.json'; diff --git a/api_docs/kbn_deeplinks_security.mdx b/api_docs/kbn_deeplinks_security.mdx index af8be0fa8f5a1..372ff59dc5a75 100644 --- a/api_docs/kbn_deeplinks_security.mdx +++ b/api_docs/kbn_deeplinks_security.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-deeplinks-security title: "@kbn/deeplinks-security" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/deeplinks-security plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/deeplinks-security'] --- import kbnDeeplinksSecurityObj from './kbn_deeplinks_security.devdocs.json'; diff --git a/api_docs/kbn_deeplinks_shared.mdx b/api_docs/kbn_deeplinks_shared.mdx index c47b419b735be..f24762384ecea 100644 --- a/api_docs/kbn_deeplinks_shared.mdx +++ b/api_docs/kbn_deeplinks_shared.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-deeplinks-shared title: "@kbn/deeplinks-shared" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/deeplinks-shared plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/deeplinks-shared'] --- import kbnDeeplinksSharedObj from './kbn_deeplinks_shared.devdocs.json'; diff --git a/api_docs/kbn_default_nav_analytics.mdx b/api_docs/kbn_default_nav_analytics.mdx index 4f7f43dd2a8da..df42da34ee3e1 100644 --- a/api_docs/kbn_default_nav_analytics.mdx +++ b/api_docs/kbn_default_nav_analytics.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-default-nav-analytics title: "@kbn/default-nav-analytics" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/default-nav-analytics plugin -date: 2024-05-16 +date: 2024-05-17 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 75d4725ef357b..de048835ad503 100644 --- a/api_docs/kbn_default_nav_devtools.mdx +++ b/api_docs/kbn_default_nav_devtools.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-default-nav-devtools title: "@kbn/default-nav-devtools" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/default-nav-devtools plugin -date: 2024-05-16 +date: 2024-05-17 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 363b55c0d16a2..b41a1ec578d6f 100644 --- a/api_docs/kbn_default_nav_management.mdx +++ b/api_docs/kbn_default_nav_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-default-nav-management title: "@kbn/default-nav-management" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/default-nav-management plugin -date: 2024-05-16 +date: 2024-05-17 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 a3fdf8e052d2f..9b2c0e7578cb9 100644 --- a/api_docs/kbn_default_nav_ml.mdx +++ b/api_docs/kbn_default_nav_ml.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-default-nav-ml title: "@kbn/default-nav-ml" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/default-nav-ml plugin -date: 2024-05-16 +date: 2024-05-17 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 9e625d94b1890..3ba178a55e200 100644 --- a/api_docs/kbn_dev_cli_errors.mdx +++ b/api_docs/kbn_dev_cli_errors.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-dev-cli-errors title: "@kbn/dev-cli-errors" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/dev-cli-errors plugin -date: 2024-05-16 +date: 2024-05-17 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 e71eef2a1bc8c..81fec4bb7d11c 100644 --- a/api_docs/kbn_dev_cli_runner.mdx +++ b/api_docs/kbn_dev_cli_runner.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-dev-cli-runner title: "@kbn/dev-cli-runner" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/dev-cli-runner plugin -date: 2024-05-16 +date: 2024-05-17 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 d3b9373be0271..bc391889d45af 100644 --- a/api_docs/kbn_dev_proc_runner.mdx +++ b/api_docs/kbn_dev_proc_runner.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-dev-proc-runner title: "@kbn/dev-proc-runner" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/dev-proc-runner plugin -date: 2024-05-16 +date: 2024-05-17 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 db6b87a2dd9bc..15cf096506cd4 100644 --- a/api_docs/kbn_dev_utils.mdx +++ b/api_docs/kbn_dev_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-dev-utils title: "@kbn/dev-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/dev-utils plugin -date: 2024-05-16 +date: 2024-05-17 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 baef7cbcccd26..46bafcf5db541 100644 --- a/api_docs/kbn_discover_utils.mdx +++ b/api_docs/kbn_discover_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-discover-utils title: "@kbn/discover-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/discover-utils plugin -date: 2024-05-16 +date: 2024-05-17 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 bf85dc5df4955..5a3baf451f37b 100644 --- a/api_docs/kbn_doc_links.mdx +++ b/api_docs/kbn_doc_links.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-doc-links title: "@kbn/doc-links" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/doc-links plugin -date: 2024-05-16 +date: 2024-05-17 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 415b2a02b41b8..c8f002965c840 100644 --- a/api_docs/kbn_docs_utils.mdx +++ b/api_docs/kbn_docs_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-docs-utils title: "@kbn/docs-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/docs-utils plugin -date: 2024-05-16 +date: 2024-05-17 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 402bfbb3f90c4..1f1140a615318 100644 --- a/api_docs/kbn_dom_drag_drop.mdx +++ b/api_docs/kbn_dom_drag_drop.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-dom-drag-drop title: "@kbn/dom-drag-drop" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/dom-drag-drop plugin -date: 2024-05-16 +date: 2024-05-17 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 dab4c21a23621..805b0e68d7a19 100644 --- a/api_docs/kbn_ebt_tools.mdx +++ b/api_docs/kbn_ebt_tools.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ebt-tools title: "@kbn/ebt-tools" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ebt-tools plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ebt-tools'] --- import kbnEbtToolsObj from './kbn_ebt_tools.devdocs.json'; diff --git a/api_docs/kbn_ecs_data_quality_dashboard.mdx b/api_docs/kbn_ecs_data_quality_dashboard.mdx index dbf8449d62373..83fd390d77147 100644 --- a/api_docs/kbn_ecs_data_quality_dashboard.mdx +++ b/api_docs/kbn_ecs_data_quality_dashboard.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ecs-data-quality-dashboard title: "@kbn/ecs-data-quality-dashboard" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ecs-data-quality-dashboard plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ecs-data-quality-dashboard'] --- import kbnEcsDataQualityDashboardObj from './kbn_ecs_data_quality_dashboard.devdocs.json'; diff --git a/api_docs/kbn_elastic_agent_utils.mdx b/api_docs/kbn_elastic_agent_utils.mdx index 06898632b335c..e8920b963d44e 100644 --- a/api_docs/kbn_elastic_agent_utils.mdx +++ b/api_docs/kbn_elastic_agent_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-elastic-agent-utils title: "@kbn/elastic-agent-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/elastic-agent-utils plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/elastic-agent-utils'] --- import kbnElasticAgentUtilsObj from './kbn_elastic_agent_utils.devdocs.json'; diff --git a/api_docs/kbn_elastic_assistant.mdx b/api_docs/kbn_elastic_assistant.mdx index 502e690f46bb0..0660e62550b6a 100644 --- a/api_docs/kbn_elastic_assistant.mdx +++ b/api_docs/kbn_elastic_assistant.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-elastic-assistant title: "@kbn/elastic-assistant" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/elastic-assistant plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/elastic-assistant'] --- import kbnElasticAssistantObj from './kbn_elastic_assistant.devdocs.json'; diff --git a/api_docs/kbn_elastic_assistant_common.mdx b/api_docs/kbn_elastic_assistant_common.mdx index 285fd33c75287..c9b782fcb5f77 100644 --- a/api_docs/kbn_elastic_assistant_common.mdx +++ b/api_docs/kbn_elastic_assistant_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-elastic-assistant-common title: "@kbn/elastic-assistant-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/elastic-assistant-common plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/elastic-assistant-common'] --- import kbnElasticAssistantCommonObj from './kbn_elastic_assistant_common.devdocs.json'; diff --git a/api_docs/kbn_es.devdocs.json b/api_docs/kbn_es.devdocs.json index 434582f0c7a68..64d416e95d6c5 100644 --- a/api_docs/kbn_es.devdocs.json +++ b/api_docs/kbn_es.devdocs.json @@ -81,7 +81,7 @@ "signature": [ "(options: ", "InstallSourceOptions", - ") => Promise<{ installPath: string; }>" + ") => Promise<{ installPath: string; disableEsTmpDir: boolean; }>" ], "path": "packages/kbn-es/src/cluster.ts", "deprecated": false, @@ -153,7 +153,7 @@ "signature": [ "(options: ", "InstallSnapshotOptions", - ") => Promise<{ installPath: string; }>" + ") => Promise<{ installPath: string; disableEsTmpDir: boolean; }>" ], "path": "packages/kbn-es/src/cluster.ts", "deprecated": false, @@ -189,7 +189,7 @@ "signature": [ "(archivePath: string, options?: ", "InstallArchiveOptions", - " | undefined) => Promise<{ installPath: string; }>" + " | undefined) => Promise<{ installPath: string; disableEsTmpDir: boolean; }>" ], "path": "packages/kbn-es/src/cluster.ts", "deprecated": false, diff --git a/api_docs/kbn_es.mdx b/api_docs/kbn_es.mdx index bbe24a2dccc9b..3a8a97fb48c7e 100644 --- a/api_docs/kbn_es.mdx +++ b/api_docs/kbn_es.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-es title: "@kbn/es" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/es plugin -date: 2024-05-16 +date: 2024-05-17 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 9b179f7ab7e87..1117b475060d2 100644 --- a/api_docs/kbn_es_archiver.mdx +++ b/api_docs/kbn_es_archiver.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-es-archiver title: "@kbn/es-archiver" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/es-archiver plugin -date: 2024-05-16 +date: 2024-05-17 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 560f2b4d0efe0..b8dd72a7dcd94 100644 --- a/api_docs/kbn_es_errors.mdx +++ b/api_docs/kbn_es_errors.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-es-errors title: "@kbn/es-errors" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/es-errors plugin -date: 2024-05-16 +date: 2024-05-17 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 a87e0d01ae416..31f59062ca8e3 100644 --- a/api_docs/kbn_es_query.mdx +++ b/api_docs/kbn_es_query.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-es-query title: "@kbn/es-query" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/es-query plugin -date: 2024-05-16 +date: 2024-05-17 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 f2560bdbe8d85..c9903f08be08d 100644 --- a/api_docs/kbn_es_types.mdx +++ b/api_docs/kbn_es_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-es-types title: "@kbn/es-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/es-types plugin -date: 2024-05-16 +date: 2024-05-17 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 c6c6c0611a875..f0a2568b31c24 100644 --- a/api_docs/kbn_eslint_plugin_imports.mdx +++ b/api_docs/kbn_eslint_plugin_imports.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-eslint-plugin-imports title: "@kbn/eslint-plugin-imports" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/eslint-plugin-imports plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/eslint-plugin-imports'] --- import kbnEslintPluginImportsObj from './kbn_eslint_plugin_imports.devdocs.json'; diff --git a/api_docs/kbn_esql_ast.mdx b/api_docs/kbn_esql_ast.mdx index 0d937df6592c8..3a73aeeff3b42 100644 --- a/api_docs/kbn_esql_ast.mdx +++ b/api_docs/kbn_esql_ast.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-esql-ast title: "@kbn/esql-ast" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/esql-ast plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/esql-ast'] --- import kbnEsqlAstObj from './kbn_esql_ast.devdocs.json'; diff --git a/api_docs/kbn_esql_utils.mdx b/api_docs/kbn_esql_utils.mdx index 814e18f14cf5e..0e707e004376d 100644 --- a/api_docs/kbn_esql_utils.mdx +++ b/api_docs/kbn_esql_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-esql-utils title: "@kbn/esql-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/esql-utils plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/esql-utils'] --- import kbnEsqlUtilsObj from './kbn_esql_utils.devdocs.json'; diff --git a/api_docs/kbn_esql_validation_autocomplete.mdx b/api_docs/kbn_esql_validation_autocomplete.mdx index 91e3ead1350fd..6caf29b4a5d35 100644 --- a/api_docs/kbn_esql_validation_autocomplete.mdx +++ b/api_docs/kbn_esql_validation_autocomplete.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-esql-validation-autocomplete title: "@kbn/esql-validation-autocomplete" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/esql-validation-autocomplete plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/esql-validation-autocomplete'] --- import kbnEsqlValidationAutocompleteObj from './kbn_esql_validation_autocomplete.devdocs.json'; diff --git a/api_docs/kbn_event_annotation_common.mdx b/api_docs/kbn_event_annotation_common.mdx index 7d831c380ee2c..c29fbb021af9c 100644 --- a/api_docs/kbn_event_annotation_common.mdx +++ b/api_docs/kbn_event_annotation_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-event-annotation-common title: "@kbn/event-annotation-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/event-annotation-common plugin -date: 2024-05-16 +date: 2024-05-17 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 ddcba759bd1bb..ecf09252a4b36 100644 --- a/api_docs/kbn_event_annotation_components.mdx +++ b/api_docs/kbn_event_annotation_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-event-annotation-components title: "@kbn/event-annotation-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/event-annotation-components plugin -date: 2024-05-16 +date: 2024-05-17 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 3d971abf8407c..99a0041525744 100644 --- a/api_docs/kbn_expandable_flyout.mdx +++ b/api_docs/kbn_expandable_flyout.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-expandable-flyout title: "@kbn/expandable-flyout" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/expandable-flyout plugin -date: 2024-05-16 +date: 2024-05-17 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 04ad5a32c856b..9550f3795d76a 100644 --- a/api_docs/kbn_field_types.mdx +++ b/api_docs/kbn_field_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-field-types title: "@kbn/field-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/field-types plugin -date: 2024-05-16 +date: 2024-05-17 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 633fb83ee7041..6d974f2ca9e35 100644 --- a/api_docs/kbn_field_utils.mdx +++ b/api_docs/kbn_field_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-field-utils title: "@kbn/field-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/field-utils plugin -date: 2024-05-16 +date: 2024-05-17 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 ae3ee63ee0574..e10d72e994550 100644 --- a/api_docs/kbn_find_used_node_modules.mdx +++ b/api_docs/kbn_find_used_node_modules.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-find-used-node-modules title: "@kbn/find-used-node-modules" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/find-used-node-modules plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/find-used-node-modules'] --- import kbnFindUsedNodeModulesObj from './kbn_find_used_node_modules.devdocs.json'; diff --git a/api_docs/kbn_formatters.mdx b/api_docs/kbn_formatters.mdx index 8a48773d6a634..3b04a25258387 100644 --- a/api_docs/kbn_formatters.mdx +++ b/api_docs/kbn_formatters.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-formatters title: "@kbn/formatters" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/formatters plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/formatters'] --- import kbnFormattersObj from './kbn_formatters.devdocs.json'; diff --git a/api_docs/kbn_ftr_common_functional_services.mdx b/api_docs/kbn_ftr_common_functional_services.mdx index 01e0892d148d9..af92263e8cfed 100644 --- a/api_docs/kbn_ftr_common_functional_services.mdx +++ b/api_docs/kbn_ftr_common_functional_services.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ftr-common-functional-services title: "@kbn/ftr-common-functional-services" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ftr-common-functional-services plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ftr-common-functional-services'] --- import kbnFtrCommonFunctionalServicesObj from './kbn_ftr_common_functional_services.devdocs.json'; diff --git a/api_docs/kbn_ftr_common_functional_ui_services.mdx b/api_docs/kbn_ftr_common_functional_ui_services.mdx index e8528064fd964..61075c6eb6579 100644 --- a/api_docs/kbn_ftr_common_functional_ui_services.mdx +++ b/api_docs/kbn_ftr_common_functional_ui_services.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ftr-common-functional-ui-services title: "@kbn/ftr-common-functional-ui-services" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ftr-common-functional-ui-services plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ftr-common-functional-ui-services'] --- import kbnFtrCommonFunctionalUiServicesObj from './kbn_ftr_common_functional_ui_services.devdocs.json'; diff --git a/api_docs/kbn_generate.mdx b/api_docs/kbn_generate.mdx index 2fcf761909de9..1ff636eeb0a21 100644 --- a/api_docs/kbn_generate.mdx +++ b/api_docs/kbn_generate.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-generate title: "@kbn/generate" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/generate plugin -date: 2024-05-16 +date: 2024-05-17 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 6cc4a893d35c9..50d686491379d 100644 --- a/api_docs/kbn_generate_console_definitions.mdx +++ b/api_docs/kbn_generate_console_definitions.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-generate-console-definitions title: "@kbn/generate-console-definitions" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/generate-console-definitions plugin -date: 2024-05-16 +date: 2024-05-17 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 b7e80fcd2dd84..653ee460a8fe5 100644 --- a/api_docs/kbn_generate_csv.mdx +++ b/api_docs/kbn_generate_csv.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-generate-csv title: "@kbn/generate-csv" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/generate-csv plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/generate-csv'] --- import kbnGenerateCsvObj from './kbn_generate_csv.devdocs.json'; diff --git a/api_docs/kbn_guided_onboarding.mdx b/api_docs/kbn_guided_onboarding.mdx index 15657f39b8393..6c33c24016be9 100644 --- a/api_docs/kbn_guided_onboarding.mdx +++ b/api_docs/kbn_guided_onboarding.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-guided-onboarding title: "@kbn/guided-onboarding" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/guided-onboarding plugin -date: 2024-05-16 +date: 2024-05-17 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 1a246c914a016..d19dc9e916402 100644 --- a/api_docs/kbn_handlebars.mdx +++ b/api_docs/kbn_handlebars.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-handlebars title: "@kbn/handlebars" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/handlebars plugin -date: 2024-05-16 +date: 2024-05-17 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 24b6ad03908c1..1b4cff78a60c8 100644 --- a/api_docs/kbn_hapi_mocks.mdx +++ b/api_docs/kbn_hapi_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-hapi-mocks title: "@kbn/hapi-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/hapi-mocks plugin -date: 2024-05-16 +date: 2024-05-17 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 06d2ac4f3792a..db3623534368c 100644 --- a/api_docs/kbn_health_gateway_server.mdx +++ b/api_docs/kbn_health_gateway_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-health-gateway-server title: "@kbn/health-gateway-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/health-gateway-server plugin -date: 2024-05-16 +date: 2024-05-17 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 09ac4afcf3651..a37230987a541 100644 --- a/api_docs/kbn_home_sample_data_card.mdx +++ b/api_docs/kbn_home_sample_data_card.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-home-sample-data-card title: "@kbn/home-sample-data-card" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/home-sample-data-card plugin -date: 2024-05-16 +date: 2024-05-17 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 9e8a77a0bde68..8b34f16ff4a37 100644 --- a/api_docs/kbn_home_sample_data_tab.mdx +++ b/api_docs/kbn_home_sample_data_tab.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-home-sample-data-tab title: "@kbn/home-sample-data-tab" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/home-sample-data-tab plugin -date: 2024-05-16 +date: 2024-05-17 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 b80c8b49f39a8..b814e45a8d7ae 100644 --- a/api_docs/kbn_i18n.mdx +++ b/api_docs/kbn_i18n.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-i18n title: "@kbn/i18n" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/i18n plugin -date: 2024-05-16 +date: 2024-05-17 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 b2e6437117528..4425c183688ab 100644 --- a/api_docs/kbn_i18n_react.mdx +++ b/api_docs/kbn_i18n_react.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-i18n-react title: "@kbn/i18n-react" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/i18n-react plugin -date: 2024-05-16 +date: 2024-05-17 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 fc4e4023935bf..0da7050bb2168 100644 --- a/api_docs/kbn_import_resolver.mdx +++ b/api_docs/kbn_import_resolver.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-import-resolver title: "@kbn/import-resolver" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/import-resolver plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/import-resolver'] --- import kbnImportResolverObj from './kbn_import_resolver.devdocs.json'; diff --git a/api_docs/kbn_index_management.mdx b/api_docs/kbn_index_management.mdx index 522045b7c9681..01225b0abd28c 100644 --- a/api_docs/kbn_index_management.mdx +++ b/api_docs/kbn_index_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-index-management title: "@kbn/index-management" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/index-management plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/index-management'] --- import kbnIndexManagementObj from './kbn_index_management.devdocs.json'; diff --git a/api_docs/kbn_inference_integration_flyout.mdx b/api_docs/kbn_inference_integration_flyout.mdx index a03b8fb0dfb9e..4e758ffe534ee 100644 --- a/api_docs/kbn_inference_integration_flyout.mdx +++ b/api_docs/kbn_inference_integration_flyout.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-inference_integration_flyout title: "@kbn/inference_integration_flyout" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/inference_integration_flyout plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/inference_integration_flyout'] --- import kbnInferenceIntegrationFlyoutObj from './kbn_inference_integration_flyout.devdocs.json'; diff --git a/api_docs/kbn_infra_forge.mdx b/api_docs/kbn_infra_forge.mdx index 5eb8b76dfc8db..af996b7c3b0a7 100644 --- a/api_docs/kbn_infra_forge.mdx +++ b/api_docs/kbn_infra_forge.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-infra-forge title: "@kbn/infra-forge" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/infra-forge plugin -date: 2024-05-16 +date: 2024-05-17 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 c90abbce90fa1..231b37fa243d3 100644 --- a/api_docs/kbn_interpreter.mdx +++ b/api_docs/kbn_interpreter.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-interpreter title: "@kbn/interpreter" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/interpreter plugin -date: 2024-05-16 +date: 2024-05-17 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 9cf87176d5f1b..251f6f1c286cc 100644 --- a/api_docs/kbn_io_ts_utils.mdx +++ b/api_docs/kbn_io_ts_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-io-ts-utils title: "@kbn/io-ts-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/io-ts-utils plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/io-ts-utils'] --- import kbnIoTsUtilsObj from './kbn_io_ts_utils.devdocs.json'; diff --git a/api_docs/kbn_ipynb.mdx b/api_docs/kbn_ipynb.mdx index b203fc2516fdb..edfc6c4d6a4f8 100644 --- a/api_docs/kbn_ipynb.mdx +++ b/api_docs/kbn_ipynb.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ipynb title: "@kbn/ipynb" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ipynb plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ipynb'] --- import kbnIpynbObj from './kbn_ipynb.devdocs.json'; diff --git a/api_docs/kbn_jest_serializers.mdx b/api_docs/kbn_jest_serializers.mdx index fe5622055d71b..19f988496b073 100644 --- a/api_docs/kbn_jest_serializers.mdx +++ b/api_docs/kbn_jest_serializers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-jest-serializers title: "@kbn/jest-serializers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/jest-serializers plugin -date: 2024-05-16 +date: 2024-05-17 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 aa9f296afcfb2..b7962b651cba6 100644 --- a/api_docs/kbn_journeys.mdx +++ b/api_docs/kbn_journeys.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-journeys title: "@kbn/journeys" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/journeys plugin -date: 2024-05-16 +date: 2024-05-17 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 fe5c456b61fc0..4330063fe00c8 100644 --- a/api_docs/kbn_json_ast.mdx +++ b/api_docs/kbn_json_ast.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-json-ast title: "@kbn/json-ast" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/json-ast plugin -date: 2024-05-16 +date: 2024-05-17 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 1f3a9b93b94f5..61ec8ae5ce8b1 100644 --- a/api_docs/kbn_kibana_manifest_schema.mdx +++ b/api_docs/kbn_kibana_manifest_schema.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-kibana-manifest-schema title: "@kbn/kibana-manifest-schema" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/kibana-manifest-schema plugin -date: 2024-05-16 +date: 2024-05-17 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 1fcb554a8919b..25b833684cbf1 100644 --- a/api_docs/kbn_language_documentation_popover.mdx +++ b/api_docs/kbn_language_documentation_popover.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-language-documentation-popover title: "@kbn/language-documentation-popover" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/language-documentation-popover plugin -date: 2024-05-16 +date: 2024-05-17 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 d041f048782be..2d2f057707b7c 100644 --- a/api_docs/kbn_lens_embeddable_utils.mdx +++ b/api_docs/kbn_lens_embeddable_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-lens-embeddable-utils title: "@kbn/lens-embeddable-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/lens-embeddable-utils plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/lens-embeddable-utils'] --- import kbnLensEmbeddableUtilsObj from './kbn_lens_embeddable_utils.devdocs.json'; diff --git a/api_docs/kbn_lens_formula_docs.mdx b/api_docs/kbn_lens_formula_docs.mdx index 6e8990daf040c..6bb8189984439 100644 --- a/api_docs/kbn_lens_formula_docs.mdx +++ b/api_docs/kbn_lens_formula_docs.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-lens-formula-docs title: "@kbn/lens-formula-docs" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/lens-formula-docs plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/lens-formula-docs'] --- import kbnLensFormulaDocsObj from './kbn_lens_formula_docs.devdocs.json'; diff --git a/api_docs/kbn_logging.mdx b/api_docs/kbn_logging.mdx index af1f09d93641b..edc37ca458a2e 100644 --- a/api_docs/kbn_logging.mdx +++ b/api_docs/kbn_logging.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-logging title: "@kbn/logging" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/logging plugin -date: 2024-05-16 +date: 2024-05-17 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 f85178aa2f7c0..58e1d323c3109 100644 --- a/api_docs/kbn_logging_mocks.mdx +++ b/api_docs/kbn_logging_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-logging-mocks title: "@kbn/logging-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/logging-mocks plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/logging-mocks'] --- import kbnLoggingMocksObj from './kbn_logging_mocks.devdocs.json'; diff --git a/api_docs/kbn_managed_content_badge.mdx b/api_docs/kbn_managed_content_badge.mdx index 45c75bd11ea9c..240057a534fbb 100644 --- a/api_docs/kbn_managed_content_badge.mdx +++ b/api_docs/kbn_managed_content_badge.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-managed-content-badge title: "@kbn/managed-content-badge" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/managed-content-badge plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/managed-content-badge'] --- import kbnManagedContentBadgeObj from './kbn_managed_content_badge.devdocs.json'; diff --git a/api_docs/kbn_managed_vscode_config.mdx b/api_docs/kbn_managed_vscode_config.mdx index 49419565ee1da..9f84eff04585e 100644 --- a/api_docs/kbn_managed_vscode_config.mdx +++ b/api_docs/kbn_managed_vscode_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-managed-vscode-config title: "@kbn/managed-vscode-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/managed-vscode-config plugin -date: 2024-05-16 +date: 2024-05-17 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 e56190abe6db0..e1a85b4a34cf6 100644 --- a/api_docs/kbn_management_cards_navigation.mdx +++ b/api_docs/kbn_management_cards_navigation.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-cards-navigation title: "@kbn/management-cards-navigation" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-cards-navigation plugin -date: 2024-05-16 +date: 2024-05-17 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 6e2a342d7864f..78ddec1b326fb 100644 --- a/api_docs/kbn_management_settings_application.mdx +++ b/api_docs/kbn_management_settings_application.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-application title: "@kbn/management-settings-application" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-application plugin -date: 2024-05-16 +date: 2024-05-17 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 1f565f99ba23d..a66e7c7f87ece 100644 --- a/api_docs/kbn_management_settings_components_field_category.mdx +++ b/api_docs/kbn_management_settings_components_field_category.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-components-field-category title: "@kbn/management-settings-components-field-category" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-components-field-category plugin -date: 2024-05-16 +date: 2024-05-17 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 8aadf9f1d589c..b16d9b73e7713 100644 --- a/api_docs/kbn_management_settings_components_field_input.mdx +++ b/api_docs/kbn_management_settings_components_field_input.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-components-field-input title: "@kbn/management-settings-components-field-input" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-components-field-input plugin -date: 2024-05-16 +date: 2024-05-17 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 fefcefacd32c6..0a057879d7f2d 100644 --- a/api_docs/kbn_management_settings_components_field_row.mdx +++ b/api_docs/kbn_management_settings_components_field_row.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-components-field-row title: "@kbn/management-settings-components-field-row" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-components-field-row plugin -date: 2024-05-16 +date: 2024-05-17 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 fd44b889d251a..ba8762a3fc108 100644 --- a/api_docs/kbn_management_settings_components_form.mdx +++ b/api_docs/kbn_management_settings_components_form.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-components-form title: "@kbn/management-settings-components-form" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-components-form plugin -date: 2024-05-16 +date: 2024-05-17 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 961e7b7e26409..f094c882827df 100644 --- a/api_docs/kbn_management_settings_field_definition.mdx +++ b/api_docs/kbn_management_settings_field_definition.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-field-definition title: "@kbn/management-settings-field-definition" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-field-definition plugin -date: 2024-05-16 +date: 2024-05-17 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 4495e0bc68ae0..b4b24972b6989 100644 --- a/api_docs/kbn_management_settings_ids.devdocs.json +++ b/api_docs/kbn_management_settings_ids.devdocs.json @@ -1342,6 +1342,21 @@ "trackAdoption": false, "initialIsOpen": false }, + { + "parentPluginId": "@kbn/management-settings-ids", + "id": "def-common.OBSERVABILITY_ENABLE_CONTAINER_ASSET_VIEW_ID", + "type": "string", + "tags": [], + "label": "OBSERVABILITY_ENABLE_CONTAINER_ASSET_VIEW_ID", + "description": [], + "signature": [ + "\"observability:enableContainerAssetView\"" + ], + "path": "packages/kbn-management/settings/setting_ids/index.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, { "parentPluginId": "@kbn/management-settings-ids", "id": "def-common.OBSERVABILITY_ENABLE_INFRASTRUCTURE_ASSET_CUSTOM_DASHBOARDS_ID", diff --git a/api_docs/kbn_management_settings_ids.mdx b/api_docs/kbn_management_settings_ids.mdx index 297d57dcf33c2..c02ad2f6362ee 100644 --- a/api_docs/kbn_management_settings_ids.mdx +++ b/api_docs/kbn_management_settings_ids.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-ids title: "@kbn/management-settings-ids" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-ids plugin -date: 2024-05-16 +date: 2024-05-17 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/kibana-management](https://github.com/ | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 138 | 0 | 135 | 0 | +| 139 | 0 | 136 | 0 | ## Common diff --git a/api_docs/kbn_management_settings_section_registry.mdx b/api_docs/kbn_management_settings_section_registry.mdx index 0399496f900ea..8e2abaa157e8a 100644 --- a/api_docs/kbn_management_settings_section_registry.mdx +++ b/api_docs/kbn_management_settings_section_registry.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-section-registry title: "@kbn/management-settings-section-registry" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-section-registry plugin -date: 2024-05-16 +date: 2024-05-17 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 49180bbb02e57..36f4ad1664324 100644 --- a/api_docs/kbn_management_settings_types.mdx +++ b/api_docs/kbn_management_settings_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-types title: "@kbn/management-settings-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-types plugin -date: 2024-05-16 +date: 2024-05-17 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 da99f5e9f1271..573e59b8eebec 100644 --- a/api_docs/kbn_management_settings_utilities.mdx +++ b/api_docs/kbn_management_settings_utilities.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-utilities title: "@kbn/management-settings-utilities" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-utilities plugin -date: 2024-05-16 +date: 2024-05-17 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 de5c1110c2404..97bf635ef7cb9 100644 --- a/api_docs/kbn_management_storybook_config.mdx +++ b/api_docs/kbn_management_storybook_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-storybook-config title: "@kbn/management-storybook-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-storybook-config plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-storybook-config'] --- import kbnManagementStorybookConfigObj from './kbn_management_storybook_config.devdocs.json'; diff --git a/api_docs/kbn_mapbox_gl.mdx b/api_docs/kbn_mapbox_gl.mdx index abb534d9be1a2..c22f7ba48d96e 100644 --- a/api_docs/kbn_mapbox_gl.mdx +++ b/api_docs/kbn_mapbox_gl.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-mapbox-gl title: "@kbn/mapbox-gl" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/mapbox-gl plugin -date: 2024-05-16 +date: 2024-05-17 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 e952df482cf47..d84fd70e0101f 100644 --- a/api_docs/kbn_maps_vector_tile_utils.mdx +++ b/api_docs/kbn_maps_vector_tile_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-maps-vector-tile-utils title: "@kbn/maps-vector-tile-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/maps-vector-tile-utils plugin -date: 2024-05-16 +date: 2024-05-17 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 ac43b164b2534..b0777f30c7b36 100644 --- a/api_docs/kbn_ml_agg_utils.mdx +++ b/api_docs/kbn_ml_agg_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-agg-utils title: "@kbn/ml-agg-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-agg-utils plugin -date: 2024-05-16 +date: 2024-05-17 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 d5ea92226e837..3470163a6c67f 100644 --- a/api_docs/kbn_ml_anomaly_utils.mdx +++ b/api_docs/kbn_ml_anomaly_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-anomaly-utils title: "@kbn/ml-anomaly-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-anomaly-utils plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-anomaly-utils'] --- import kbnMlAnomalyUtilsObj from './kbn_ml_anomaly_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_cancellable_search.mdx b/api_docs/kbn_ml_cancellable_search.mdx index 8aaca7383fda2..6e43c3815a031 100644 --- a/api_docs/kbn_ml_cancellable_search.mdx +++ b/api_docs/kbn_ml_cancellable_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-cancellable-search title: "@kbn/ml-cancellable-search" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-cancellable-search plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-cancellable-search'] --- import kbnMlCancellableSearchObj from './kbn_ml_cancellable_search.devdocs.json'; diff --git a/api_docs/kbn_ml_category_validator.mdx b/api_docs/kbn_ml_category_validator.mdx index cfff61a6d388c..a935ca38b9907 100644 --- a/api_docs/kbn_ml_category_validator.mdx +++ b/api_docs/kbn_ml_category_validator.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-category-validator title: "@kbn/ml-category-validator" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-category-validator plugin -date: 2024-05-16 +date: 2024-05-17 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 066dd0af7acd2..706082b11619b 100644 --- a/api_docs/kbn_ml_chi2test.mdx +++ b/api_docs/kbn_ml_chi2test.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-chi2test title: "@kbn/ml-chi2test" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-chi2test plugin -date: 2024-05-16 +date: 2024-05-17 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 1dc691ed14ac1..61c4bd53b7bf8 100644 --- a/api_docs/kbn_ml_data_frame_analytics_utils.mdx +++ b/api_docs/kbn_ml_data_frame_analytics_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-data-frame-analytics-utils title: "@kbn/ml-data-frame-analytics-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-data-frame-analytics-utils plugin -date: 2024-05-16 +date: 2024-05-17 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 68beb5c99a0b1..9ad707baf9de7 100644 --- a/api_docs/kbn_ml_data_grid.mdx +++ b/api_docs/kbn_ml_data_grid.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-data-grid title: "@kbn/ml-data-grid" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-data-grid plugin -date: 2024-05-16 +date: 2024-05-17 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 2ec314b6d2f2f..0dc7fd4d8ce46 100644 --- a/api_docs/kbn_ml_date_picker.mdx +++ b/api_docs/kbn_ml_date_picker.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-date-picker title: "@kbn/ml-date-picker" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-date-picker plugin -date: 2024-05-16 +date: 2024-05-17 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 bc36c983a8e58..fdb87e6ead0c8 100644 --- a/api_docs/kbn_ml_date_utils.mdx +++ b/api_docs/kbn_ml_date_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-date-utils title: "@kbn/ml-date-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-date-utils plugin -date: 2024-05-16 +date: 2024-05-17 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 54904f9dcf01a..34e962709318d 100644 --- a/api_docs/kbn_ml_error_utils.mdx +++ b/api_docs/kbn_ml_error_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-error-utils title: "@kbn/ml-error-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-error-utils plugin -date: 2024-05-16 +date: 2024-05-17 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 ace9ba9a7a16c..1bd4b9f1987be 100644 --- a/api_docs/kbn_ml_in_memory_table.mdx +++ b/api_docs/kbn_ml_in_memory_table.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-in-memory-table title: "@kbn/ml-in-memory-table" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-in-memory-table plugin -date: 2024-05-16 +date: 2024-05-17 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 6cc9a25f58261..5f7cd4e2ff0a9 100644 --- a/api_docs/kbn_ml_is_defined.mdx +++ b/api_docs/kbn_ml_is_defined.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-is-defined title: "@kbn/ml-is-defined" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-is-defined plugin -date: 2024-05-16 +date: 2024-05-17 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 be7e72f1acd6e..31f4017eac823 100644 --- a/api_docs/kbn_ml_is_populated_object.mdx +++ b/api_docs/kbn_ml_is_populated_object.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-is-populated-object title: "@kbn/ml-is-populated-object" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-is-populated-object plugin -date: 2024-05-16 +date: 2024-05-17 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 e42d2355c629e..62b780240d0e9 100644 --- a/api_docs/kbn_ml_kibana_theme.mdx +++ b/api_docs/kbn_ml_kibana_theme.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-kibana-theme title: "@kbn/ml-kibana-theme" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-kibana-theme plugin -date: 2024-05-16 +date: 2024-05-17 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 df050e23b8ea3..98320a592e34d 100644 --- a/api_docs/kbn_ml_local_storage.mdx +++ b/api_docs/kbn_ml_local_storage.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-local-storage title: "@kbn/ml-local-storage" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-local-storage plugin -date: 2024-05-16 +date: 2024-05-17 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 bcddcebaee35b..002d87f9f8b7d 100644 --- a/api_docs/kbn_ml_nested_property.mdx +++ b/api_docs/kbn_ml_nested_property.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-nested-property title: "@kbn/ml-nested-property" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-nested-property plugin -date: 2024-05-16 +date: 2024-05-17 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 cd110f90c86da..b31da35bf65b2 100644 --- a/api_docs/kbn_ml_number_utils.mdx +++ b/api_docs/kbn_ml_number_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-number-utils title: "@kbn/ml-number-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-number-utils plugin -date: 2024-05-16 +date: 2024-05-17 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 e690148f10f0e..4394bfcba4ed0 100644 --- a/api_docs/kbn_ml_query_utils.mdx +++ b/api_docs/kbn_ml_query_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-query-utils title: "@kbn/ml-query-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-query-utils plugin -date: 2024-05-16 +date: 2024-05-17 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 8fa568ecb2db4..40a3bd21d910e 100644 --- a/api_docs/kbn_ml_random_sampler_utils.mdx +++ b/api_docs/kbn_ml_random_sampler_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-random-sampler-utils title: "@kbn/ml-random-sampler-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-random-sampler-utils plugin -date: 2024-05-16 +date: 2024-05-17 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 3f488dc0d0f82..d41647a8f96de 100644 --- a/api_docs/kbn_ml_route_utils.mdx +++ b/api_docs/kbn_ml_route_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-route-utils title: "@kbn/ml-route-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-route-utils plugin -date: 2024-05-16 +date: 2024-05-17 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 f39a80437742a..d07b6ab436856 100644 --- a/api_docs/kbn_ml_runtime_field_utils.mdx +++ b/api_docs/kbn_ml_runtime_field_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-runtime-field-utils title: "@kbn/ml-runtime-field-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-runtime-field-utils plugin -date: 2024-05-16 +date: 2024-05-17 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 7660ee4fbce76..71dad33e042a0 100644 --- a/api_docs/kbn_ml_string_hash.mdx +++ b/api_docs/kbn_ml_string_hash.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-string-hash title: "@kbn/ml-string-hash" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-string-hash plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-string-hash'] --- import kbnMlStringHashObj from './kbn_ml_string_hash.devdocs.json'; diff --git a/api_docs/kbn_ml_time_buckets.mdx b/api_docs/kbn_ml_time_buckets.mdx index 0b10962df3c63..225c805a33255 100644 --- a/api_docs/kbn_ml_time_buckets.mdx +++ b/api_docs/kbn_ml_time_buckets.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-time-buckets title: "@kbn/ml-time-buckets" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-time-buckets plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-time-buckets'] --- import kbnMlTimeBucketsObj from './kbn_ml_time_buckets.devdocs.json'; diff --git a/api_docs/kbn_ml_trained_models_utils.mdx b/api_docs/kbn_ml_trained_models_utils.mdx index 446045a85c68d..bc8fe63031abb 100644 --- a/api_docs/kbn_ml_trained_models_utils.mdx +++ b/api_docs/kbn_ml_trained_models_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-trained-models-utils title: "@kbn/ml-trained-models-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-trained-models-utils plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-trained-models-utils'] --- import kbnMlTrainedModelsUtilsObj from './kbn_ml_trained_models_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_ui_actions.mdx b/api_docs/kbn_ml_ui_actions.mdx index 00fb6b3e1c9a4..c4bb62c548c4a 100644 --- a/api_docs/kbn_ml_ui_actions.mdx +++ b/api_docs/kbn_ml_ui_actions.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-ui-actions title: "@kbn/ml-ui-actions" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-ui-actions plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-ui-actions'] --- import kbnMlUiActionsObj from './kbn_ml_ui_actions.devdocs.json'; diff --git a/api_docs/kbn_ml_url_state.mdx b/api_docs/kbn_ml_url_state.mdx index 0623299e03f7e..4a16938f93301 100644 --- a/api_docs/kbn_ml_url_state.mdx +++ b/api_docs/kbn_ml_url_state.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-url-state title: "@kbn/ml-url-state" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-url-state plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-url-state'] --- import kbnMlUrlStateObj from './kbn_ml_url_state.devdocs.json'; diff --git a/api_docs/kbn_mock_idp_utils.mdx b/api_docs/kbn_mock_idp_utils.mdx index 9292911bd5c30..e02d381b3e051 100644 --- a/api_docs/kbn_mock_idp_utils.mdx +++ b/api_docs/kbn_mock_idp_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-mock-idp-utils title: "@kbn/mock-idp-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/mock-idp-utils plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/mock-idp-utils'] --- import kbnMockIdpUtilsObj from './kbn_mock_idp_utils.devdocs.json'; diff --git a/api_docs/kbn_monaco.mdx b/api_docs/kbn_monaco.mdx index f16ab074bb6cc..15a38628e7285 100644 --- a/api_docs/kbn_monaco.mdx +++ b/api_docs/kbn_monaco.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-monaco title: "@kbn/monaco" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/monaco plugin -date: 2024-05-16 +date: 2024-05-17 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 9c4da7bb006fb..3158f504dfa0b 100644 --- a/api_docs/kbn_object_versioning.mdx +++ b/api_docs/kbn_object_versioning.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-object-versioning title: "@kbn/object-versioning" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/object-versioning plugin -date: 2024-05-16 +date: 2024-05-17 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 2a259d02cbe57..e1cf9fe43736e 100644 --- a/api_docs/kbn_observability_alert_details.mdx +++ b/api_docs/kbn_observability_alert_details.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-observability-alert-details title: "@kbn/observability-alert-details" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/observability-alert-details plugin -date: 2024-05-16 +date: 2024-05-17 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 46db2baac7725..ccf41b9aeca24 100644 --- a/api_docs/kbn_observability_alerting_test_data.mdx +++ b/api_docs/kbn_observability_alerting_test_data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-observability-alerting-test-data title: "@kbn/observability-alerting-test-data" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/observability-alerting-test-data plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/observability-alerting-test-data'] --- import kbnObservabilityAlertingTestDataObj from './kbn_observability_alerting_test_data.devdocs.json'; diff --git a/api_docs/kbn_observability_get_padded_alert_time_range_util.mdx b/api_docs/kbn_observability_get_padded_alert_time_range_util.mdx index 6a499920eb57b..34124658ca632 100644 --- a/api_docs/kbn_observability_get_padded_alert_time_range_util.mdx +++ b/api_docs/kbn_observability_get_padded_alert_time_range_util.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-observability-get-padded-alert-time-range-util title: "@kbn/observability-get-padded-alert-time-range-util" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/observability-get-padded-alert-time-range-util plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/observability-get-padded-alert-time-range-util'] --- import kbnObservabilityGetPaddedAlertTimeRangeUtilObj from './kbn_observability_get_padded_alert_time_range_util.devdocs.json'; diff --git a/api_docs/kbn_openapi_bundler.mdx b/api_docs/kbn_openapi_bundler.mdx index 893394d5f2309..971a09d2961bb 100644 --- a/api_docs/kbn_openapi_bundler.mdx +++ b/api_docs/kbn_openapi_bundler.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-openapi-bundler title: "@kbn/openapi-bundler" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/openapi-bundler plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/openapi-bundler'] --- import kbnOpenapiBundlerObj from './kbn_openapi_bundler.devdocs.json'; diff --git a/api_docs/kbn_openapi_generator.mdx b/api_docs/kbn_openapi_generator.mdx index 17a3a3363b47f..fc637a17aaf88 100644 --- a/api_docs/kbn_openapi_generator.mdx +++ b/api_docs/kbn_openapi_generator.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-openapi-generator title: "@kbn/openapi-generator" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/openapi-generator plugin -date: 2024-05-16 +date: 2024-05-17 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 30062861db8aa..5aaecbeb28bbe 100644 --- a/api_docs/kbn_optimizer.mdx +++ b/api_docs/kbn_optimizer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-optimizer title: "@kbn/optimizer" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/optimizer plugin -date: 2024-05-16 +date: 2024-05-17 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 19e8f1ef457c7..4eaba13918985 100644 --- a/api_docs/kbn_optimizer_webpack_helpers.mdx +++ b/api_docs/kbn_optimizer_webpack_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-optimizer-webpack-helpers title: "@kbn/optimizer-webpack-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/optimizer-webpack-helpers plugin -date: 2024-05-16 +date: 2024-05-17 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 5988d319eec88..75097b46b245c 100644 --- a/api_docs/kbn_osquery_io_ts_types.mdx +++ b/api_docs/kbn_osquery_io_ts_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-osquery-io-ts-types title: "@kbn/osquery-io-ts-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/osquery-io-ts-types plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/osquery-io-ts-types'] --- import kbnOsqueryIoTsTypesObj from './kbn_osquery_io_ts_types.devdocs.json'; diff --git a/api_docs/kbn_panel_loader.mdx b/api_docs/kbn_panel_loader.mdx index ef342a31fa9e9..13c370601d475 100644 --- a/api_docs/kbn_panel_loader.mdx +++ b/api_docs/kbn_panel_loader.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-panel-loader title: "@kbn/panel-loader" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/panel-loader plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/panel-loader'] --- import kbnPanelLoaderObj from './kbn_panel_loader.devdocs.json'; diff --git a/api_docs/kbn_performance_testing_dataset_extractor.mdx b/api_docs/kbn_performance_testing_dataset_extractor.mdx index 3115d92cca918..a44e491c8d3a3 100644 --- a/api_docs/kbn_performance_testing_dataset_extractor.mdx +++ b/api_docs/kbn_performance_testing_dataset_extractor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-performance-testing-dataset-extractor title: "@kbn/performance-testing-dataset-extractor" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/performance-testing-dataset-extractor plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/performance-testing-dataset-extractor'] --- import kbnPerformanceTestingDatasetExtractorObj from './kbn_performance_testing_dataset_extractor.devdocs.json'; diff --git a/api_docs/kbn_plugin_check.mdx b/api_docs/kbn_plugin_check.mdx index 70c0cd1635403..b8d5a7807394b 100644 --- a/api_docs/kbn_plugin_check.mdx +++ b/api_docs/kbn_plugin_check.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-plugin-check title: "@kbn/plugin-check" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/plugin-check plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/plugin-check'] --- import kbnPluginCheckObj from './kbn_plugin_check.devdocs.json'; diff --git a/api_docs/kbn_plugin_generator.mdx b/api_docs/kbn_plugin_generator.mdx index b7272bf02596d..65e7c98c7b039 100644 --- a/api_docs/kbn_plugin_generator.mdx +++ b/api_docs/kbn_plugin_generator.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-plugin-generator title: "@kbn/plugin-generator" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/plugin-generator plugin -date: 2024-05-16 +date: 2024-05-17 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 2dc3d4b1f5564..3c4eeaf583bd7 100644 --- a/api_docs/kbn_plugin_helpers.mdx +++ b/api_docs/kbn_plugin_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-plugin-helpers title: "@kbn/plugin-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/plugin-helpers plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/plugin-helpers'] --- import kbnPluginHelpersObj from './kbn_plugin_helpers.devdocs.json'; diff --git a/api_docs/kbn_presentation_containers.mdx b/api_docs/kbn_presentation_containers.mdx index 5c5db58273a13..840eec03bb9cb 100644 --- a/api_docs/kbn_presentation_containers.mdx +++ b/api_docs/kbn_presentation_containers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-presentation-containers title: "@kbn/presentation-containers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/presentation-containers plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/presentation-containers'] --- import kbnPresentationContainersObj from './kbn_presentation_containers.devdocs.json'; diff --git a/api_docs/kbn_presentation_publishing.mdx b/api_docs/kbn_presentation_publishing.mdx index 1d19fc6153c52..f7a3ee02052bc 100644 --- a/api_docs/kbn_presentation_publishing.mdx +++ b/api_docs/kbn_presentation_publishing.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-presentation-publishing title: "@kbn/presentation-publishing" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/presentation-publishing plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/presentation-publishing'] --- import kbnPresentationPublishingObj from './kbn_presentation_publishing.devdocs.json'; diff --git a/api_docs/kbn_profiling_utils.mdx b/api_docs/kbn_profiling_utils.mdx index b3473decf8180..4c5d579d8e0ea 100644 --- a/api_docs/kbn_profiling_utils.mdx +++ b/api_docs/kbn_profiling_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-profiling-utils title: "@kbn/profiling-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/profiling-utils plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/profiling-utils'] --- import kbnProfilingUtilsObj from './kbn_profiling_utils.devdocs.json'; diff --git a/api_docs/kbn_random_sampling.mdx b/api_docs/kbn_random_sampling.mdx index d6dff54af4bfc..75eaac5c950b5 100644 --- a/api_docs/kbn_random_sampling.mdx +++ b/api_docs/kbn_random_sampling.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-random-sampling title: "@kbn/random-sampling" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/random-sampling plugin -date: 2024-05-16 +date: 2024-05-17 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 b95dab9985f24..076f18c6b1c04 100644 --- a/api_docs/kbn_react_field.mdx +++ b/api_docs/kbn_react_field.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-react-field title: "@kbn/react-field" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/react-field plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/react-field'] --- import kbnReactFieldObj from './kbn_react_field.devdocs.json'; diff --git a/api_docs/kbn_react_hooks.mdx b/api_docs/kbn_react_hooks.mdx index d2ff18342228f..08f8a5afa177b 100644 --- a/api_docs/kbn_react_hooks.mdx +++ b/api_docs/kbn_react_hooks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-react-hooks title: "@kbn/react-hooks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/react-hooks plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/react-hooks'] --- import kbnReactHooksObj from './kbn_react_hooks.devdocs.json'; diff --git a/api_docs/kbn_react_kibana_context_common.mdx b/api_docs/kbn_react_kibana_context_common.mdx index 3d38276562ee3..2246b0c439f93 100644 --- a/api_docs/kbn_react_kibana_context_common.mdx +++ b/api_docs/kbn_react_kibana_context_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-react-kibana-context-common title: "@kbn/react-kibana-context-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/react-kibana-context-common plugin -date: 2024-05-16 +date: 2024-05-17 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 1a02d530677ff..7979c997747f9 100644 --- a/api_docs/kbn_react_kibana_context_render.mdx +++ b/api_docs/kbn_react_kibana_context_render.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-react-kibana-context-render title: "@kbn/react-kibana-context-render" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/react-kibana-context-render plugin -date: 2024-05-16 +date: 2024-05-17 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 f211ee67186c1..f38620267378c 100644 --- a/api_docs/kbn_react_kibana_context_root.mdx +++ b/api_docs/kbn_react_kibana_context_root.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-react-kibana-context-root title: "@kbn/react-kibana-context-root" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/react-kibana-context-root plugin -date: 2024-05-16 +date: 2024-05-17 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 939b04a827589..0b091edb14b97 100644 --- a/api_docs/kbn_react_kibana_context_styled.mdx +++ b/api_docs/kbn_react_kibana_context_styled.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-react-kibana-context-styled title: "@kbn/react-kibana-context-styled" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/react-kibana-context-styled plugin -date: 2024-05-16 +date: 2024-05-17 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 f16b1d5406a9b..07257e9fbc75d 100644 --- a/api_docs/kbn_react_kibana_context_theme.mdx +++ b/api_docs/kbn_react_kibana_context_theme.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-react-kibana-context-theme title: "@kbn/react-kibana-context-theme" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/react-kibana-context-theme plugin -date: 2024-05-16 +date: 2024-05-17 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 8e79c9fa63789..bb8079ef191ec 100644 --- a/api_docs/kbn_react_kibana_mount.mdx +++ b/api_docs/kbn_react_kibana_mount.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-react-kibana-mount title: "@kbn/react-kibana-mount" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/react-kibana-mount plugin -date: 2024-05-16 +date: 2024-05-17 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 99213d80d4b0c..dcfacf132e61e 100644 --- a/api_docs/kbn_repo_file_maps.mdx +++ b/api_docs/kbn_repo_file_maps.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-repo-file-maps title: "@kbn/repo-file-maps" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/repo-file-maps plugin -date: 2024-05-16 +date: 2024-05-17 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 19a4ffd6a4797..68f966745a9ec 100644 --- a/api_docs/kbn_repo_linter.mdx +++ b/api_docs/kbn_repo_linter.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-repo-linter title: "@kbn/repo-linter" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/repo-linter plugin -date: 2024-05-16 +date: 2024-05-17 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 f8081532d763c..0417a37f7539e 100644 --- a/api_docs/kbn_repo_path.mdx +++ b/api_docs/kbn_repo_path.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-repo-path title: "@kbn/repo-path" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/repo-path plugin -date: 2024-05-16 +date: 2024-05-17 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 01da4c545fd1b..1774ed88835c7 100644 --- a/api_docs/kbn_repo_source_classifier.mdx +++ b/api_docs/kbn_repo_source_classifier.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-repo-source-classifier title: "@kbn/repo-source-classifier" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/repo-source-classifier plugin -date: 2024-05-16 +date: 2024-05-17 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 cb3e30a4c8bdc..6b6e08cd517ac 100644 --- a/api_docs/kbn_reporting_common.mdx +++ b/api_docs/kbn_reporting_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-reporting-common title: "@kbn/reporting-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/reporting-common plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-common'] --- import kbnReportingCommonObj from './kbn_reporting_common.devdocs.json'; diff --git a/api_docs/kbn_reporting_csv_share_panel.mdx b/api_docs/kbn_reporting_csv_share_panel.mdx index 5f62dc6463774..9a6ee5f3e5f3d 100644 --- a/api_docs/kbn_reporting_csv_share_panel.mdx +++ b/api_docs/kbn_reporting_csv_share_panel.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-reporting-csv-share-panel title: "@kbn/reporting-csv-share-panel" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/reporting-csv-share-panel plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-csv-share-panel'] --- import kbnReportingCsvSharePanelObj from './kbn_reporting_csv_share_panel.devdocs.json'; diff --git a/api_docs/kbn_reporting_export_types_csv.mdx b/api_docs/kbn_reporting_export_types_csv.mdx index 834913754d3e9..ee4ec1dde186f 100644 --- a/api_docs/kbn_reporting_export_types_csv.mdx +++ b/api_docs/kbn_reporting_export_types_csv.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-reporting-export-types-csv title: "@kbn/reporting-export-types-csv" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/reporting-export-types-csv plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-export-types-csv'] --- import kbnReportingExportTypesCsvObj from './kbn_reporting_export_types_csv.devdocs.json'; diff --git a/api_docs/kbn_reporting_export_types_csv_common.mdx b/api_docs/kbn_reporting_export_types_csv_common.mdx index f1993c9dc6974..41d11899a42af 100644 --- a/api_docs/kbn_reporting_export_types_csv_common.mdx +++ b/api_docs/kbn_reporting_export_types_csv_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-reporting-export-types-csv-common title: "@kbn/reporting-export-types-csv-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/reporting-export-types-csv-common plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-export-types-csv-common'] --- import kbnReportingExportTypesCsvCommonObj from './kbn_reporting_export_types_csv_common.devdocs.json'; diff --git a/api_docs/kbn_reporting_export_types_pdf.mdx b/api_docs/kbn_reporting_export_types_pdf.mdx index 0baedd862b84b..d1d6055b499da 100644 --- a/api_docs/kbn_reporting_export_types_pdf.mdx +++ b/api_docs/kbn_reporting_export_types_pdf.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-reporting-export-types-pdf title: "@kbn/reporting-export-types-pdf" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/reporting-export-types-pdf plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-export-types-pdf'] --- import kbnReportingExportTypesPdfObj from './kbn_reporting_export_types_pdf.devdocs.json'; diff --git a/api_docs/kbn_reporting_export_types_pdf_common.mdx b/api_docs/kbn_reporting_export_types_pdf_common.mdx index 55d777ede8542..645b55ac68d01 100644 --- a/api_docs/kbn_reporting_export_types_pdf_common.mdx +++ b/api_docs/kbn_reporting_export_types_pdf_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-reporting-export-types-pdf-common title: "@kbn/reporting-export-types-pdf-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/reporting-export-types-pdf-common plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-export-types-pdf-common'] --- import kbnReportingExportTypesPdfCommonObj from './kbn_reporting_export_types_pdf_common.devdocs.json'; diff --git a/api_docs/kbn_reporting_export_types_png.mdx b/api_docs/kbn_reporting_export_types_png.mdx index 72cbe897839b5..58623b4f50029 100644 --- a/api_docs/kbn_reporting_export_types_png.mdx +++ b/api_docs/kbn_reporting_export_types_png.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-reporting-export-types-png title: "@kbn/reporting-export-types-png" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/reporting-export-types-png plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-export-types-png'] --- import kbnReportingExportTypesPngObj from './kbn_reporting_export_types_png.devdocs.json'; diff --git a/api_docs/kbn_reporting_export_types_png_common.mdx b/api_docs/kbn_reporting_export_types_png_common.mdx index 917278e0379be..382a175012340 100644 --- a/api_docs/kbn_reporting_export_types_png_common.mdx +++ b/api_docs/kbn_reporting_export_types_png_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-reporting-export-types-png-common title: "@kbn/reporting-export-types-png-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/reporting-export-types-png-common plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-export-types-png-common'] --- import kbnReportingExportTypesPngCommonObj from './kbn_reporting_export_types_png_common.devdocs.json'; diff --git a/api_docs/kbn_reporting_mocks_server.mdx b/api_docs/kbn_reporting_mocks_server.mdx index f4c24fbe6e150..6febd41dd4a3f 100644 --- a/api_docs/kbn_reporting_mocks_server.mdx +++ b/api_docs/kbn_reporting_mocks_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-reporting-mocks-server title: "@kbn/reporting-mocks-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/reporting-mocks-server plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-mocks-server'] --- import kbnReportingMocksServerObj from './kbn_reporting_mocks_server.devdocs.json'; diff --git a/api_docs/kbn_reporting_public.mdx b/api_docs/kbn_reporting_public.mdx index 4271e03b4adbd..4aea2a32ee902 100644 --- a/api_docs/kbn_reporting_public.mdx +++ b/api_docs/kbn_reporting_public.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-reporting-public title: "@kbn/reporting-public" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/reporting-public plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-public'] --- import kbnReportingPublicObj from './kbn_reporting_public.devdocs.json'; diff --git a/api_docs/kbn_reporting_server.mdx b/api_docs/kbn_reporting_server.mdx index 5b1f1cbb75d4b..f41f3aefbdc71 100644 --- a/api_docs/kbn_reporting_server.mdx +++ b/api_docs/kbn_reporting_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-reporting-server title: "@kbn/reporting-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/reporting-server plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-server'] --- import kbnReportingServerObj from './kbn_reporting_server.devdocs.json'; diff --git a/api_docs/kbn_resizable_layout.mdx b/api_docs/kbn_resizable_layout.mdx index 697ee4e73a921..0d6cc96a8303c 100644 --- a/api_docs/kbn_resizable_layout.mdx +++ b/api_docs/kbn_resizable_layout.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-resizable-layout title: "@kbn/resizable-layout" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/resizable-layout plugin -date: 2024-05-16 +date: 2024-05-17 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 f9b9e50825e7f..3a25e6066e2e5 100644 --- a/api_docs/kbn_rison.mdx +++ b/api_docs/kbn_rison.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-rison title: "@kbn/rison" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/rison plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/rison'] --- import kbnRisonObj from './kbn_rison.devdocs.json'; diff --git a/api_docs/kbn_router_to_openapispec.mdx b/api_docs/kbn_router_to_openapispec.mdx index 1b70f82179fcf..b6bc3d26a2e6d 100644 --- a/api_docs/kbn_router_to_openapispec.mdx +++ b/api_docs/kbn_router_to_openapispec.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-router-to-openapispec title: "@kbn/router-to-openapispec" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/router-to-openapispec plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/router-to-openapispec'] --- import kbnRouterToOpenapispecObj from './kbn_router_to_openapispec.devdocs.json'; diff --git a/api_docs/kbn_router_utils.mdx b/api_docs/kbn_router_utils.mdx index 3ac83c9da4088..7fea2af26040a 100644 --- a/api_docs/kbn_router_utils.mdx +++ b/api_docs/kbn_router_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-router-utils title: "@kbn/router-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/router-utils plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/router-utils'] --- import kbnRouterUtilsObj from './kbn_router_utils.devdocs.json'; diff --git a/api_docs/kbn_rrule.mdx b/api_docs/kbn_rrule.mdx index 65435c955102a..91d869e6d8495 100644 --- a/api_docs/kbn_rrule.mdx +++ b/api_docs/kbn_rrule.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-rrule title: "@kbn/rrule" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/rrule plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/rrule'] --- import kbnRruleObj from './kbn_rrule.devdocs.json'; diff --git a/api_docs/kbn_rule_data_utils.mdx b/api_docs/kbn_rule_data_utils.mdx index fc45e0583c934..bf43222cd3057 100644 --- a/api_docs/kbn_rule_data_utils.mdx +++ b/api_docs/kbn_rule_data_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-rule-data-utils title: "@kbn/rule-data-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/rule-data-utils plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/rule-data-utils'] --- import kbnRuleDataUtilsObj from './kbn_rule_data_utils.devdocs.json'; diff --git a/api_docs/kbn_saved_objects_settings.mdx b/api_docs/kbn_saved_objects_settings.mdx index 3a04b271ffa77..a06c844bb8e3e 100644 --- a/api_docs/kbn_saved_objects_settings.mdx +++ b/api_docs/kbn_saved_objects_settings.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-saved-objects-settings title: "@kbn/saved-objects-settings" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/saved-objects-settings plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/saved-objects-settings'] --- import kbnSavedObjectsSettingsObj from './kbn_saved_objects_settings.devdocs.json'; diff --git a/api_docs/kbn_search_api_panels.devdocs.json b/api_docs/kbn_search_api_panels.devdocs.json index 6b64604da0fec..3e17ad34f9985 100644 --- a/api_docs/kbn_search_api_panels.devdocs.json +++ b/api_docs/kbn_search_api_panels.devdocs.json @@ -326,7 +326,7 @@ "label": "IngestData", "description": [], "signature": [ - "({ codeSnippet, selectedLanguage, setSelectedLanguage, docLinks, assetBasePath, application, consolePlugin, sharePlugin, languages, consoleRequest, additionalIngestionPanel, }: React.PropsWithChildren) => JSX.Element" + "({ codeSnippet, selectedLanguage, selectedPipeline, setSelectedLanguage, docLinks, assetBasePath, application, consolePlugin, sharePlugin, languages, consoleRequest, additionalIngestionPanel, ingestPipelineData, setSelectedPipeline, defaultIngestPipeline, }: React.PropsWithChildren) => JSX.Element" ], "path": "packages/kbn-search-api-panels/components/ingest_data.tsx", "deprecated": false, @@ -337,7 +337,7 @@ "id": "def-common.IngestData.$1", "type": "CompoundType", "tags": [], - "label": "{\n codeSnippet,\n selectedLanguage,\n setSelectedLanguage,\n docLinks,\n assetBasePath,\n application,\n consolePlugin,\n sharePlugin,\n languages,\n consoleRequest,\n additionalIngestionPanel,\n}", + "label": "{\n codeSnippet,\n selectedLanguage,\n selectedPipeline,\n setSelectedLanguage,\n docLinks,\n assetBasePath,\n application,\n consolePlugin,\n sharePlugin,\n languages,\n consoleRequest,\n additionalIngestionPanel,\n ingestPipelineData,\n setSelectedPipeline,\n defaultIngestPipeline,\n}", "description": [], "signature": [ "React.PropsWithChildren" @@ -384,6 +384,39 @@ "returnComment": [], "initialIsOpen": false }, + { + "parentPluginId": "@kbn/search-api-panels", + "id": "def-common.IngestPipelinePanel", + "type": "Function", + "tags": [], + "label": "IngestPipelinePanel", + "description": [], + "signature": [ + "({ selectedPipeline, setSelectedPipeline, ingestPipelinesData, defaultIngestPipeline, }: React.PropsWithChildren) => JSX.Element" + ], + "path": "packages/kbn-search-api-panels/components/ingest_pipelines/ingest_pipeline_panel.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/search-api-panels", + "id": "def-common.IngestPipelinePanel.$1", + "type": "CompoundType", + "tags": [], + "label": "{\n selectedPipeline,\n setSelectedPipeline,\n ingestPipelinesData,\n defaultIngestPipeline,\n}", + "description": [], + "signature": [ + "React.PropsWithChildren" + ], + "path": "packages/kbn-search-api-panels/components/ingest_pipelines/ingest_pipeline_panel.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, { "parentPluginId": "@kbn/search-api-panels", "id": "def-common.InstallClientPanel", diff --git a/api_docs/kbn_search_api_panels.mdx b/api_docs/kbn_search_api_panels.mdx index 0761b37a04863..61f63e012b7a4 100644 --- a/api_docs/kbn_search_api_panels.mdx +++ b/api_docs/kbn_search_api_panels.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-search-api-panels title: "@kbn/search-api-panels" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/search-api-panels plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/search-api-panels'] --- import kbnSearchApiPanelsObj from './kbn_search_api_panels.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/enterprise-search-frontend](https://github.com/orgs/elastic/te | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 74 | 0 | 74 | 0 | +| 76 | 0 | 76 | 0 | ## Common diff --git a/api_docs/kbn_search_connectors.devdocs.json b/api_docs/kbn_search_connectors.devdocs.json index 1536cc0f405c5..703be6afbdcd4 100644 --- a/api_docs/kbn_search_connectors.devdocs.json +++ b/api_docs/kbn_search_connectors.devdocs.json @@ -2643,15 +2643,7 @@ "section": "def-common.ElasticsearchClient", "text": "ElasticsearchClient" }, - ", connectorId: string, { advancedSnippet, filteringRules, }: { advancedSnippet: string; filteringRules: ", - { - "pluginId": "@kbn/search-connectors", - "scope": "common", - "docId": "kibKbnSearchConnectorsPluginApi", - "section": "def-common.FilteringRule", - "text": "FilteringRule" - }, - "[]; }) => Promise<", + ", connectorId: string) => Promise<", { "pluginId": "@kbn/search-connectors", "scope": "common", @@ -2700,51 +2692,6 @@ "deprecated": false, "trackAdoption": false, "isRequired": true - }, - { - "parentPluginId": "@kbn/search-connectors", - "id": "def-common.updateFiltering.$3", - "type": "Object", - "tags": [], - "label": "{\n advancedSnippet,\n filteringRules,\n }", - "description": [], - "path": "packages/kbn-search-connectors/lib/update_filtering.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "@kbn/search-connectors", - "id": "def-common.updateFiltering.$3.advancedSnippet", - "type": "string", - "tags": [], - "label": "advancedSnippet", - "description": [], - "path": "packages/kbn-search-connectors/lib/update_filtering.ts", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "@kbn/search-connectors", - "id": "def-common.updateFiltering.$3.filteringRules", - "type": "Array", - "tags": [], - "label": "filteringRules", - "description": [], - "signature": [ - { - "pluginId": "@kbn/search-connectors", - "scope": "common", - "docId": "kibKbnSearchConnectorsPluginApi", - "section": "def-common.FilteringRule", - "text": "FilteringRule" - }, - "[]" - ], - "path": "packages/kbn-search-connectors/lib/update_filtering.ts", - "deprecated": false, - "trackAdoption": false - } - ] } ], "returnComment": [], @@ -45942,6 +45889,206 @@ } ] }, + { + "parentPluginId": "@kbn/search-connectors", + "id": "def-common.NATIVE_CONNECTOR_DEFINITIONS.salesforce.configuration.use_document_level_security", + "type": "Object", + "tags": [], + "label": "use_document_level_security", + "description": [], + "path": "packages/kbn-search-connectors/types/native_connectors.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/search-connectors", + "id": "def-common.NATIVE_CONNECTOR_DEFINITIONS.salesforce.configuration.use_document_level_security.default_value", + "type": "Uncategorized", + "tags": [], + "label": "default_value", + "description": [], + "signature": [ + "null" + ], + "path": "packages/kbn-search-connectors/types/native_connectors.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/search-connectors", + "id": "def-common.NATIVE_CONNECTOR_DEFINITIONS.salesforce.configuration.use_document_level_security.depends_on", + "type": "Array", + "tags": [], + "label": "depends_on", + "description": [], + "signature": [ + "never[]" + ], + "path": "packages/kbn-search-connectors/types/native_connectors.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/search-connectors", + "id": "def-common.NATIVE_CONNECTOR_DEFINITIONS.salesforce.configuration.use_document_level_security.display", + "type": "string", + "tags": [], + "label": "display", + "description": [], + "signature": [ + { + "pluginId": "@kbn/search-connectors", + "scope": "common", + "docId": "kibKbnSearchConnectorsPluginApi", + "section": "def-common.DisplayType", + "text": "DisplayType" + }, + ".TOGGLE" + ], + "path": "packages/kbn-search-connectors/types/native_connectors.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/search-connectors", + "id": "def-common.NATIVE_CONNECTOR_DEFINITIONS.salesforce.configuration.use_document_level_security.label", + "type": "string", + "tags": [], + "label": "label", + "description": [], + "path": "packages/kbn-search-connectors/types/native_connectors.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/search-connectors", + "id": "def-common.NATIVE_CONNECTOR_DEFINITIONS.salesforce.configuration.use_document_level_security.options", + "type": "Array", + "tags": [], + "label": "options", + "description": [], + "signature": [ + "never[]" + ], + "path": "packages/kbn-search-connectors/types/native_connectors.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/search-connectors", + "id": "def-common.NATIVE_CONNECTOR_DEFINITIONS.salesforce.configuration.use_document_level_security.order", + "type": "number", + "tags": [], + "label": "order", + "description": [], + "path": "packages/kbn-search-connectors/types/native_connectors.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/search-connectors", + "id": "def-common.NATIVE_CONNECTOR_DEFINITIONS.salesforce.configuration.use_document_level_security.required", + "type": "boolean", + "tags": [], + "label": "required", + "description": [], + "signature": [ + "true" + ], + "path": "packages/kbn-search-connectors/types/native_connectors.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/search-connectors", + "id": "def-common.NATIVE_CONNECTOR_DEFINITIONS.salesforce.configuration.use_document_level_security.sensitive", + "type": "boolean", + "tags": [], + "label": "sensitive", + "description": [], + "signature": [ + "false" + ], + "path": "packages/kbn-search-connectors/types/native_connectors.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/search-connectors", + "id": "def-common.NATIVE_CONNECTOR_DEFINITIONS.salesforce.configuration.use_document_level_security.tooltip", + "type": "string", + "tags": [], + "label": "tooltip", + "description": [], + "path": "packages/kbn-search-connectors/types/native_connectors.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/search-connectors", + "id": "def-common.NATIVE_CONNECTOR_DEFINITIONS.salesforce.configuration.use_document_level_security.type", + "type": "string", + "tags": [], + "label": "type", + "description": [], + "signature": [ + { + "pluginId": "@kbn/search-connectors", + "scope": "common", + "docId": "kibKbnSearchConnectorsPluginApi", + "section": "def-common.FieldType", + "text": "FieldType" + }, + ".BOOLEAN" + ], + "path": "packages/kbn-search-connectors/types/native_connectors.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/search-connectors", + "id": "def-common.NATIVE_CONNECTOR_DEFINITIONS.salesforce.configuration.use_document_level_security.ui_restrictions", + "type": "Array", + "tags": [], + "label": "ui_restrictions", + "description": [], + "signature": [ + "never[]" + ], + "path": "packages/kbn-search-connectors/types/native_connectors.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/search-connectors", + "id": "def-common.NATIVE_CONNECTOR_DEFINITIONS.salesforce.configuration.use_document_level_security.validations", + "type": "Array", + "tags": [], + "label": "validations", + "description": [], + "signature": [ + "never[]" + ], + "path": "packages/kbn-search-connectors/types/native_connectors.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/search-connectors", + "id": "def-common.NATIVE_CONNECTOR_DEFINITIONS.salesforce.configuration.use_document_level_security.value", + "type": "boolean", + "tags": [], + "label": "value", + "description": [], + "signature": [ + "false" + ], + "path": "packages/kbn-search-connectors/types/native_connectors.ts", + "deprecated": false, + "trackAdoption": false + } + ] + }, { "parentPluginId": "@kbn/search-connectors", "id": "def-common.NATIVE_CONNECTOR_DEFINITIONS.salesforce.configuration.use_text_extraction_service", diff --git a/api_docs/kbn_search_connectors.mdx b/api_docs/kbn_search_connectors.mdx index 9e5db9a384896..5ed11e321eb61 100644 --- a/api_docs/kbn_search_connectors.mdx +++ b/api_docs/kbn_search_connectors.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-search-connectors title: "@kbn/search-connectors" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/search-connectors plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/search-connectors'] --- import kbnSearchConnectorsObj from './kbn_search_connectors.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/enterprise-search-frontend](https://github.com/orgs/elastic/te | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 3661 | 0 | 3661 | 0 | +| 3672 | 0 | 3672 | 0 | ## Common diff --git a/api_docs/kbn_search_errors.mdx b/api_docs/kbn_search_errors.mdx index bfef1bd8b3aea..984025b7d06e7 100644 --- a/api_docs/kbn_search_errors.mdx +++ b/api_docs/kbn_search_errors.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-search-errors title: "@kbn/search-errors" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/search-errors plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/search-errors'] --- import kbnSearchErrorsObj from './kbn_search_errors.devdocs.json'; diff --git a/api_docs/kbn_search_index_documents.mdx b/api_docs/kbn_search_index_documents.mdx index 984eabeb4f418..a9b26f8c602ec 100644 --- a/api_docs/kbn_search_index_documents.mdx +++ b/api_docs/kbn_search_index_documents.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-search-index-documents title: "@kbn/search-index-documents" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/search-index-documents plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/search-index-documents'] --- import kbnSearchIndexDocumentsObj from './kbn_search_index_documents.devdocs.json'; diff --git a/api_docs/kbn_search_response_warnings.mdx b/api_docs/kbn_search_response_warnings.mdx index 490d1081a6e8a..d58b65eb56578 100644 --- a/api_docs/kbn_search_response_warnings.mdx +++ b/api_docs/kbn_search_response_warnings.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-search-response-warnings title: "@kbn/search-response-warnings" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/search-response-warnings plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/search-response-warnings'] --- import kbnSearchResponseWarningsObj from './kbn_search_response_warnings.devdocs.json'; diff --git a/api_docs/kbn_search_types.mdx b/api_docs/kbn_search_types.mdx index 387775730d6cf..bcb46438310cc 100644 --- a/api_docs/kbn_search_types.mdx +++ b/api_docs/kbn_search_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-search-types title: "@kbn/search-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/search-types plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/search-types'] --- import kbnSearchTypesObj from './kbn_search_types.devdocs.json'; diff --git a/api_docs/kbn_security_hardening.mdx b/api_docs/kbn_security_hardening.mdx index 1211f3deb9f7f..94deed4ec4598 100644 --- a/api_docs/kbn_security_hardening.mdx +++ b/api_docs/kbn_security_hardening.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-security-hardening title: "@kbn/security-hardening" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/security-hardening plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-hardening'] --- import kbnSecurityHardeningObj from './kbn_security_hardening.devdocs.json'; diff --git a/api_docs/kbn_security_plugin_types_common.mdx b/api_docs/kbn_security_plugin_types_common.mdx index 1fae3b2181779..89d6e4fc0fa13 100644 --- a/api_docs/kbn_security_plugin_types_common.mdx +++ b/api_docs/kbn_security_plugin_types_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-security-plugin-types-common title: "@kbn/security-plugin-types-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/security-plugin-types-common plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-plugin-types-common'] --- import kbnSecurityPluginTypesCommonObj from './kbn_security_plugin_types_common.devdocs.json'; diff --git a/api_docs/kbn_security_plugin_types_public.mdx b/api_docs/kbn_security_plugin_types_public.mdx index f7e6285fa9233..70ba64c9ab624 100644 --- a/api_docs/kbn_security_plugin_types_public.mdx +++ b/api_docs/kbn_security_plugin_types_public.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-security-plugin-types-public title: "@kbn/security-plugin-types-public" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/security-plugin-types-public plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-plugin-types-public'] --- import kbnSecurityPluginTypesPublicObj from './kbn_security_plugin_types_public.devdocs.json'; diff --git a/api_docs/kbn_security_plugin_types_server.mdx b/api_docs/kbn_security_plugin_types_server.mdx index c3098606794d2..c8834e98b44f3 100644 --- a/api_docs/kbn_security_plugin_types_server.mdx +++ b/api_docs/kbn_security_plugin_types_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-security-plugin-types-server title: "@kbn/security-plugin-types-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/security-plugin-types-server plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-plugin-types-server'] --- import kbnSecurityPluginTypesServerObj from './kbn_security_plugin_types_server.devdocs.json'; diff --git a/api_docs/kbn_security_solution_features.mdx b/api_docs/kbn_security_solution_features.mdx index d119d9d2c72d5..f3442ad45f12b 100644 --- a/api_docs/kbn_security_solution_features.mdx +++ b/api_docs/kbn_security_solution_features.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-security-solution-features title: "@kbn/security-solution-features" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/security-solution-features plugin -date: 2024-05-16 +date: 2024-05-17 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 21a0574be4cf1..cb475dad3ad2f 100644 --- a/api_docs/kbn_security_solution_navigation.mdx +++ b/api_docs/kbn_security_solution_navigation.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-security-solution-navigation title: "@kbn/security-solution-navigation" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/security-solution-navigation plugin -date: 2024-05-16 +date: 2024-05-17 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 63fdbc46a818b..7b7a9bfa7808c 100644 --- a/api_docs/kbn_security_solution_side_nav.mdx +++ b/api_docs/kbn_security_solution_side_nav.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-security-solution-side-nav title: "@kbn/security-solution-side-nav" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/security-solution-side-nav plugin -date: 2024-05-16 +date: 2024-05-17 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 10fedf5ce7e76..96e2ebca3d22e 100644 --- a/api_docs/kbn_security_solution_storybook_config.mdx +++ b/api_docs/kbn_security_solution_storybook_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-security-solution-storybook-config title: "@kbn/security-solution-storybook-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/security-solution-storybook-config plugin -date: 2024-05-16 +date: 2024-05-17 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 4702520018bdd..30e170f3cf2cf 100644 --- a/api_docs/kbn_securitysolution_autocomplete.mdx +++ b/api_docs/kbn_securitysolution_autocomplete.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-autocomplete title: "@kbn/securitysolution-autocomplete" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-autocomplete plugin -date: 2024-05-16 +date: 2024-05-17 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 ebc9a026ea74f..5f658ed3e12df 100644 --- a/api_docs/kbn_securitysolution_data_table.mdx +++ b/api_docs/kbn_securitysolution_data_table.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-data-table title: "@kbn/securitysolution-data-table" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-data-table plugin -date: 2024-05-16 +date: 2024-05-17 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 0f486cabed185..60aa38c8a7a96 100644 --- a/api_docs/kbn_securitysolution_ecs.mdx +++ b/api_docs/kbn_securitysolution_ecs.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-ecs title: "@kbn/securitysolution-ecs" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-ecs plugin -date: 2024-05-16 +date: 2024-05-17 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 4506b13a9fa35..150892b1a83b9 100644 --- a/api_docs/kbn_securitysolution_es_utils.mdx +++ b/api_docs/kbn_securitysolution_es_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-es-utils title: "@kbn/securitysolution-es-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-es-utils plugin -date: 2024-05-16 +date: 2024-05-17 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 dd3be276a74ce..023bbf4aeee19 100644 --- a/api_docs/kbn_securitysolution_exception_list_components.mdx +++ b/api_docs/kbn_securitysolution_exception_list_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-exception-list-components title: "@kbn/securitysolution-exception-list-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-exception-list-components plugin -date: 2024-05-16 +date: 2024-05-17 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 83a4fa2286df8..8a1874fe8b814 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: 2024-05-16 +date: 2024-05-17 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 f21facb7dacf1..8e604d51e2470 100644 --- a/api_docs/kbn_securitysolution_hook_utils.mdx +++ b/api_docs/kbn_securitysolution_hook_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-hook-utils title: "@kbn/securitysolution-hook-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-hook-utils plugin -date: 2024-05-16 +date: 2024-05-17 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 baae394990f71..a62bdb48a0f09 100644 --- a/api_docs/kbn_securitysolution_io_ts_alerting_types.mdx +++ b/api_docs/kbn_securitysolution_io_ts_alerting_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-io-ts-alerting-types title: "@kbn/securitysolution-io-ts-alerting-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-io-ts-alerting-types plugin -date: 2024-05-16 +date: 2024-05-17 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 4142401c57e43..faa08f94d3118 100644 --- a/api_docs/kbn_securitysolution_io_ts_list_types.mdx +++ b/api_docs/kbn_securitysolution_io_ts_list_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-io-ts-list-types title: "@kbn/securitysolution-io-ts-list-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-io-ts-list-types plugin -date: 2024-05-16 +date: 2024-05-17 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 9440ca4903a74..12815e0c764dd 100644 --- a/api_docs/kbn_securitysolution_io_ts_types.mdx +++ b/api_docs/kbn_securitysolution_io_ts_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-io-ts-types title: "@kbn/securitysolution-io-ts-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-io-ts-types plugin -date: 2024-05-16 +date: 2024-05-17 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 56497662d301e..e38be73a94349 100644 --- a/api_docs/kbn_securitysolution_io_ts_utils.mdx +++ b/api_docs/kbn_securitysolution_io_ts_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-io-ts-utils title: "@kbn/securitysolution-io-ts-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-io-ts-utils plugin -date: 2024-05-16 +date: 2024-05-17 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 5f7eff5937ee5..a0457c67c4803 100644 --- a/api_docs/kbn_securitysolution_list_api.mdx +++ b/api_docs/kbn_securitysolution_list_api.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-list-api title: "@kbn/securitysolution-list-api" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-list-api plugin -date: 2024-05-16 +date: 2024-05-17 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 fd2bbf80c087b..e6a41b28a8dd5 100644 --- a/api_docs/kbn_securitysolution_list_constants.mdx +++ b/api_docs/kbn_securitysolution_list_constants.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-list-constants title: "@kbn/securitysolution-list-constants" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-list-constants plugin -date: 2024-05-16 +date: 2024-05-17 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 f1004ec7b35de..d5fa741e96602 100644 --- a/api_docs/kbn_securitysolution_list_hooks.mdx +++ b/api_docs/kbn_securitysolution_list_hooks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-list-hooks title: "@kbn/securitysolution-list-hooks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-list-hooks plugin -date: 2024-05-16 +date: 2024-05-17 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 bdfa6b9b967ab..94923dc377f94 100644 --- a/api_docs/kbn_securitysolution_list_utils.mdx +++ b/api_docs/kbn_securitysolution_list_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-list-utils title: "@kbn/securitysolution-list-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-list-utils plugin -date: 2024-05-16 +date: 2024-05-17 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 62ac97e20720e..4f131138cc71a 100644 --- a/api_docs/kbn_securitysolution_rules.mdx +++ b/api_docs/kbn_securitysolution_rules.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-rules title: "@kbn/securitysolution-rules" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-rules plugin -date: 2024-05-16 +date: 2024-05-17 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 a019393fea119..5f11ec521639a 100644 --- a/api_docs/kbn_securitysolution_t_grid.mdx +++ b/api_docs/kbn_securitysolution_t_grid.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-t-grid title: "@kbn/securitysolution-t-grid" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-t-grid plugin -date: 2024-05-16 +date: 2024-05-17 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 1735a03457eb9..4e4ebe2b8e153 100644 --- a/api_docs/kbn_securitysolution_utils.mdx +++ b/api_docs/kbn_securitysolution_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-utils title: "@kbn/securitysolution-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-utils plugin -date: 2024-05-16 +date: 2024-05-17 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 262e529fa13aa..86c4d69b3efd5 100644 --- a/api_docs/kbn_server_http_tools.mdx +++ b/api_docs/kbn_server_http_tools.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-server-http-tools title: "@kbn/server-http-tools" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/server-http-tools plugin -date: 2024-05-16 +date: 2024-05-17 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 1db39cadbf035..2e31210d23d62 100644 --- a/api_docs/kbn_server_route_repository.mdx +++ b/api_docs/kbn_server_route_repository.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-server-route-repository title: "@kbn/server-route-repository" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/server-route-repository plugin -date: 2024-05-16 +date: 2024-05-17 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 22a9f74217185..380c44789901c 100644 --- a/api_docs/kbn_serverless_common_settings.mdx +++ b/api_docs/kbn_serverless_common_settings.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-serverless-common-settings title: "@kbn/serverless-common-settings" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/serverless-common-settings plugin -date: 2024-05-16 +date: 2024-05-17 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 e977a2820cdb7..58bf802d7d92f 100644 --- a/api_docs/kbn_serverless_observability_settings.mdx +++ b/api_docs/kbn_serverless_observability_settings.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-serverless-observability-settings title: "@kbn/serverless-observability-settings" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/serverless-observability-settings plugin -date: 2024-05-16 +date: 2024-05-17 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 efaaa4e4114f6..6e7e1d3a1f40c 100644 --- a/api_docs/kbn_serverless_project_switcher.mdx +++ b/api_docs/kbn_serverless_project_switcher.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-serverless-project-switcher title: "@kbn/serverless-project-switcher" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/serverless-project-switcher plugin -date: 2024-05-16 +date: 2024-05-17 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 9a854220887bf..42496b3489c2d 100644 --- a/api_docs/kbn_serverless_search_settings.mdx +++ b/api_docs/kbn_serverless_search_settings.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-serverless-search-settings title: "@kbn/serverless-search-settings" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/serverless-search-settings plugin -date: 2024-05-16 +date: 2024-05-17 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 107e89971e6f6..d3298b2ac803b 100644 --- a/api_docs/kbn_serverless_security_settings.mdx +++ b/api_docs/kbn_serverless_security_settings.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-serverless-security-settings title: "@kbn/serverless-security-settings" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/serverless-security-settings plugin -date: 2024-05-16 +date: 2024-05-17 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 dca21675ec13b..44f0dba92b480 100644 --- a/api_docs/kbn_serverless_storybook_config.mdx +++ b/api_docs/kbn_serverless_storybook_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-serverless-storybook-config title: "@kbn/serverless-storybook-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/serverless-storybook-config plugin -date: 2024-05-16 +date: 2024-05-17 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 98702aa2c1804..fa60e6707fbf9 100644 --- a/api_docs/kbn_shared_svg.mdx +++ b/api_docs/kbn_shared_svg.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-svg title: "@kbn/shared-svg" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-svg plugin -date: 2024-05-16 +date: 2024-05-17 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 3b36ea5d1e9c0..073d802aa91de 100644 --- a/api_docs/kbn_shared_ux_avatar_solution.mdx +++ b/api_docs/kbn_shared_ux_avatar_solution.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-avatar-solution title: "@kbn/shared-ux-avatar-solution" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-avatar-solution plugin -date: 2024-05-16 +date: 2024-05-17 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 a518de989cb57..f50075ed2d474 100644 --- a/api_docs/kbn_shared_ux_button_exit_full_screen.mdx +++ b/api_docs/kbn_shared_ux_button_exit_full_screen.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-button-exit-full-screen title: "@kbn/shared-ux-button-exit-full-screen" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-button-exit-full-screen plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-button-exit-full-screen'] --- import kbnSharedUxButtonExitFullScreenObj from './kbn_shared_ux_button_exit_full_screen.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_button_toolbar.mdx b/api_docs/kbn_shared_ux_button_toolbar.mdx index 1bc4f54b8fa0e..c2ebdf62a81d8 100644 --- a/api_docs/kbn_shared_ux_button_toolbar.mdx +++ b/api_docs/kbn_shared_ux_button_toolbar.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-button-toolbar title: "@kbn/shared-ux-button-toolbar" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-button-toolbar plugin -date: 2024-05-16 +date: 2024-05-17 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 8361a23eb2903..7835d3cdf4d22 100644 --- a/api_docs/kbn_shared_ux_card_no_data.mdx +++ b/api_docs/kbn_shared_ux_card_no_data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-card-no-data title: "@kbn/shared-ux-card-no-data" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-card-no-data plugin -date: 2024-05-16 +date: 2024-05-17 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 35deb9618afa1..956722380965a 100644 --- a/api_docs/kbn_shared_ux_card_no_data_mocks.mdx +++ b/api_docs/kbn_shared_ux_card_no_data_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-card-no-data-mocks title: "@kbn/shared-ux-card-no-data-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-card-no-data-mocks plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-card-no-data-mocks'] --- import kbnSharedUxCardNoDataMocksObj from './kbn_shared_ux_card_no_data_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_chrome_navigation.mdx b/api_docs/kbn_shared_ux_chrome_navigation.mdx index f907c556f1c87..5d44372103f97 100644 --- a/api_docs/kbn_shared_ux_chrome_navigation.mdx +++ b/api_docs/kbn_shared_ux_chrome_navigation.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-chrome-navigation title: "@kbn/shared-ux-chrome-navigation" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-chrome-navigation plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-chrome-navigation'] --- import kbnSharedUxChromeNavigationObj from './kbn_shared_ux_chrome_navigation.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_error_boundary.mdx b/api_docs/kbn_shared_ux_error_boundary.mdx index 4d2f5f1823e80..0f6e6712887e8 100644 --- a/api_docs/kbn_shared_ux_error_boundary.mdx +++ b/api_docs/kbn_shared_ux_error_boundary.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-error-boundary title: "@kbn/shared-ux-error-boundary" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-error-boundary plugin -date: 2024-05-16 +date: 2024-05-17 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 f645cd4d00c9e..3c852594630f1 100644 --- a/api_docs/kbn_shared_ux_file_context.mdx +++ b/api_docs/kbn_shared_ux_file_context.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-context title: "@kbn/shared-ux-file-context" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-context plugin -date: 2024-05-16 +date: 2024-05-17 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 1254ca2154b94..bb3ee8f113b7d 100644 --- a/api_docs/kbn_shared_ux_file_image.mdx +++ b/api_docs/kbn_shared_ux_file_image.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-image title: "@kbn/shared-ux-file-image" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-image plugin -date: 2024-05-16 +date: 2024-05-17 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 a338ea52665e2..b5bd9309f8b18 100644 --- a/api_docs/kbn_shared_ux_file_image_mocks.mdx +++ b/api_docs/kbn_shared_ux_file_image_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-image-mocks title: "@kbn/shared-ux-file-image-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-image-mocks plugin -date: 2024-05-16 +date: 2024-05-17 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 8ef215892bacc..be42cc4157ca2 100644 --- a/api_docs/kbn_shared_ux_file_mocks.mdx +++ b/api_docs/kbn_shared_ux_file_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-mocks title: "@kbn/shared-ux-file-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-mocks plugin -date: 2024-05-16 +date: 2024-05-17 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 45c20f1b23428..0046fb6826ea2 100644 --- a/api_docs/kbn_shared_ux_file_picker.mdx +++ b/api_docs/kbn_shared_ux_file_picker.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-picker title: "@kbn/shared-ux-file-picker" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-picker plugin -date: 2024-05-16 +date: 2024-05-17 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 d0965a9c5c3a0..1b5cb7ae74613 100644 --- a/api_docs/kbn_shared_ux_file_types.mdx +++ b/api_docs/kbn_shared_ux_file_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-types title: "@kbn/shared-ux-file-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-types plugin -date: 2024-05-16 +date: 2024-05-17 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 e7521ef97563c..155ddc0c11d8f 100644 --- a/api_docs/kbn_shared_ux_file_upload.mdx +++ b/api_docs/kbn_shared_ux_file_upload.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-upload title: "@kbn/shared-ux-file-upload" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-upload plugin -date: 2024-05-16 +date: 2024-05-17 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 2d5cea3cf4b74..537e30cbb2d65 100644 --- a/api_docs/kbn_shared_ux_file_util.mdx +++ b/api_docs/kbn_shared_ux_file_util.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-util title: "@kbn/shared-ux-file-util" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-util plugin -date: 2024-05-16 +date: 2024-05-17 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 ebce9336e18f5..b86f71d81beed 100644 --- a/api_docs/kbn_shared_ux_link_redirect_app.mdx +++ b/api_docs/kbn_shared_ux_link_redirect_app.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-link-redirect-app title: "@kbn/shared-ux-link-redirect-app" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-link-redirect-app plugin -date: 2024-05-16 +date: 2024-05-17 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 540063b47b078..09bb430a3aa85 100644 --- a/api_docs/kbn_shared_ux_link_redirect_app_mocks.mdx +++ b/api_docs/kbn_shared_ux_link_redirect_app_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-link-redirect-app-mocks title: "@kbn/shared-ux-link-redirect-app-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-link-redirect-app-mocks plugin -date: 2024-05-16 +date: 2024-05-17 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 0094b649ab73c..5ff6f52d7fe54 100644 --- a/api_docs/kbn_shared_ux_markdown.mdx +++ b/api_docs/kbn_shared_ux_markdown.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-markdown title: "@kbn/shared-ux-markdown" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-markdown plugin -date: 2024-05-16 +date: 2024-05-17 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 549075b984ec6..76e22a9401f24 100644 --- a/api_docs/kbn_shared_ux_markdown_mocks.mdx +++ b/api_docs/kbn_shared_ux_markdown_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-markdown-mocks title: "@kbn/shared-ux-markdown-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-markdown-mocks plugin -date: 2024-05-16 +date: 2024-05-17 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 b2259a25a7042..e5bc883bddde8 100644 --- a/api_docs/kbn_shared_ux_page_analytics_no_data.mdx +++ b/api_docs/kbn_shared_ux_page_analytics_no_data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-analytics-no-data title: "@kbn/shared-ux-page-analytics-no-data" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-analytics-no-data plugin -date: 2024-05-16 +date: 2024-05-17 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 233e5b4be552c..f5604aecb0dd6 100644 --- a/api_docs/kbn_shared_ux_page_analytics_no_data_mocks.mdx +++ b/api_docs/kbn_shared_ux_page_analytics_no_data_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-analytics-no-data-mocks title: "@kbn/shared-ux-page-analytics-no-data-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-analytics-no-data-mocks plugin -date: 2024-05-16 +date: 2024-05-17 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 b9b28030ef322..a94994d2f2b61 100644 --- a/api_docs/kbn_shared_ux_page_kibana_no_data.mdx +++ b/api_docs/kbn_shared_ux_page_kibana_no_data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-kibana-no-data title: "@kbn/shared-ux-page-kibana-no-data" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-kibana-no-data plugin -date: 2024-05-16 +date: 2024-05-17 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 f7c4adf7e8081..b537dd0dfc291 100644 --- a/api_docs/kbn_shared_ux_page_kibana_no_data_mocks.mdx +++ b/api_docs/kbn_shared_ux_page_kibana_no_data_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-kibana-no-data-mocks title: "@kbn/shared-ux-page-kibana-no-data-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-kibana-no-data-mocks plugin -date: 2024-05-16 +date: 2024-05-17 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 26e2bd19edceb..c49d6066a79d5 100644 --- a/api_docs/kbn_shared_ux_page_kibana_template.mdx +++ b/api_docs/kbn_shared_ux_page_kibana_template.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-kibana-template title: "@kbn/shared-ux-page-kibana-template" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-kibana-template plugin -date: 2024-05-16 +date: 2024-05-17 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 1c336dd3a7fe5..de9299337b544 100644 --- a/api_docs/kbn_shared_ux_page_kibana_template_mocks.mdx +++ b/api_docs/kbn_shared_ux_page_kibana_template_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-kibana-template-mocks title: "@kbn/shared-ux-page-kibana-template-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-kibana-template-mocks plugin -date: 2024-05-16 +date: 2024-05-17 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 08ef89efcbd47..a91d801ec4c5b 100644 --- a/api_docs/kbn_shared_ux_page_no_data.mdx +++ b/api_docs/kbn_shared_ux_page_no_data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-no-data title: "@kbn/shared-ux-page-no-data" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-no-data plugin -date: 2024-05-16 +date: 2024-05-17 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 09c1fc506e3c6..23e909c407999 100644 --- a/api_docs/kbn_shared_ux_page_no_data_config.mdx +++ b/api_docs/kbn_shared_ux_page_no_data_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-no-data-config title: "@kbn/shared-ux-page-no-data-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-no-data-config plugin -date: 2024-05-16 +date: 2024-05-17 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 8f07624c61f94..b83265c35d7b8 100644 --- a/api_docs/kbn_shared_ux_page_no_data_config_mocks.mdx +++ b/api_docs/kbn_shared_ux_page_no_data_config_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-no-data-config-mocks title: "@kbn/shared-ux-page-no-data-config-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-no-data-config-mocks plugin -date: 2024-05-16 +date: 2024-05-17 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 ef5ce2e346ee5..ac29444142cdf 100644 --- a/api_docs/kbn_shared_ux_page_no_data_mocks.mdx +++ b/api_docs/kbn_shared_ux_page_no_data_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-no-data-mocks title: "@kbn/shared-ux-page-no-data-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-no-data-mocks plugin -date: 2024-05-16 +date: 2024-05-17 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 e11424c8b9a73..e710289fd40b5 100644 --- a/api_docs/kbn_shared_ux_page_solution_nav.mdx +++ b/api_docs/kbn_shared_ux_page_solution_nav.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-solution-nav title: "@kbn/shared-ux-page-solution-nav" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-solution-nav plugin -date: 2024-05-16 +date: 2024-05-17 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 d6bcbca90ae50..1069afb70486b 100644 --- a/api_docs/kbn_shared_ux_prompt_no_data_views.mdx +++ b/api_docs/kbn_shared_ux_prompt_no_data_views.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-prompt-no-data-views title: "@kbn/shared-ux-prompt-no-data-views" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-prompt-no-data-views plugin -date: 2024-05-16 +date: 2024-05-17 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 b01e77817da3c..bec8d90d7c0a8 100644 --- a/api_docs/kbn_shared_ux_prompt_no_data_views_mocks.mdx +++ b/api_docs/kbn_shared_ux_prompt_no_data_views_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-prompt-no-data-views-mocks title: "@kbn/shared-ux-prompt-no-data-views-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-prompt-no-data-views-mocks plugin -date: 2024-05-16 +date: 2024-05-17 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 42477fc361f44..2fee7168aabaa 100644 --- a/api_docs/kbn_shared_ux_prompt_not_found.mdx +++ b/api_docs/kbn_shared_ux_prompt_not_found.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-prompt-not-found title: "@kbn/shared-ux-prompt-not-found" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-prompt-not-found plugin -date: 2024-05-16 +date: 2024-05-17 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 600f2c8ef0234..78417172d1319 100644 --- a/api_docs/kbn_shared_ux_router.mdx +++ b/api_docs/kbn_shared_ux_router.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-router title: "@kbn/shared-ux-router" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-router plugin -date: 2024-05-16 +date: 2024-05-17 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 579d9be1c6ffe..293f834f05d33 100644 --- a/api_docs/kbn_shared_ux_router_mocks.mdx +++ b/api_docs/kbn_shared_ux_router_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-router-mocks title: "@kbn/shared-ux-router-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-router-mocks plugin -date: 2024-05-16 +date: 2024-05-17 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 54a7bd5123d50..b5b069a29e0ab 100644 --- a/api_docs/kbn_shared_ux_storybook_config.mdx +++ b/api_docs/kbn_shared_ux_storybook_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-storybook-config title: "@kbn/shared-ux-storybook-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-storybook-config plugin -date: 2024-05-16 +date: 2024-05-17 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 c1b20a9cc7c2a..8ac82dd68f8cf 100644 --- a/api_docs/kbn_shared_ux_storybook_mock.mdx +++ b/api_docs/kbn_shared_ux_storybook_mock.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-storybook-mock title: "@kbn/shared-ux-storybook-mock" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-storybook-mock plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-storybook-mock'] --- import kbnSharedUxStorybookMockObj from './kbn_shared_ux_storybook_mock.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_tabbed_modal.mdx b/api_docs/kbn_shared_ux_tabbed_modal.mdx index 6eb0d20daa312..3633185c4a091 100644 --- a/api_docs/kbn_shared_ux_tabbed_modal.mdx +++ b/api_docs/kbn_shared_ux_tabbed_modal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-tabbed-modal title: "@kbn/shared-ux-tabbed-modal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-tabbed-modal plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-tabbed-modal'] --- import kbnSharedUxTabbedModalObj from './kbn_shared_ux_tabbed_modal.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_utility.mdx b/api_docs/kbn_shared_ux_utility.mdx index 3fc67c924f5ab..e32ff9e949652 100644 --- a/api_docs/kbn_shared_ux_utility.mdx +++ b/api_docs/kbn_shared_ux_utility.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-utility title: "@kbn/shared-ux-utility" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-utility plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-utility'] --- import kbnSharedUxUtilityObj from './kbn_shared_ux_utility.devdocs.json'; diff --git a/api_docs/kbn_slo_schema.devdocs.json b/api_docs/kbn_slo_schema.devdocs.json index 2322c73758327..fb749318c15e2 100644 --- a/api_docs/kbn_slo_schema.devdocs.json +++ b/api_docs/kbn_slo_schema.devdocs.json @@ -745,7 +745,7 @@ "section": "def-common.Duration", "text": "Duration" }, - " | undefined; }; groupBy: string | string[]; revision: number; } & { remoteName?: string | undefined; range?: { from: string; to: string; } | undefined; })[]; }" + " | undefined; }; groupBy: string | string[]; revision: number; } & { remoteName?: string | undefined; range?: { from: Date; to: Date; } | undefined; })[]; }" ], "path": "x-pack/packages/kbn-slo-schema/src/rest_specs/routes/fetch_historical_summary.ts", "deprecated": false, @@ -910,7 +910,7 @@ "label": "GetPreviewDataParams", "description": [], "signature": [ - "{ indicator: { type: \"sli.apm.transactionDuration\"; params: { environment: string; service: string; transactionType: string; transactionName: string; threshold: number; index: string; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; index: string; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }; } | { type: \"sli.synthetics.availability\"; params: { monitorIds: { value: string; label: string; }[]; index: string; } & { tags?: { value: string; label: string; }[] | undefined; projects?: { value: string; label: string; }[] | undefined; filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; good: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; }; total: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; }; timestampField: string; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }; } | { type: \"sli.metric.custom\"; params: { index: string; good: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }))[]; equation: string; }; total: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }))[]; equation: string; }; timestampField: string; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }; } | { type: \"sli.metric.timeslice\"; params: { index: string; metric: { metrics: (({ name: string; aggregation: \"min\" | \"max\" | \"sum\" | \"avg\" | \"last_value\" | \"cardinality\" | \"std_deviation\"; field: string; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }) | ({ name: string; aggregation: \"percentile\"; field: string; percentile: number; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }))[]; equation: string; threshold: number; comparator: \"GT\" | \"GTE\" | \"LT\" | \"LTE\"; }; timestampField: string; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }; } | { type: \"sli.histogram.custom\"; params: { index: string; timestampField: string; good: ({ field: string; aggregation: \"value_count\"; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }); total: ({ field: string; aggregation: \"value_count\"; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }); } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }; }; range: { start: number; end: number; }; } & { objective?: ({ target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: ", + "{ indicator: { type: \"sli.apm.transactionDuration\"; params: { environment: string; service: string; transactionType: string; transactionName: string; threshold: number; index: string; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; index: string; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }; } | { type: \"sli.synthetics.availability\"; params: { monitorIds: { value: string; label: string; }[]; index: string; } & { tags?: { value: string; label: string; }[] | undefined; projects?: { value: string; label: string; }[] | undefined; filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; good: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; }; total: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; }; timestampField: string; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }; } | { type: \"sli.metric.custom\"; params: { index: string; good: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }))[]; equation: string; }; total: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }))[]; equation: string; }; timestampField: string; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }; } | { type: \"sli.metric.timeslice\"; params: { index: string; metric: { metrics: (({ name: string; aggregation: \"min\" | \"max\" | \"sum\" | \"avg\" | \"last_value\" | \"cardinality\" | \"std_deviation\"; field: string; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }) | ({ name: string; aggregation: \"percentile\"; field: string; percentile: number; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }))[]; equation: string; threshold: number; comparator: \"GT\" | \"GTE\" | \"LT\" | \"LTE\"; }; timestampField: string; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }; } | { type: \"sli.histogram.custom\"; params: { index: string; timestampField: string; good: ({ field: string; aggregation: \"value_count\"; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }); total: ({ field: string; aggregation: \"value_count\"; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }); } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }; }; range: { from: Date; to: Date; }; } & { objective?: ({ target: number; } & { timesliceTarget?: number | undefined; timesliceWindow?: ", { "pluginId": "@kbn/slo-schema", "scope": "common", @@ -3241,18 +3241,10 @@ "signature": [ "TypeC", "<{ from: ", - "UnionC", - "<[", "Type", - ", ", - "StringC", - "]>; to: ", - "UnionC", - "<[", + "; to: ", "Type", - ", ", - "StringC", - "]>; }>" + "; }>" ], "path": "x-pack/packages/kbn-slo-schema/src/schema/common.ts", "deprecated": false, @@ -3475,10 +3467,10 @@ "; range: ", "TypeC", "<{ from: ", - "StringC", - "; to: ", - "StringC", - "; }>; }>]>>; }>; }>" + "Type", + "; to: ", + "Type", + "; }>; }>]>>; }>; }>" ], "path": "x-pack/packages/kbn-slo-schema/src/rest_specs/routes/fetch_historical_summary.ts", "deprecated": false, @@ -8054,11 +8046,11 @@ "AnyC", ">; }>>; }>]>; }>]>; }>]>; range: ", "TypeC", - "<{ start: ", - "NumberC", - "; end: ", - "NumberC", - "; }>; }>, ", + "<{ from: ", + "Type", + "; to: ", + "Type", + "; }>; }>, ", "PartialC", "<{ objective: ", "IntersectionC", diff --git a/api_docs/kbn_slo_schema.mdx b/api_docs/kbn_slo_schema.mdx index 57f02527ae298..9b1dcf79f7ed0 100644 --- a/api_docs/kbn_slo_schema.mdx +++ b/api_docs/kbn_slo_schema.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-slo-schema title: "@kbn/slo-schema" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/slo-schema plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/slo-schema'] --- import kbnSloSchemaObj from './kbn_slo_schema.devdocs.json'; diff --git a/api_docs/kbn_solution_nav_es.mdx b/api_docs/kbn_solution_nav_es.mdx index 166bc52255a21..be1ef596adfa5 100644 --- a/api_docs/kbn_solution_nav_es.mdx +++ b/api_docs/kbn_solution_nav_es.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-solution-nav-es title: "@kbn/solution-nav-es" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/solution-nav-es plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/solution-nav-es'] --- import kbnSolutionNavEsObj from './kbn_solution_nav_es.devdocs.json'; diff --git a/api_docs/kbn_solution_nav_oblt.mdx b/api_docs/kbn_solution_nav_oblt.mdx index 8146c538764e6..1f69c6c2dbd24 100644 --- a/api_docs/kbn_solution_nav_oblt.mdx +++ b/api_docs/kbn_solution_nav_oblt.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-solution-nav-oblt title: "@kbn/solution-nav-oblt" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/solution-nav-oblt plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/solution-nav-oblt'] --- import kbnSolutionNavObltObj from './kbn_solution_nav_oblt.devdocs.json'; diff --git a/api_docs/kbn_some_dev_log.mdx b/api_docs/kbn_some_dev_log.mdx index 027ec53e5f5cd..f71f3086091d0 100644 --- a/api_docs/kbn_some_dev_log.mdx +++ b/api_docs/kbn_some_dev_log.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-some-dev-log title: "@kbn/some-dev-log" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/some-dev-log plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/some-dev-log'] --- import kbnSomeDevLogObj from './kbn_some_dev_log.devdocs.json'; diff --git a/api_docs/kbn_sort_predicates.mdx b/api_docs/kbn_sort_predicates.mdx index fba0c0bc86551..df1e5cb309937 100644 --- a/api_docs/kbn_sort_predicates.mdx +++ b/api_docs/kbn_sort_predicates.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-sort-predicates title: "@kbn/sort-predicates" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/sort-predicates plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/sort-predicates'] --- import kbnSortPredicatesObj from './kbn_sort_predicates.devdocs.json'; diff --git a/api_docs/kbn_std.mdx b/api_docs/kbn_std.mdx index 91e2dc1fa14d7..dbc6b71f15cf1 100644 --- a/api_docs/kbn_std.mdx +++ b/api_docs/kbn_std.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-std title: "@kbn/std" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/std plugin -date: 2024-05-16 +date: 2024-05-17 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 d2c5020047e94..e5dbedf0ae93f 100644 --- a/api_docs/kbn_stdio_dev_helpers.mdx +++ b/api_docs/kbn_stdio_dev_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-stdio-dev-helpers title: "@kbn/stdio-dev-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/stdio-dev-helpers plugin -date: 2024-05-16 +date: 2024-05-17 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 36e8a7f76b79f..90df907eeb784 100644 --- a/api_docs/kbn_storybook.mdx +++ b/api_docs/kbn_storybook.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-storybook title: "@kbn/storybook" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/storybook plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/storybook'] --- import kbnStorybookObj from './kbn_storybook.devdocs.json'; diff --git a/api_docs/kbn_telemetry_tools.mdx b/api_docs/kbn_telemetry_tools.mdx index 42facc713b24c..db5fa66f10db7 100644 --- a/api_docs/kbn_telemetry_tools.mdx +++ b/api_docs/kbn_telemetry_tools.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-telemetry-tools title: "@kbn/telemetry-tools" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/telemetry-tools plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/telemetry-tools'] --- import kbnTelemetryToolsObj from './kbn_telemetry_tools.devdocs.json'; diff --git a/api_docs/kbn_test.mdx b/api_docs/kbn_test.mdx index 84737a2c9f9b4..1fa524b0efb8d 100644 --- a/api_docs/kbn_test.mdx +++ b/api_docs/kbn_test.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-test title: "@kbn/test" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/test plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/test'] --- import kbnTestObj from './kbn_test.devdocs.json'; diff --git a/api_docs/kbn_test_eui_helpers.mdx b/api_docs/kbn_test_eui_helpers.mdx index b184c22be1544..4289e00f1e5e7 100644 --- a/api_docs/kbn_test_eui_helpers.mdx +++ b/api_docs/kbn_test_eui_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-test-eui-helpers title: "@kbn/test-eui-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/test-eui-helpers plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/test-eui-helpers'] --- import kbnTestEuiHelpersObj from './kbn_test_eui_helpers.devdocs.json'; diff --git a/api_docs/kbn_test_jest_helpers.mdx b/api_docs/kbn_test_jest_helpers.mdx index 2236e323df45f..9bdb32296af21 100644 --- a/api_docs/kbn_test_jest_helpers.mdx +++ b/api_docs/kbn_test_jest_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-test-jest-helpers title: "@kbn/test-jest-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/test-jest-helpers plugin -date: 2024-05-16 +date: 2024-05-17 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 a95d2c09c4db2..97d1302cdea1c 100644 --- a/api_docs/kbn_test_subj_selector.mdx +++ b/api_docs/kbn_test_subj_selector.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-test-subj-selector title: "@kbn/test-subj-selector" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/test-subj-selector plugin -date: 2024-05-16 +date: 2024-05-17 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 bfddc274650d6..be45708d02c2a 100644 --- a/api_docs/kbn_text_based_editor.mdx +++ b/api_docs/kbn_text_based_editor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-text-based-editor title: "@kbn/text-based-editor" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/text-based-editor plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/text-based-editor'] --- import kbnTextBasedEditorObj from './kbn_text_based_editor.devdocs.json'; diff --git a/api_docs/kbn_timerange.mdx b/api_docs/kbn_timerange.mdx index 314d215e990ce..78612333dcd1b 100644 --- a/api_docs/kbn_timerange.mdx +++ b/api_docs/kbn_timerange.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-timerange title: "@kbn/timerange" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/timerange plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/timerange'] --- import kbnTimerangeObj from './kbn_timerange.devdocs.json'; diff --git a/api_docs/kbn_tooling_log.mdx b/api_docs/kbn_tooling_log.mdx index cfec45e65cc76..0c988ebd69f35 100644 --- a/api_docs/kbn_tooling_log.mdx +++ b/api_docs/kbn_tooling_log.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-tooling-log title: "@kbn/tooling-log" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/tooling-log plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/tooling-log'] --- import kbnToolingLogObj from './kbn_tooling_log.devdocs.json'; diff --git a/api_docs/kbn_triggers_actions_ui_types.mdx b/api_docs/kbn_triggers_actions_ui_types.mdx index 1edc8f9da5712..c228926342b71 100644 --- a/api_docs/kbn_triggers_actions_ui_types.mdx +++ b/api_docs/kbn_triggers_actions_ui_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-triggers-actions-ui-types title: "@kbn/triggers-actions-ui-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/triggers-actions-ui-types plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/triggers-actions-ui-types'] --- import kbnTriggersActionsUiTypesObj from './kbn_triggers_actions_ui_types.devdocs.json'; diff --git a/api_docs/kbn_try_in_console.mdx b/api_docs/kbn_try_in_console.mdx index c4d3e26e9546d..ecc4518ba8e81 100644 --- a/api_docs/kbn_try_in_console.mdx +++ b/api_docs/kbn_try_in_console.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-try-in-console title: "@kbn/try-in-console" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/try-in-console plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/try-in-console'] --- import kbnTryInConsoleObj from './kbn_try_in_console.devdocs.json'; diff --git a/api_docs/kbn_ts_projects.mdx b/api_docs/kbn_ts_projects.mdx index 176d30b579f26..a96fa3df263b9 100644 --- a/api_docs/kbn_ts_projects.mdx +++ b/api_docs/kbn_ts_projects.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ts-projects title: "@kbn/ts-projects" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ts-projects plugin -date: 2024-05-16 +date: 2024-05-17 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 dc5a0a8484a76..c5c4e4a4a132b 100644 --- a/api_docs/kbn_typed_react_router_config.mdx +++ b/api_docs/kbn_typed_react_router_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-typed-react-router-config title: "@kbn/typed-react-router-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/typed-react-router-config plugin -date: 2024-05-16 +date: 2024-05-17 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 ae43f0539af1a..0acf68f5d9d20 100644 --- a/api_docs/kbn_ui_actions_browser.mdx +++ b/api_docs/kbn_ui_actions_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ui-actions-browser title: "@kbn/ui-actions-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ui-actions-browser plugin -date: 2024-05-16 +date: 2024-05-17 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 bb0a0f8c06991..ce32374b41013 100644 --- a/api_docs/kbn_ui_shared_deps_src.mdx +++ b/api_docs/kbn_ui_shared_deps_src.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ui-shared-deps-src title: "@kbn/ui-shared-deps-src" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ui-shared-deps-src plugin -date: 2024-05-16 +date: 2024-05-17 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 ef827c0a57ccd..9031fda6e4043 100644 --- a/api_docs/kbn_ui_theme.mdx +++ b/api_docs/kbn_ui_theme.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ui-theme title: "@kbn/ui-theme" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ui-theme plugin -date: 2024-05-16 +date: 2024-05-17 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 49959eb9f4656..2ee487cd0d663 100644 --- a/api_docs/kbn_unified_data_table.mdx +++ b/api_docs/kbn_unified_data_table.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-unified-data-table title: "@kbn/unified-data-table" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/unified-data-table plugin -date: 2024-05-16 +date: 2024-05-17 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 3791de89a21cf..0c51079c29228 100644 --- a/api_docs/kbn_unified_doc_viewer.mdx +++ b/api_docs/kbn_unified_doc_viewer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-unified-doc-viewer title: "@kbn/unified-doc-viewer" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/unified-doc-viewer plugin -date: 2024-05-16 +date: 2024-05-17 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 931cda1107e6b..3d052cb5f9202 100644 --- a/api_docs/kbn_unified_field_list.mdx +++ b/api_docs/kbn_unified_field_list.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-unified-field-list title: "@kbn/unified-field-list" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/unified-field-list plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/unified-field-list'] --- import kbnUnifiedFieldListObj from './kbn_unified_field_list.devdocs.json'; diff --git a/api_docs/kbn_unsaved_changes_badge.mdx b/api_docs/kbn_unsaved_changes_badge.mdx index 9352a38315dd7..18eb27ecd9cc4 100644 --- a/api_docs/kbn_unsaved_changes_badge.mdx +++ b/api_docs/kbn_unsaved_changes_badge.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-unsaved-changes-badge title: "@kbn/unsaved-changes-badge" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/unsaved-changes-badge plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/unsaved-changes-badge'] --- import kbnUnsavedChangesBadgeObj from './kbn_unsaved_changes_badge.devdocs.json'; diff --git a/api_docs/kbn_use_tracked_promise.mdx b/api_docs/kbn_use_tracked_promise.mdx index 32e0ef1be4cb4..627774c485e46 100644 --- a/api_docs/kbn_use_tracked_promise.mdx +++ b/api_docs/kbn_use_tracked_promise.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-use-tracked-promise title: "@kbn/use-tracked-promise" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/use-tracked-promise plugin -date: 2024-05-16 +date: 2024-05-17 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 1ee17f2da1447..2c67f344d71aa 100644 --- a/api_docs/kbn_user_profile_components.mdx +++ b/api_docs/kbn_user_profile_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-user-profile-components title: "@kbn/user-profile-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/user-profile-components plugin -date: 2024-05-16 +date: 2024-05-17 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 724cd472c9551..80abfba5a79ea 100644 --- a/api_docs/kbn_utility_types.mdx +++ b/api_docs/kbn_utility_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-utility-types title: "@kbn/utility-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/utility-types plugin -date: 2024-05-16 +date: 2024-05-17 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 d41184c744562..58eb8d7c15930 100644 --- a/api_docs/kbn_utility_types_jest.mdx +++ b/api_docs/kbn_utility_types_jest.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-utility-types-jest title: "@kbn/utility-types-jest" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/utility-types-jest plugin -date: 2024-05-16 +date: 2024-05-17 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 31f07dfbc118d..a61141d65731b 100644 --- a/api_docs/kbn_utils.mdx +++ b/api_docs/kbn_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-utils title: "@kbn/utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/utils plugin -date: 2024-05-16 +date: 2024-05-17 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 b44bb62993580..914287fb5f99c 100644 --- a/api_docs/kbn_visualization_ui_components.mdx +++ b/api_docs/kbn_visualization_ui_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-visualization-ui-components title: "@kbn/visualization-ui-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/visualization-ui-components plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/visualization-ui-components'] --- import kbnVisualizationUiComponentsObj from './kbn_visualization_ui_components.devdocs.json'; diff --git a/api_docs/kbn_visualization_utils.mdx b/api_docs/kbn_visualization_utils.mdx index 9d4d5b45e0d5e..dfe5fc14f95f5 100644 --- a/api_docs/kbn_visualization_utils.mdx +++ b/api_docs/kbn_visualization_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-visualization-utils title: "@kbn/visualization-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/visualization-utils plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/visualization-utils'] --- import kbnVisualizationUtilsObj from './kbn_visualization_utils.devdocs.json'; diff --git a/api_docs/kbn_xstate_utils.mdx b/api_docs/kbn_xstate_utils.mdx index 321f42394aa4e..a909a06d1bae8 100644 --- a/api_docs/kbn_xstate_utils.mdx +++ b/api_docs/kbn_xstate_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-xstate-utils title: "@kbn/xstate-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/xstate-utils plugin -date: 2024-05-16 +date: 2024-05-17 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 cf1968ea2b1c5..88715e0a5a96b 100644 --- a/api_docs/kbn_yarn_lock_validator.mdx +++ b/api_docs/kbn_yarn_lock_validator.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-yarn-lock-validator title: "@kbn/yarn-lock-validator" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/yarn-lock-validator plugin -date: 2024-05-16 +date: 2024-05-17 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 93dc63ea17678..ea0a35c33ad68 100644 --- a/api_docs/kbn_zod_helpers.mdx +++ b/api_docs/kbn_zod_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-zod-helpers title: "@kbn/zod-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/zod-helpers plugin -date: 2024-05-16 +date: 2024-05-17 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 357169b6bc610..3556053ea6943 100644 --- a/api_docs/kibana_overview.mdx +++ b/api_docs/kibana_overview.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kibanaOverview title: "kibanaOverview" image: https://source.unsplash.com/400x175/?github description: API docs for the kibanaOverview plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'kibanaOverview'] --- import kibanaOverviewObj from './kibana_overview.devdocs.json'; diff --git a/api_docs/kibana_react.mdx b/api_docs/kibana_react.mdx index 7a5aef74a8c4a..5fe49dd46adf0 100644 --- a/api_docs/kibana_react.mdx +++ b/api_docs/kibana_react.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kibanaReact title: "kibanaReact" image: https://source.unsplash.com/400x175/?github description: API docs for the kibanaReact plugin -date: 2024-05-16 +date: 2024-05-17 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 011e618aa23aa..b0f4c61c8a5a8 100644 --- a/api_docs/kibana_utils.mdx +++ b/api_docs/kibana_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kibanaUtils title: "kibanaUtils" image: https://source.unsplash.com/400x175/?github description: API docs for the kibanaUtils plugin -date: 2024-05-16 +date: 2024-05-17 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 919f4a3b6cb8d..7a9e99ddbfaa8 100644 --- a/api_docs/kubernetes_security.mdx +++ b/api_docs/kubernetes_security.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kubernetesSecurity title: "kubernetesSecurity" image: https://source.unsplash.com/400x175/?github description: API docs for the kubernetesSecurity plugin -date: 2024-05-16 +date: 2024-05-17 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 75b891aa6e677..f5c5fadbdedac 100644 --- a/api_docs/lens.mdx +++ b/api_docs/lens.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/lens title: "lens" image: https://source.unsplash.com/400x175/?github description: API docs for the lens plugin -date: 2024-05-16 +date: 2024-05-17 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 0e482e6ea7225..8031bc32939b9 100644 --- a/api_docs/license_api_guard.mdx +++ b/api_docs/license_api_guard.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/licenseApiGuard title: "licenseApiGuard" image: https://source.unsplash.com/400x175/?github description: API docs for the licenseApiGuard plugin -date: 2024-05-16 +date: 2024-05-17 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 26e85a2bdd468..5b1dde74c7d56 100644 --- a/api_docs/license_management.mdx +++ b/api_docs/license_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/licenseManagement title: "licenseManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the licenseManagement plugin -date: 2024-05-16 +date: 2024-05-17 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 92d78bfb15e3a..18a581ce893ac 100644 --- a/api_docs/licensing.mdx +++ b/api_docs/licensing.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/licensing title: "licensing" image: https://source.unsplash.com/400x175/?github description: API docs for the licensing plugin -date: 2024-05-16 +date: 2024-05-17 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 96d81e43d0780..a9a7e2a5cd7fa 100644 --- a/api_docs/links.mdx +++ b/api_docs/links.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/links title: "links" image: https://source.unsplash.com/400x175/?github description: API docs for the links plugin -date: 2024-05-16 +date: 2024-05-17 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 abd0d0369f6ef..c614d4f6dff63 100644 --- a/api_docs/lists.mdx +++ b/api_docs/lists.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/lists title: "lists" image: https://source.unsplash.com/400x175/?github description: API docs for the lists plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'lists'] --- import listsObj from './lists.devdocs.json'; diff --git a/api_docs/logs_data_access.mdx b/api_docs/logs_data_access.mdx index 00a94ada300b4..2115a9ac683c5 100644 --- a/api_docs/logs_data_access.mdx +++ b/api_docs/logs_data_access.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/logsDataAccess title: "logsDataAccess" image: https://source.unsplash.com/400x175/?github description: API docs for the logsDataAccess plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'logsDataAccess'] --- import logsDataAccessObj from './logs_data_access.devdocs.json'; diff --git a/api_docs/logs_explorer.mdx b/api_docs/logs_explorer.mdx index 7a709b5e0fc4e..b3676d8731bd7 100644 --- a/api_docs/logs_explorer.mdx +++ b/api_docs/logs_explorer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/logsExplorer title: "logsExplorer" image: https://source.unsplash.com/400x175/?github description: API docs for the logsExplorer plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'logsExplorer'] --- import logsExplorerObj from './logs_explorer.devdocs.json'; diff --git a/api_docs/logs_shared.mdx b/api_docs/logs_shared.mdx index 6ad6f3f106dc5..7c20eddf443c2 100644 --- a/api_docs/logs_shared.mdx +++ b/api_docs/logs_shared.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/logsShared title: "logsShared" image: https://source.unsplash.com/400x175/?github description: API docs for the logsShared plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'logsShared'] --- import logsSharedObj from './logs_shared.devdocs.json'; diff --git a/api_docs/management.mdx b/api_docs/management.mdx index b8b6c19554faa..9cb264a9150ae 100644 --- a/api_docs/management.mdx +++ b/api_docs/management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/management title: "management" image: https://source.unsplash.com/400x175/?github description: API docs for the management plugin -date: 2024-05-16 +date: 2024-05-17 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 3f913dd6a1d76..59378c35aa8e4 100644 --- a/api_docs/maps.mdx +++ b/api_docs/maps.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/maps title: "maps" image: https://source.unsplash.com/400x175/?github description: API docs for the maps plugin -date: 2024-05-16 +date: 2024-05-17 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 e84d3422051a2..9d9ecca4dcbfd 100644 --- a/api_docs/maps_ems.mdx +++ b/api_docs/maps_ems.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/mapsEms title: "mapsEms" image: https://source.unsplash.com/400x175/?github description: API docs for the mapsEms plugin -date: 2024-05-16 +date: 2024-05-17 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 da97d001411cf..a744b95998f51 100644 --- a/api_docs/metrics_data_access.devdocs.json +++ b/api_docs/metrics_data_access.devdocs.json @@ -1301,7 +1301,107 @@ "InventoryModel", "<", "InventoryMetrics", - ">)[]" + "> | ", + "InventoryModel", + "<", + "InventoryMetricsWithCharts", + "<{ readonly dockerContainerCpuUsage: ", + "LensBaseLayer", + "; readonly dockerContainerMemoryUsage: ", + "LensBaseLayer", + "; readonly k8sContainerCpuUsage: ", + "LensBaseLayer", + "; readonly k8sContainerMemoryUsage: ", + "LensBaseLayer", + "; }, { readonly cpu: { readonly xy: { readonly dockerContainerCpuUsage: { title: string; dataset?: ", + "LensDataset", + " | undefined; chartType: \"xy\"; layers: ({ dataset?: ", + "LensDataset", + " | undefined; yAxis: ", + "LensBaseLayer", + "[]; type: \"series\"; breakdown?: ", + "LensBreakdownConfig", + " | undefined; xAxis: ", + "LensBreakdownConfig", + "; seriesType: \"area\" | \"line\" | \"bar\"; } | { dataset?: ", + "LensDataset", + " | undefined; yAxis: ", + "LensBaseLayer", + "[]; type: \"annotation\"; events: ({ name: string; color?: string | undefined; icon?: string | undefined; datetime: string; } | { name: string; color?: string | undefined; icon?: string | undefined; field: string; filter: string; })[]; } | ", + "LensReferenceLineLayer", + ")[]; legend?: { show?: boolean | undefined; position?: \"right\" | \"left\" | \"top\" | \"bottom\" | undefined; } | undefined; axisTitleVisibility?: { showXAxisTitle?: boolean | undefined; showYAxisTitle?: boolean | undefined; } | undefined; emphasizeFitting?: boolean | undefined; fittingFunction?: \"None\" | \"Average\" | \"Zero\" | \"Nearest\" | \"Linear\" | \"Carry\" | \"Lookahead\" | undefined; yBounds?: ", + "LensYBoundsConfig", + " | undefined; } & { id: string; }; readonly k8sContainerCpuUsage: { title: string; dataset?: ", + "LensDataset", + " | undefined; chartType: \"xy\"; layers: ({ dataset?: ", + "LensDataset", + " | undefined; yAxis: ", + "LensBaseLayer", + "[]; type: \"series\"; breakdown?: ", + "LensBreakdownConfig", + " | undefined; xAxis: ", + "LensBreakdownConfig", + "; seriesType: \"area\" | \"line\" | \"bar\"; } | { dataset?: ", + "LensDataset", + " | undefined; yAxis: ", + "LensBaseLayer", + "[]; type: \"annotation\"; events: ({ name: string; color?: string | undefined; icon?: string | undefined; datetime: string; } | { name: string; color?: string | undefined; icon?: string | undefined; field: string; filter: string; })[]; } | ", + "LensReferenceLineLayer", + ")[]; legend?: { show?: boolean | undefined; position?: \"right\" | \"left\" | \"top\" | \"bottom\" | undefined; } | undefined; axisTitleVisibility?: { showXAxisTitle?: boolean | undefined; showYAxisTitle?: boolean | undefined; } | undefined; emphasizeFitting?: boolean | undefined; fittingFunction?: \"None\" | \"Average\" | \"Zero\" | \"Nearest\" | \"Linear\" | \"Carry\" | \"Lookahead\" | undefined; yBounds?: ", + "LensYBoundsConfig", + " | undefined; } & { id: string; }; }; readonly metric: { readonly dockerContainerCpuUsage: { title: string; dataset?: ", + "LensDataset", + " | undefined; label?: string | undefined; filter?: string | undefined; format?: \"string\" | \"number\" | \"duration\" | \"percent\" | \"currency\" | \"bytes\" | \"bits\" | undefined; decimals?: number | undefined; normalizeByUnit?: \"m\" | \"d\" | \"h\" | \"s\" | undefined; compactValues?: boolean | undefined; randomSampling?: number | undefined; useGlobalFilter?: boolean | undefined; seriesColor?: string | undefined; value: string; chartType: \"metric\"; querySecondaryMetric?: string | undefined; queryMaxValue?: string | undefined; breakdown?: ", + "LensBreakdownConfig", + " | undefined; trendLine?: boolean | undefined; subtitle?: string | undefined; } & { id: string; }; readonly k8sContainerCpuUsage: { title: string; dataset?: ", + "LensDataset", + " | undefined; label?: string | undefined; filter?: string | undefined; format?: \"string\" | \"number\" | \"duration\" | \"percent\" | \"currency\" | \"bytes\" | \"bits\" | undefined; decimals?: number | undefined; normalizeByUnit?: \"m\" | \"d\" | \"h\" | \"s\" | undefined; compactValues?: boolean | undefined; randomSampling?: number | undefined; useGlobalFilter?: boolean | undefined; seriesColor?: string | undefined; value: string; chartType: \"metric\"; querySecondaryMetric?: string | undefined; queryMaxValue?: string | undefined; breakdown?: ", + "LensBreakdownConfig", + " | undefined; trendLine?: boolean | undefined; subtitle?: string | undefined; } & { id: string; }; }; }; readonly memory: { xy: { dockerContainerMemoryUsage: { title: string; dataset?: ", + "LensDataset", + " | undefined; chartType: \"xy\"; layers: ({ dataset?: ", + "LensDataset", + " | undefined; yAxis: ", + "LensBaseLayer", + "[]; type: \"series\"; breakdown?: ", + "LensBreakdownConfig", + " | undefined; xAxis: ", + "LensBreakdownConfig", + "; seriesType: \"area\" | \"line\" | \"bar\"; } | { dataset?: ", + "LensDataset", + " | undefined; yAxis: ", + "LensBaseLayer", + "[]; type: \"annotation\"; events: ({ name: string; color?: string | undefined; icon?: string | undefined; datetime: string; } | { name: string; color?: string | undefined; icon?: string | undefined; field: string; filter: string; })[]; } | ", + "LensReferenceLineLayer", + ")[]; legend?: { show?: boolean | undefined; position?: \"right\" | \"left\" | \"top\" | \"bottom\" | undefined; } | undefined; axisTitleVisibility?: { showXAxisTitle?: boolean | undefined; showYAxisTitle?: boolean | undefined; } | undefined; emphasizeFitting?: boolean | undefined; fittingFunction?: \"None\" | \"Average\" | \"Zero\" | \"Nearest\" | \"Linear\" | \"Carry\" | \"Lookahead\" | undefined; yBounds?: ", + "LensYBoundsConfig", + " | undefined; } & { id: string; }; k8sContainerMemoryUsage: { title: string; dataset?: ", + "LensDataset", + " | undefined; chartType: \"xy\"; layers: ({ dataset?: ", + "LensDataset", + " | undefined; yAxis: ", + "LensBaseLayer", + "[]; type: \"series\"; breakdown?: ", + "LensBreakdownConfig", + " | undefined; xAxis: ", + "LensBreakdownConfig", + "; seriesType: \"area\" | \"line\" | \"bar\"; } | { dataset?: ", + "LensDataset", + " | undefined; yAxis: ", + "LensBaseLayer", + "[]; type: \"annotation\"; events: ({ name: string; color?: string | undefined; icon?: string | undefined; datetime: string; } | { name: string; color?: string | undefined; icon?: string | undefined; field: string; filter: string; })[]; } | ", + "LensReferenceLineLayer", + ")[]; legend?: { show?: boolean | undefined; position?: \"right\" | \"left\" | \"top\" | \"bottom\" | undefined; } | undefined; axisTitleVisibility?: { showXAxisTitle?: boolean | undefined; showYAxisTitle?: boolean | undefined; } | undefined; emphasizeFitting?: boolean | undefined; fittingFunction?: \"None\" | \"Average\" | \"Zero\" | \"Nearest\" | \"Linear\" | \"Carry\" | \"Lookahead\" | undefined; yBounds?: ", + "LensYBoundsConfig", + " | undefined; } & { id: string; }; }; metric: { dockerContainerMemoryUsage: { title: string; dataset?: ", + "LensDataset", + " | undefined; label?: string | undefined; filter?: string | undefined; format?: \"string\" | \"number\" | \"duration\" | \"percent\" | \"currency\" | \"bytes\" | \"bits\" | undefined; decimals?: number | undefined; normalizeByUnit?: \"m\" | \"d\" | \"h\" | \"s\" | undefined; compactValues?: boolean | undefined; randomSampling?: number | undefined; useGlobalFilter?: boolean | undefined; seriesColor?: string | undefined; value: string; chartType: \"metric\"; querySecondaryMetric?: string | undefined; queryMaxValue?: string | undefined; breakdown?: ", + "LensBreakdownConfig", + " | undefined; trendLine?: boolean | undefined; subtitle?: string | undefined; } & { id: string; }; k8sContainerMemoryUsage: { title: string; dataset?: ", + "LensDataset", + " | undefined; label?: string | undefined; filter?: string | undefined; format?: \"string\" | \"number\" | \"duration\" | \"percent\" | \"currency\" | \"bytes\" | \"bits\" | undefined; decimals?: number | undefined; normalizeByUnit?: \"m\" | \"d\" | \"h\" | \"s\" | undefined; compactValues?: boolean | undefined; randomSampling?: number | undefined; useGlobalFilter?: boolean | undefined; seriesColor?: string | undefined; value: string; chartType: \"metric\"; querySecondaryMetric?: string | undefined; queryMaxValue?: string | undefined; breakdown?: ", + "LensBreakdownConfig", + " | undefined; trendLine?: boolean | undefined; subtitle?: string | undefined; } & { id: string; }; }; }; }>>)[]" ], "path": "x-pack/plugins/observability_solution/metrics_data_access/common/inventory_models/index.ts", "deprecated": false, diff --git a/api_docs/metrics_data_access.mdx b/api_docs/metrics_data_access.mdx index ccd39f2162bbf..198a88d6d3b22 100644 --- a/api_docs/metrics_data_access.mdx +++ b/api_docs/metrics_data_access.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/metricsDataAccess title: "metricsDataAccess" image: https://source.unsplash.com/400x175/?github description: API docs for the metricsDataAccess plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'metricsDataAccess'] --- import metricsDataAccessObj from './metrics_data_access.devdocs.json'; diff --git a/api_docs/ml.mdx b/api_docs/ml.mdx index 4f8c6b6fe013a..cc3a12fe8a590 100644 --- a/api_docs/ml.mdx +++ b/api_docs/ml.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/ml title: "ml" image: https://source.unsplash.com/400x175/?github description: API docs for the ml plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'ml'] --- import mlObj from './ml.devdocs.json'; diff --git a/api_docs/mock_idp_plugin.mdx b/api_docs/mock_idp_plugin.mdx index 73a8c8b5c7d31..52f90e201be8f 100644 --- a/api_docs/mock_idp_plugin.mdx +++ b/api_docs/mock_idp_plugin.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/mockIdpPlugin title: "mockIdpPlugin" image: https://source.unsplash.com/400x175/?github description: API docs for the mockIdpPlugin plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'mockIdpPlugin'] --- import mockIdpPluginObj from './mock_idp_plugin.devdocs.json'; diff --git a/api_docs/monitoring.mdx b/api_docs/monitoring.mdx index 40cec41f85dda..4b58490652ace 100644 --- a/api_docs/monitoring.mdx +++ b/api_docs/monitoring.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/monitoring title: "monitoring" image: https://source.unsplash.com/400x175/?github description: API docs for the monitoring plugin -date: 2024-05-16 +date: 2024-05-17 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 c80f1935b2f6e..feda619f2dde3 100644 --- a/api_docs/monitoring_collection.mdx +++ b/api_docs/monitoring_collection.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/monitoringCollection title: "monitoringCollection" image: https://source.unsplash.com/400x175/?github description: API docs for the monitoringCollection plugin -date: 2024-05-16 +date: 2024-05-17 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 b81fed6e69a37..1e7b8ef379f8f 100644 --- a/api_docs/navigation.mdx +++ b/api_docs/navigation.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/navigation title: "navigation" image: https://source.unsplash.com/400x175/?github description: API docs for the navigation plugin -date: 2024-05-16 +date: 2024-05-17 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 397df74040477..b85d674a84232 100644 --- a/api_docs/newsfeed.mdx +++ b/api_docs/newsfeed.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/newsfeed title: "newsfeed" image: https://source.unsplash.com/400x175/?github description: API docs for the newsfeed plugin -date: 2024-05-16 +date: 2024-05-17 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 5a3533019838b..2c274f8a5b07a 100644 --- a/api_docs/no_data_page.mdx +++ b/api_docs/no_data_page.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/noDataPage title: "noDataPage" image: https://source.unsplash.com/400x175/?github description: API docs for the noDataPage plugin -date: 2024-05-16 +date: 2024-05-17 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 0dd53fb82f210..3f6937d1fe7fa 100644 --- a/api_docs/notifications.mdx +++ b/api_docs/notifications.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/notifications title: "notifications" image: https://source.unsplash.com/400x175/?github description: API docs for the notifications plugin -date: 2024-05-16 +date: 2024-05-17 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 3cffa85091ec5..977e46df309f5 100644 --- a/api_docs/observability.devdocs.json +++ b/api_docs/observability.devdocs.json @@ -4521,6 +4521,21 @@ "trackAdoption": false, "initialIsOpen": false }, + { + "parentPluginId": "observability", + "id": "def-public.enableInfrastructureContainerAssetView", + "type": "string", + "tags": [], + "label": "enableInfrastructureContainerAssetView", + "description": [], + "signature": [ + "\"observability:enableInfrastructureContainerAssetView\"" + ], + "path": "x-pack/plugins/observability_solution/observability/common/ui_settings_keys.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, { "parentPluginId": "observability", "id": "def-public.enableInfrastructureHostsView", @@ -10105,6 +10120,90 @@ } ] }, + { + "parentPluginId": "observability", + "id": "def-server.uiSettings.enableInfrastructureContainerAssetView", + "type": "Object", + "tags": [], + "label": "[enableInfrastructureContainerAssetView]", + "description": [], + "path": "x-pack/plugins/observability_solution/observability/server/ui_settings.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "observability", + "id": "def-server.uiSettings.enableInfrastructureContainerAssetView.category", + "type": "Array", + "tags": [], + "label": "category", + "description": [], + "signature": [ + "string[]" + ], + "path": "x-pack/plugins/observability_solution/observability/server/ui_settings.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "observability", + "id": "def-server.uiSettings.enableInfrastructureContainerAssetView.name", + "type": "string", + "tags": [], + "label": "name", + "description": [], + "path": "x-pack/plugins/observability_solution/observability/server/ui_settings.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "observability", + "id": "def-server.uiSettings.enableInfrastructureContainerAssetView.value", + "type": "boolean", + "tags": [], + "label": "value", + "description": [], + "signature": [ + "false" + ], + "path": "x-pack/plugins/observability_solution/observability/server/ui_settings.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "observability", + "id": "def-server.uiSettings.enableInfrastructureContainerAssetView.description", + "type": "string", + "tags": [], + "label": "description", + "description": [], + "path": "x-pack/plugins/observability_solution/observability/server/ui_settings.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "observability", + "id": "def-server.uiSettings.enableInfrastructureContainerAssetView.schema", + "type": "Object", + "tags": [], + "label": "schema", + "description": [], + "signature": [ + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "" + ], + "path": "x-pack/plugins/observability_solution/observability/server/ui_settings.ts", + "deprecated": false, + "trackAdoption": false + } + ] + }, { "parentPluginId": "observability", "id": "def-server.uiSettings.enableInfrastructureProfilingIntegration", @@ -14051,6 +14150,21 @@ "trackAdoption": false, "initialIsOpen": false }, + { + "parentPluginId": "observability", + "id": "def-common.enableInfrastructureContainerAssetView", + "type": "string", + "tags": [], + "label": "enableInfrastructureContainerAssetView", + "description": [], + "signature": [ + "\"observability:enableInfrastructureContainerAssetView\"" + ], + "path": "x-pack/plugins/observability_solution/observability/common/ui_settings_keys.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, { "parentPluginId": "observability", "id": "def-common.enableInfrastructureHostsView", diff --git a/api_docs/observability.mdx b/api_docs/observability.mdx index 4262ed9eec0b0..f561cc2b30f38 100644 --- a/api_docs/observability.mdx +++ b/api_docs/observability.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/observability title: "observability" image: https://source.unsplash.com/400x175/?github description: API docs for the observability plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'observability'] --- import observabilityObj from './observability.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/obs-ux-management-team](https://github.com/orgs/elastic/teams/ | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 687 | 2 | 678 | 15 | +| 695 | 2 | 686 | 15 | ## Client diff --git a/api_docs/observability_a_i_assistant.mdx b/api_docs/observability_a_i_assistant.mdx index 00c154ef7b9bd..f914b84526451 100644 --- a/api_docs/observability_a_i_assistant.mdx +++ b/api_docs/observability_a_i_assistant.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/observabilityAIAssistant title: "observabilityAIAssistant" image: https://source.unsplash.com/400x175/?github description: API docs for the observabilityAIAssistant plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'observabilityAIAssistant'] --- import observabilityAIAssistantObj from './observability_a_i_assistant.devdocs.json'; diff --git a/api_docs/observability_a_i_assistant_app.mdx b/api_docs/observability_a_i_assistant_app.mdx index 94079a6a623ab..af86bb282745b 100644 --- a/api_docs/observability_a_i_assistant_app.mdx +++ b/api_docs/observability_a_i_assistant_app.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/observabilityAIAssistantApp title: "observabilityAIAssistantApp" image: https://source.unsplash.com/400x175/?github description: API docs for the observabilityAIAssistantApp plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'observabilityAIAssistantApp'] --- import observabilityAIAssistantAppObj from './observability_a_i_assistant_app.devdocs.json'; diff --git a/api_docs/observability_ai_assistant_management.mdx b/api_docs/observability_ai_assistant_management.mdx index dff0be9912090..01fb2eb61183a 100644 --- a/api_docs/observability_ai_assistant_management.mdx +++ b/api_docs/observability_ai_assistant_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/observabilityAiAssistantManagement title: "observabilityAiAssistantManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the observabilityAiAssistantManagement plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'observabilityAiAssistantManagement'] --- import observabilityAiAssistantManagementObj from './observability_ai_assistant_management.devdocs.json'; diff --git a/api_docs/observability_logs_explorer.mdx b/api_docs/observability_logs_explorer.mdx index de588320fe4d1..0fc72712b45b0 100644 --- a/api_docs/observability_logs_explorer.mdx +++ b/api_docs/observability_logs_explorer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/observabilityLogsExplorer title: "observabilityLogsExplorer" image: https://source.unsplash.com/400x175/?github description: API docs for the observabilityLogsExplorer plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'observabilityLogsExplorer'] --- import observabilityLogsExplorerObj from './observability_logs_explorer.devdocs.json'; diff --git a/api_docs/observability_onboarding.mdx b/api_docs/observability_onboarding.mdx index b6c68453a523a..c5e4c62abe8e8 100644 --- a/api_docs/observability_onboarding.mdx +++ b/api_docs/observability_onboarding.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/observabilityOnboarding title: "observabilityOnboarding" image: https://source.unsplash.com/400x175/?github description: API docs for the observabilityOnboarding plugin -date: 2024-05-16 +date: 2024-05-17 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 a9e2a3bac29c6..26f7ba67398be 100644 --- a/api_docs/observability_shared.mdx +++ b/api_docs/observability_shared.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/observabilityShared title: "observabilityShared" image: https://source.unsplash.com/400x175/?github description: API docs for the observabilityShared plugin -date: 2024-05-16 +date: 2024-05-17 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 8a9550166fc8d..d65e6fd1cb6b7 100644 --- a/api_docs/osquery.mdx +++ b/api_docs/osquery.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/osquery title: "osquery" image: https://source.unsplash.com/400x175/?github description: API docs for the osquery plugin -date: 2024-05-16 +date: 2024-05-17 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 2bb9abcc168ee..de7c5bd7b1e8f 100644 --- a/api_docs/painless_lab.mdx +++ b/api_docs/painless_lab.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/painlessLab title: "painlessLab" image: https://source.unsplash.com/400x175/?github description: API docs for the painlessLab plugin -date: 2024-05-16 +date: 2024-05-17 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 3e64d151f37b2..0a85ec1f71028 100644 --- a/api_docs/plugin_directory.mdx +++ b/api_docs/plugin_directory.mdx @@ -7,7 +7,7 @@ id: kibDevDocsPluginDirectory slug: /kibana-dev-docs/api-meta/plugin-api-directory title: Directory description: Directory of public APIs available through plugins or packages. -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- @@ -21,7 +21,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | API Count | Any Count | Missing comments | Missing exports | |--------------|----------|-----------------|--------| -| 48169 | 241 | 36749 | 1858 | +| 48193 | 241 | 36773 | 1860 | ## Plugin Directory @@ -142,7 +142,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 17 | 0 | 17 | 0 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 3 | 0 | 3 | 0 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 2 | 0 | 2 | 1 | -| | [@elastic/obs-ux-management-team](https://github.com/orgs/elastic/teams/obs-ux-management-team) | - | 687 | 2 | 678 | 15 | +| | [@elastic/obs-ux-management-team](https://github.com/orgs/elastic/teams/obs-ux-management-team) | - | 695 | 2 | 686 | 15 | | | [@elastic/obs-ai-assistant](https://github.com/orgs/elastic/teams/obs-ai-assistant) | - | 253 | 1 | 251 | 26 | | | [@elastic/obs-ai-assistant](https://github.com/orgs/elastic/teams/obs-ai-assistant) | - | 2 | 0 | 2 | 0 | | | [@elastic/obs-ai-assistant](https://github.com/orgs/elastic/teams/obs-ai-assistant) | - | 2 | 0 | 2 | 0 | @@ -249,7 +249,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 18 | 0 | 18 | 0 | | | [@elastic/obs-ux-infra_services-team](https://github.com/orgs/elastic/teams/obs-ux-infra_services-team) | - | 4 | 0 | 4 | 0 | | | [@elastic/obs-ux-infra_services-team](https://github.com/orgs/elastic/teams/obs-ux-infra_services-team) | - | 49 | 0 | 49 | 8 | -| | [@elastic/obs-ux-infra_services-team](https://github.com/orgs/elastic/teams/obs-ux-infra_services-team) | - | 191 | 0 | 191 | 28 | +| | [@elastic/obs-ux-infra_services-team](https://github.com/orgs/elastic/teams/obs-ux-infra_services-team) | - | 193 | 0 | 193 | 30 | | | [@elastic/obs-ux-infra_services-team](https://github.com/orgs/elastic/teams/obs-ux-infra_services-team) | - | 11 | 0 | 11 | 0 | | | [@elastic/kibana-qa](https://github.com/orgs/elastic/teams/kibana-qa) | - | 12 | 0 | 12 | 0 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 4 | 0 | 1 | 0 | @@ -538,7 +538,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/kibana-management](https://github.com/orgs/elastic/teams/kibana-management) | - | 23 | 0 | 7 | 0 | | | [@elastic/kibana-management](https://github.com/orgs/elastic/teams/kibana-management) | - | 8 | 0 | 2 | 3 | | | [@elastic/kibana-management](https://github.com/orgs/elastic/teams/kibana-management) | - | 45 | 0 | 0 | 0 | -| | [@elastic/appex-sharedux @elastic/kibana-management](https://github.com/orgs/elastic/teams/appex-sharedux ) | - | 138 | 0 | 135 | 0 | +| | [@elastic/appex-sharedux @elastic/kibana-management](https://github.com/orgs/elastic/teams/appex-sharedux ) | - | 139 | 0 | 136 | 0 | | | [@elastic/appex-sharedux @elastic/kibana-management](https://github.com/orgs/elastic/teams/appex-sharedux ) | - | 20 | 0 | 11 | 0 | | | [@elastic/kibana-management](https://github.com/orgs/elastic/teams/kibana-management) | - | 88 | 0 | 10 | 0 | | | [@elastic/kibana-management](https://github.com/orgs/elastic/teams/kibana-management) | - | 56 | 0 | 6 | 0 | @@ -621,8 +621,8 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/response-ops](https://github.com/orgs/elastic/teams/response-ops) | - | 16 | 0 | 16 | 1 | | | [@elastic/security-detections-response](https://github.com/orgs/elastic/teams/security-detections-response) | - | 125 | 0 | 122 | 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) | - | 74 | 0 | 74 | 0 | -| | [@elastic/enterprise-search-frontend](https://github.com/orgs/elastic/teams/enterprise-search-frontend) | - | 3661 | 0 | 3661 | 0 | +| | [@elastic/enterprise-search-frontend](https://github.com/orgs/elastic/teams/enterprise-search-frontend) | - | 76 | 0 | 76 | 0 | +| | [@elastic/enterprise-search-frontend](https://github.com/orgs/elastic/teams/enterprise-search-frontend) | - | 3672 | 0 | 3672 | 0 | | | [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | - | 18 | 1 | 17 | 1 | | | [@elastic/enterprise-search-frontend](https://github.com/orgs/elastic/teams/enterprise-search-frontend) | - | 25 | 0 | 25 | 0 | | | [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | - | 20 | 0 | 18 | 1 | diff --git a/api_docs/presentation_panel.mdx b/api_docs/presentation_panel.mdx index 2145e99247362..17ae841e4cf7d 100644 --- a/api_docs/presentation_panel.mdx +++ b/api_docs/presentation_panel.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/presentationPanel title: "presentationPanel" image: https://source.unsplash.com/400x175/?github description: API docs for the presentationPanel plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'presentationPanel'] --- import presentationPanelObj from './presentation_panel.devdocs.json'; diff --git a/api_docs/presentation_util.mdx b/api_docs/presentation_util.mdx index da95f22c5d43b..e6d914b993e9a 100644 --- a/api_docs/presentation_util.mdx +++ b/api_docs/presentation_util.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/presentationUtil title: "presentationUtil" image: https://source.unsplash.com/400x175/?github description: API docs for the presentationUtil plugin -date: 2024-05-16 +date: 2024-05-17 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 59bcde1e25540..d9b6d1e49dc00 100644 --- a/api_docs/profiling.mdx +++ b/api_docs/profiling.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/profiling title: "profiling" image: https://source.unsplash.com/400x175/?github description: API docs for the profiling plugin -date: 2024-05-16 +date: 2024-05-17 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 7e50e73193555..450b95b62aee9 100644 --- a/api_docs/profiling_data_access.mdx +++ b/api_docs/profiling_data_access.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/profilingDataAccess title: "profilingDataAccess" image: https://source.unsplash.com/400x175/?github description: API docs for the profilingDataAccess plugin -date: 2024-05-16 +date: 2024-05-17 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 3c2a53eb016ad..627f617141db3 100644 --- a/api_docs/remote_clusters.mdx +++ b/api_docs/remote_clusters.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/remoteClusters title: "remoteClusters" image: https://source.unsplash.com/400x175/?github description: API docs for the remoteClusters plugin -date: 2024-05-16 +date: 2024-05-17 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 2a05fe65cb673..cfbfe38c627e7 100644 --- a/api_docs/reporting.mdx +++ b/api_docs/reporting.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/reporting title: "reporting" image: https://source.unsplash.com/400x175/?github description: API docs for the reporting plugin -date: 2024-05-16 +date: 2024-05-17 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 23bf7e53d0667..bab44d5f808c0 100644 --- a/api_docs/rollup.mdx +++ b/api_docs/rollup.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/rollup title: "rollup" image: https://source.unsplash.com/400x175/?github description: API docs for the rollup plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'rollup'] --- import rollupObj from './rollup.devdocs.json'; diff --git a/api_docs/rule_registry.mdx b/api_docs/rule_registry.mdx index e36801de65fe5..3aae98fbefbb0 100644 --- a/api_docs/rule_registry.mdx +++ b/api_docs/rule_registry.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/ruleRegistry title: "ruleRegistry" image: https://source.unsplash.com/400x175/?github description: API docs for the ruleRegistry plugin -date: 2024-05-16 +date: 2024-05-17 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 aacbce38894b8..1be7f3ab83872 100644 --- a/api_docs/runtime_fields.mdx +++ b/api_docs/runtime_fields.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/runtimeFields title: "runtimeFields" image: https://source.unsplash.com/400x175/?github description: API docs for the runtimeFields plugin -date: 2024-05-16 +date: 2024-05-17 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 2bc1a39cc90c6..789683d0e9f0b 100644 --- a/api_docs/saved_objects.mdx +++ b/api_docs/saved_objects.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedObjects title: "savedObjects" image: https://source.unsplash.com/400x175/?github description: API docs for the savedObjects plugin -date: 2024-05-16 +date: 2024-05-17 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 46ae5fbff6659..8767f1d956706 100644 --- a/api_docs/saved_objects_finder.mdx +++ b/api_docs/saved_objects_finder.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedObjectsFinder title: "savedObjectsFinder" image: https://source.unsplash.com/400x175/?github description: API docs for the savedObjectsFinder plugin -date: 2024-05-16 +date: 2024-05-17 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 e20f831efa6aa..24881313fef48 100644 --- a/api_docs/saved_objects_management.mdx +++ b/api_docs/saved_objects_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedObjectsManagement title: "savedObjectsManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the savedObjectsManagement plugin -date: 2024-05-16 +date: 2024-05-17 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 f28487633f2da..3bdf5ca9305c6 100644 --- a/api_docs/saved_objects_tagging.mdx +++ b/api_docs/saved_objects_tagging.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedObjectsTagging title: "savedObjectsTagging" image: https://source.unsplash.com/400x175/?github description: API docs for the savedObjectsTagging plugin -date: 2024-05-16 +date: 2024-05-17 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 3bc20357ed071..ac922dcccf9a6 100644 --- a/api_docs/saved_objects_tagging_oss.mdx +++ b/api_docs/saved_objects_tagging_oss.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedObjectsTaggingOss title: "savedObjectsTaggingOss" image: https://source.unsplash.com/400x175/?github description: API docs for the savedObjectsTaggingOss plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjectsTaggingOss'] --- import savedObjectsTaggingOssObj from './saved_objects_tagging_oss.devdocs.json'; diff --git a/api_docs/saved_search.mdx b/api_docs/saved_search.mdx index b8692decda8e9..41bb46f258268 100644 --- a/api_docs/saved_search.mdx +++ b/api_docs/saved_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedSearch title: "savedSearch" image: https://source.unsplash.com/400x175/?github description: API docs for the savedSearch plugin -date: 2024-05-16 +date: 2024-05-17 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 72f430068b701..b0b21f7ef1698 100644 --- a/api_docs/screenshot_mode.mdx +++ b/api_docs/screenshot_mode.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/screenshotMode title: "screenshotMode" image: https://source.unsplash.com/400x175/?github description: API docs for the screenshotMode plugin -date: 2024-05-16 +date: 2024-05-17 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 712304b5e4224..675cee452135c 100644 --- a/api_docs/screenshotting.mdx +++ b/api_docs/screenshotting.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/screenshotting title: "screenshotting" image: https://source.unsplash.com/400x175/?github description: API docs for the screenshotting plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'screenshotting'] --- import screenshottingObj from './screenshotting.devdocs.json'; diff --git a/api_docs/search_connectors.mdx b/api_docs/search_connectors.mdx index 1ac19f6cbeeb9..4f26ccc544955 100644 --- a/api_docs/search_connectors.mdx +++ b/api_docs/search_connectors.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/searchConnectors title: "searchConnectors" image: https://source.unsplash.com/400x175/?github description: API docs for the searchConnectors plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'searchConnectors'] --- import searchConnectorsObj from './search_connectors.devdocs.json'; diff --git a/api_docs/search_notebooks.mdx b/api_docs/search_notebooks.mdx index e10f9cbb278ac..8d42178f20e00 100644 --- a/api_docs/search_notebooks.mdx +++ b/api_docs/search_notebooks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/searchNotebooks title: "searchNotebooks" image: https://source.unsplash.com/400x175/?github description: API docs for the searchNotebooks plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'searchNotebooks'] --- import searchNotebooksObj from './search_notebooks.devdocs.json'; diff --git a/api_docs/search_playground.mdx b/api_docs/search_playground.mdx index ad30d44332bc3..5066649de862d 100644 --- a/api_docs/search_playground.mdx +++ b/api_docs/search_playground.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/searchPlayground title: "searchPlayground" image: https://source.unsplash.com/400x175/?github description: API docs for the searchPlayground plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'searchPlayground'] --- import searchPlaygroundObj from './search_playground.devdocs.json'; diff --git a/api_docs/security.mdx b/api_docs/security.mdx index 9cc1a66ad2cad..d35d950f51d48 100644 --- a/api_docs/security.mdx +++ b/api_docs/security.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/security title: "security" image: https://source.unsplash.com/400x175/?github description: API docs for the security plugin -date: 2024-05-16 +date: 2024-05-17 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 85c8a7e004df7..75e3bfcc21f7e 100644 --- a/api_docs/security_solution.mdx +++ b/api_docs/security_solution.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/securitySolution title: "securitySolution" image: https://source.unsplash.com/400x175/?github description: API docs for the securitySolution plugin -date: 2024-05-16 +date: 2024-05-17 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 fea3359dc12e8..8d1e4b618f3cf 100644 --- a/api_docs/security_solution_ess.mdx +++ b/api_docs/security_solution_ess.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/securitySolutionEss title: "securitySolutionEss" image: https://source.unsplash.com/400x175/?github description: API docs for the securitySolutionEss plugin -date: 2024-05-16 +date: 2024-05-17 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 d6ddfb15b8aa3..f1ddf26d0a3b7 100644 --- a/api_docs/security_solution_serverless.mdx +++ b/api_docs/security_solution_serverless.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/securitySolutionServerless title: "securitySolutionServerless" image: https://source.unsplash.com/400x175/?github description: API docs for the securitySolutionServerless plugin -date: 2024-05-16 +date: 2024-05-17 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 30cbb8e5ac8a7..49fce71c23171 100644 --- a/api_docs/serverless.mdx +++ b/api_docs/serverless.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/serverless title: "serverless" image: https://source.unsplash.com/400x175/?github description: API docs for the serverless plugin -date: 2024-05-16 +date: 2024-05-17 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 cf0a98ae88b87..7f7135ff16625 100644 --- a/api_docs/serverless_observability.mdx +++ b/api_docs/serverless_observability.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/serverlessObservability title: "serverlessObservability" image: https://source.unsplash.com/400x175/?github description: API docs for the serverlessObservability plugin -date: 2024-05-16 +date: 2024-05-17 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 1cb1741ffda15..f15d76343d1da 100644 --- a/api_docs/serverless_search.mdx +++ b/api_docs/serverless_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/serverlessSearch title: "serverlessSearch" image: https://source.unsplash.com/400x175/?github description: API docs for the serverlessSearch plugin -date: 2024-05-16 +date: 2024-05-17 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 c1f4d9050b1ef..1d8b1d434f1bb 100644 --- a/api_docs/session_view.mdx +++ b/api_docs/session_view.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/sessionView title: "sessionView" image: https://source.unsplash.com/400x175/?github description: API docs for the sessionView plugin -date: 2024-05-16 +date: 2024-05-17 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 8c720971ed0a1..8bc9855effad1 100644 --- a/api_docs/share.mdx +++ b/api_docs/share.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/share title: "share" image: https://source.unsplash.com/400x175/?github description: API docs for the share plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'share'] --- import shareObj from './share.devdocs.json'; diff --git a/api_docs/slo.devdocs.json b/api_docs/slo.devdocs.json index 7641ca4b43fd5..02cfed22cb843 100644 --- a/api_docs/slo.devdocs.json +++ b/api_docs/slo.devdocs.json @@ -1256,7 +1256,7 @@ }, "<", "CreateSLOForm", - "<{ type: \"sli.apm.transactionDuration\"; params: { environment: string; service: string; transactionType: string; transactionName: string; threshold: number; index: string; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; index: string; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }; } | { type: \"sli.synthetics.availability\"; params: { monitorIds: { value: string; label: string; }[]; index: string; } & { tags?: { value: string; label: string; }[] | undefined; projects?: { value: string; label: string; }[] | undefined; filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; good: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; }; total: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; }; timestampField: string; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }; } | { type: \"sli.metric.custom\"; params: { index: string; good: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }))[]; equation: string; }; total: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }))[]; equation: string; }; timestampField: string; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }; } | { type: \"sli.metric.timeslice\"; params: { index: string; metric: { metrics: (({ name: string; aggregation: \"min\" | \"max\" | \"sum\" | \"avg\" | \"last_value\" | \"cardinality\" | \"std_deviation\"; field: string; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }) | ({ name: string; aggregation: \"percentile\"; field: string; percentile: number; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }))[]; equation: string; threshold: number; comparator: \"GT\" | \"GTE\" | \"LT\" | \"LTE\"; }; timestampField: string; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }; } | { type: \"sli.histogram.custom\"; params: { index: string; timestampField: string; good: ({ field: string; aggregation: \"value_count\"; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }); total: ({ field: string; aggregation: \"value_count\"; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }); } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }; }>> | undefined; }) => Promise; }" + "<{ type: \"sli.apm.transactionDuration\"; params: { environment: string; service: string; transactionType: string; transactionName: string; threshold: number; index: string; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }; } | { type: \"sli.apm.transactionErrorRate\"; params: { environment: string; service: string; transactionType: string; transactionName: string; index: string; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }; } | { type: \"sli.synthetics.availability\"; params: { monitorIds: { value: string; label: string; }[]; index: string; } & { tags?: { value: string; label: string; }[] | undefined; projects?: { value: string; label: string; }[] | undefined; filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }; } | { type: \"sli.kql.custom\"; params: { index: string; good: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; }; total: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; }; timestampField: string; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }; } | { type: \"sli.metric.custom\"; params: { index: string; good: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }))[]; equation: string; }; total: { metrics: (({ name: string; aggregation: \"sum\"; field: string; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }))[]; equation: string; }; timestampField: string; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }; } | { type: \"sli.metric.timeslice\"; params: { index: string; metric: { metrics: (({ name: string; aggregation: \"min\" | \"max\" | \"sum\" | \"avg\" | \"last_value\" | \"cardinality\" | \"std_deviation\"; field: string; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }) | ({ name: string; aggregation: \"doc_count\"; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }) | ({ name: string; aggregation: \"percentile\"; field: string; percentile: number; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }))[]; equation: string; threshold: number; comparator: \"GT\" | \"GTE\" | \"LT\" | \"LTE\"; }; timestampField: string; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }; } | { type: \"sli.histogram.custom\"; params: { index: string; timestampField: string; good: ({ field: string; aggregation: \"value_count\"; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }); total: ({ field: string; aggregation: \"value_count\"; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }) | ({ field: string; aggregation: \"range\"; from: number; to: number; } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }); } & { filter?: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; } | undefined; }; }>> | undefined; }) => JSX.Element; }" ], "path": "x-pack/plugins/observability_solution/slo/public/types.ts", "deprecated": false, diff --git a/api_docs/slo.mdx b/api_docs/slo.mdx index 8b5389648d7be..edb940a1a20ae 100644 --- a/api_docs/slo.mdx +++ b/api_docs/slo.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/slo title: "slo" image: https://source.unsplash.com/400x175/?github description: API docs for the slo plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'slo'] --- import sloObj from './slo.devdocs.json'; diff --git a/api_docs/snapshot_restore.mdx b/api_docs/snapshot_restore.mdx index f6aaf051b3b9a..bc3e5500f7e51 100644 --- a/api_docs/snapshot_restore.mdx +++ b/api_docs/snapshot_restore.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/snapshotRestore title: "snapshotRestore" image: https://source.unsplash.com/400x175/?github description: API docs for the snapshotRestore plugin -date: 2024-05-16 +date: 2024-05-17 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 830a9e5aca980..ecccab49e53ad 100644 --- a/api_docs/spaces.mdx +++ b/api_docs/spaces.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/spaces title: "spaces" image: https://source.unsplash.com/400x175/?github description: API docs for the spaces plugin -date: 2024-05-16 +date: 2024-05-17 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 812a693b535ed..de2e177b8d43d 100644 --- a/api_docs/stack_alerts.mdx +++ b/api_docs/stack_alerts.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/stackAlerts title: "stackAlerts" image: https://source.unsplash.com/400x175/?github description: API docs for the stackAlerts plugin -date: 2024-05-16 +date: 2024-05-17 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 02eb6962b84dd..9aa5b7dbc4989 100644 --- a/api_docs/stack_connectors.mdx +++ b/api_docs/stack_connectors.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/stackConnectors title: "stackConnectors" image: https://source.unsplash.com/400x175/?github description: API docs for the stackConnectors plugin -date: 2024-05-16 +date: 2024-05-17 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 516c11d380aa9..d315f52b1e028 100644 --- a/api_docs/task_manager.mdx +++ b/api_docs/task_manager.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/taskManager title: "taskManager" image: https://source.unsplash.com/400x175/?github description: API docs for the taskManager plugin -date: 2024-05-16 +date: 2024-05-17 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 74631a8919b1e..bd9a2bba7bbf1 100644 --- a/api_docs/telemetry.mdx +++ b/api_docs/telemetry.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/telemetry title: "telemetry" image: https://source.unsplash.com/400x175/?github description: API docs for the telemetry plugin -date: 2024-05-16 +date: 2024-05-17 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 053edf9c9126d..1661a32a6d3c7 100644 --- a/api_docs/telemetry_collection_manager.mdx +++ b/api_docs/telemetry_collection_manager.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/telemetryCollectionManager title: "telemetryCollectionManager" image: https://source.unsplash.com/400x175/?github description: API docs for the telemetryCollectionManager plugin -date: 2024-05-16 +date: 2024-05-17 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 b90952aa40d1d..2d9f16cf8dbf4 100644 --- a/api_docs/telemetry_collection_xpack.mdx +++ b/api_docs/telemetry_collection_xpack.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/telemetryCollectionXpack title: "telemetryCollectionXpack" image: https://source.unsplash.com/400x175/?github description: API docs for the telemetryCollectionXpack plugin -date: 2024-05-16 +date: 2024-05-17 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 857fc60f97275..dab9fb8c7c0b2 100644 --- a/api_docs/telemetry_management_section.mdx +++ b/api_docs/telemetry_management_section.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/telemetryManagementSection title: "telemetryManagementSection" image: https://source.unsplash.com/400x175/?github description: API docs for the telemetryManagementSection plugin -date: 2024-05-16 +date: 2024-05-17 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 8ecaf47a13738..0602d9f0463bf 100644 --- a/api_docs/text_based_languages.mdx +++ b/api_docs/text_based_languages.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/textBasedLanguages title: "textBasedLanguages" image: https://source.unsplash.com/400x175/?github description: API docs for the textBasedLanguages plugin -date: 2024-05-16 +date: 2024-05-17 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 378d0497d9775..cd2e9d3f30b2e 100644 --- a/api_docs/threat_intelligence.mdx +++ b/api_docs/threat_intelligence.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/threatIntelligence title: "threatIntelligence" image: https://source.unsplash.com/400x175/?github description: API docs for the threatIntelligence plugin -date: 2024-05-16 +date: 2024-05-17 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 e1022f8e64e82..15785d5e9c77d 100644 --- a/api_docs/timelines.mdx +++ b/api_docs/timelines.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/timelines title: "timelines" image: https://source.unsplash.com/400x175/?github description: API docs for the timelines plugin -date: 2024-05-16 +date: 2024-05-17 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 9bda799d01487..5c6e086cdbe9c 100644 --- a/api_docs/transform.mdx +++ b/api_docs/transform.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/transform title: "transform" image: https://source.unsplash.com/400x175/?github description: API docs for the transform plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'transform'] --- import transformObj from './transform.devdocs.json'; diff --git a/api_docs/triggers_actions_ui.mdx b/api_docs/triggers_actions_ui.mdx index 4ff64d38543aa..948a680134bf6 100644 --- a/api_docs/triggers_actions_ui.mdx +++ b/api_docs/triggers_actions_ui.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/triggersActionsUi title: "triggersActionsUi" image: https://source.unsplash.com/400x175/?github description: API docs for the triggersActionsUi plugin -date: 2024-05-16 +date: 2024-05-17 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 709beb47f717d..d29f81c4b8e70 100644 --- a/api_docs/ui_actions.mdx +++ b/api_docs/ui_actions.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/uiActions title: "uiActions" image: https://source.unsplash.com/400x175/?github description: API docs for the uiActions plugin -date: 2024-05-16 +date: 2024-05-17 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 3a0eae1a653d8..24e68e14aff39 100644 --- a/api_docs/ui_actions_enhanced.mdx +++ b/api_docs/ui_actions_enhanced.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/uiActionsEnhanced title: "uiActionsEnhanced" image: https://source.unsplash.com/400x175/?github description: API docs for the uiActionsEnhanced plugin -date: 2024-05-16 +date: 2024-05-17 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 73a64d8061abd..ace5e5c862af6 100644 --- a/api_docs/unified_doc_viewer.mdx +++ b/api_docs/unified_doc_viewer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/unifiedDocViewer title: "unifiedDocViewer" image: https://source.unsplash.com/400x175/?github description: API docs for the unifiedDocViewer plugin -date: 2024-05-16 +date: 2024-05-17 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 69324711e559b..a01553de13ec7 100644 --- a/api_docs/unified_histogram.mdx +++ b/api_docs/unified_histogram.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/unifiedHistogram title: "unifiedHistogram" image: https://source.unsplash.com/400x175/?github description: API docs for the unifiedHistogram plugin -date: 2024-05-16 +date: 2024-05-17 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 4f96aa3a99e84..da0d4980397d0 100644 --- a/api_docs/unified_search.mdx +++ b/api_docs/unified_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/unifiedSearch title: "unifiedSearch" image: https://source.unsplash.com/400x175/?github description: API docs for the unifiedSearch plugin -date: 2024-05-16 +date: 2024-05-17 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 22caefb2c4aa7..bb8e9a67fe88f 100644 --- a/api_docs/unified_search_autocomplete.mdx +++ b/api_docs/unified_search_autocomplete.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/unifiedSearch-autocomplete title: "unifiedSearch.autocomplete" image: https://source.unsplash.com/400x175/?github description: API docs for the unifiedSearch.autocomplete plugin -date: 2024-05-16 +date: 2024-05-17 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 75c3728f3990a..d1f9c494f3a48 100644 --- a/api_docs/uptime.mdx +++ b/api_docs/uptime.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/uptime title: "uptime" image: https://source.unsplash.com/400x175/?github description: API docs for the uptime plugin -date: 2024-05-16 +date: 2024-05-17 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 89fb7f8808360..85b4d97d1e026 100644 --- a/api_docs/url_forwarding.mdx +++ b/api_docs/url_forwarding.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/urlForwarding title: "urlForwarding" image: https://source.unsplash.com/400x175/?github description: API docs for the urlForwarding plugin -date: 2024-05-16 +date: 2024-05-17 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 45c0fe42cf6ce..d1bb77ed006ef 100644 --- a/api_docs/usage_collection.mdx +++ b/api_docs/usage_collection.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/usageCollection title: "usageCollection" image: https://source.unsplash.com/400x175/?github description: API docs for the usageCollection plugin -date: 2024-05-16 +date: 2024-05-17 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 e53fe6a4b37c8..db6a1ca512588 100644 --- a/api_docs/ux.mdx +++ b/api_docs/ux.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/ux title: "ux" image: https://source.unsplash.com/400x175/?github description: API docs for the ux plugin -date: 2024-05-16 +date: 2024-05-17 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 17e298249be94..55570b4ff6a5b 100644 --- a/api_docs/vis_default_editor.mdx +++ b/api_docs/vis_default_editor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visDefaultEditor title: "visDefaultEditor" image: https://source.unsplash.com/400x175/?github description: API docs for the visDefaultEditor plugin -date: 2024-05-16 +date: 2024-05-17 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 f3adce8e310ca..897c86f288392 100644 --- a/api_docs/vis_type_gauge.mdx +++ b/api_docs/vis_type_gauge.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeGauge title: "visTypeGauge" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeGauge plugin -date: 2024-05-16 +date: 2024-05-17 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 5d6141e96a9cf..da0ff135945fd 100644 --- a/api_docs/vis_type_heatmap.mdx +++ b/api_docs/vis_type_heatmap.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeHeatmap title: "visTypeHeatmap" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeHeatmap plugin -date: 2024-05-16 +date: 2024-05-17 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 2696af2b3e9b5..5c8e4075daeec 100644 --- a/api_docs/vis_type_pie.mdx +++ b/api_docs/vis_type_pie.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypePie title: "visTypePie" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypePie plugin -date: 2024-05-16 +date: 2024-05-17 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 349085d407f44..36ee250be6b2f 100644 --- a/api_docs/vis_type_table.mdx +++ b/api_docs/vis_type_table.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeTable title: "visTypeTable" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeTable plugin -date: 2024-05-16 +date: 2024-05-17 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 b97fa189cac8b..b7c940f5b3377 100644 --- a/api_docs/vis_type_timelion.mdx +++ b/api_docs/vis_type_timelion.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeTimelion title: "visTypeTimelion" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeTimelion plugin -date: 2024-05-16 +date: 2024-05-17 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 ad4855319ba27..b1b6dac3edd80 100644 --- a/api_docs/vis_type_timeseries.mdx +++ b/api_docs/vis_type_timeseries.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeTimeseries title: "visTypeTimeseries" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeTimeseries plugin -date: 2024-05-16 +date: 2024-05-17 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 62ca2ea357824..184b4ec0d7070 100644 --- a/api_docs/vis_type_vega.mdx +++ b/api_docs/vis_type_vega.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeVega title: "visTypeVega" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeVega plugin -date: 2024-05-16 +date: 2024-05-17 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 9be604bdcc0da..207b8f90b309d 100644 --- a/api_docs/vis_type_vislib.mdx +++ b/api_docs/vis_type_vislib.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeVislib title: "visTypeVislib" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeVislib plugin -date: 2024-05-16 +date: 2024-05-17 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 31bdcc7b53bb3..028b77aa7c213 100644 --- a/api_docs/vis_type_xy.mdx +++ b/api_docs/vis_type_xy.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeXy title: "visTypeXy" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeXy plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeXy'] --- import visTypeXyObj from './vis_type_xy.devdocs.json'; diff --git a/api_docs/visualizations.mdx b/api_docs/visualizations.mdx index a33529abce609..a10ede7ef660a 100644 --- a/api_docs/visualizations.mdx +++ b/api_docs/visualizations.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visualizations title: "visualizations" image: https://source.unsplash.com/400x175/?github description: API docs for the visualizations plugin -date: 2024-05-16 +date: 2024-05-17 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visualizations'] --- import visualizationsObj from './visualizations.devdocs.json'; diff --git a/docs/api/role-management/get-all.asciidoc b/docs/api/role-management/get-all.asciidoc index 888bf0c8a137c..56c8b2c78859b 100644 --- a/docs/api/role-management/get-all.asciidoc +++ b/docs/api/role-management/get-all.asciidoc @@ -32,6 +32,7 @@ The API returns the following: [ { "name": "my_kibana_role", + "description": "My kibana role description", "metadata" : { "version" : 1 }, @@ -55,6 +56,7 @@ The API returns the following: }, { "name": "my_admin_role", + "description": "My admin role description", "metadata" : { "version" : 1 }, diff --git a/docs/api/role-management/get.asciidoc b/docs/api/role-management/get.asciidoc index b18b2e231774a..95f944a56e150 100644 --- a/docs/api/role-management/get.asciidoc +++ b/docs/api/role-management/get.asciidoc @@ -31,6 +31,7 @@ The API returns the following: -------------------------------------------------- { "name": "my_restricted_kibana_role", + "description": "My restricted kibana role description", "metadata" : { "version" : 1 }, diff --git a/docs/api/role-management/put.asciidoc b/docs/api/role-management/put.asciidoc index ce293f75b63ae..d68f3928a4063 100644 --- a/docs/api/role-management/put.asciidoc +++ b/docs/api/role-management/put.asciidoc @@ -21,6 +21,9 @@ To use the create or update role API, you must have the `manage_security` cluste [[role-management-api-response-body]] ==== Request body +`description`:: + (Optional, string) Description for the role. + `metadata`:: (Optional, object) In the `metadata` object, keys that begin with `_` are reserved for system usage. @@ -74,6 +77,7 @@ Grant access to various features in all spaces: -------------------------------------------------- $ curl -X PUT api/security/role/my_kibana_role { + "description": "my_kibana_role_description", "metadata": { "version": 1 }, @@ -112,6 +116,7 @@ Grant dashboard-only access to only the Marketing space: -------------------------------------------------- $ curl -X PUT api/security/role/my_kibana_role { + "description": "Grants dashboard-only access to only the Marketing space.", "metadata": { "version": 1 }, @@ -138,6 +143,7 @@ Grant full access to all features in the Default space: -------------------------------------------------- $ curl -X PUT api/security/role/my_kibana_role { + "description": "Grants full access to all features in the Default space.", "metadata": { "version": 1 }, @@ -162,6 +168,7 @@ Grant different access to different spaces: -------------------------------------------------- $ curl -X PUT api/security/role/my_kibana_role { + "description": "Grants full access to discover and dashboard features in the default space. Grants read access in the marketing, and sales spaces.", "metadata": { "version": 1 }, @@ -193,6 +200,7 @@ Grant access to {kib} and {es}: -------------------------------------------------- $ curl -X PUT api/security/role/my_kibana_role { + "description": "Grants all cluster privileges and full access to index1 and index2. Grants full access to remote_index1 and remote_index2, and the monitor_enrich cluster privilege on remote_cluster1. Grants all Kibana privileges in the default space.", "metadata": { "version": 1 }, diff --git a/docs/concepts/esql.asciidoc b/docs/concepts/esql.asciidoc index 97f4b82586322..0390f9f6e2bc7 100644 --- a/docs/concepts/esql.asciidoc +++ b/docs/concepts/esql.asciidoc @@ -1,23 +1,36 @@ [[esql]] === {esql} -preview::["Do not use {esql} on production environments. 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."] +The Elasticsearch Query Language, {esql}, makes it faster and easier to explore your data. -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. +{esql} is a piped language which 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. -[role="screenshot"] -image:images/esql-data-view-menu.png[An image of the Discover UI where users can access the {esql} feature, width=30%] +{esql} comes with its own dedicated {esql} Compute Engine for greater efficiency. With 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]. -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. +Here's how to use {esql} in the data view selector in **Discover**: -{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]. +[role="screenshot"] +image:images/esql-data-view-menu.png[An image of the Discover UI where users can access the {esql} feature, width=30%, align="center"] {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}]. +You can also use ES|QL queries to create panels on your dashboards, create enrich policies, and create alerting rules. + +For more detailed information about {esql} in Kibana, refer to {ref}/esql-kibana.html[Using {esql} in {kib}]. + +[NOTE] +==== +{esql} is enabled by default in {kib}. It can be +disabled using the `enableESQL` setting from the +{kibana-ref}/advanced-options.html[Advanced Settings]. + +This will hide the {esql} user interface from various applications. +However, users will be able to access existing {esql} artifacts like saved searches and visualizations. +==== [float] [[esql-observability]] @@ -35,6 +48,6 @@ Use {esql} to retrieve important information for investigation by using lookups. [[esql-whats-next]] ==== What's next? -Full documentation for this language is available in the {es} documentation, refer to {ref}/esql.html[{esql}]. +The main documentation for {esql} lives in the {ref}/esql.html[{es} docs]. -Alternatively, a short tutorial is available in the **Discover** section <>. \ No newline at end of file +We also have a short tutorial in the **Discover** docs: <>. \ No newline at end of file diff --git a/docs/concepts/images/esql-data-view-menu.png b/docs/concepts/images/esql-data-view-menu.png index fbbbdf44d315c..15e7365626ba8 100644 Binary files a/docs/concepts/images/esql-data-view-menu.png 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 index eb818a11cbacb..5f00248c10af2 100644 Binary files a/docs/concepts/images/esql-in-app-help.png and b/docs/concepts/images/esql-in-app-help.png differ diff --git a/docs/discover/try-esql.asciidoc b/docs/discover/try-esql.asciidoc index 7731700147e50..32718d87c955a 100644 --- a/docs/discover/try-esql.asciidoc +++ b/docs/discover/try-esql.asciidoc @@ -1,5 +1,5 @@ [[try-esql]] -== Try {esql} +== Using {esql} The Elasticsearch Query Language, {esql}, makes it easier to explore your data without leaving Discover. @@ -9,11 +9,11 @@ In this tutorial we'll use the {kib} sample web logs in Discover and Lens to exp [[prerequisite]] === Prerequisite -To be able to select **Try {esql}** from the Data views menu the `enableESQL` setting must be enabled from **Stack Management > Advanced Settings**. It is enabled by default. +To be able to select **Language {esql}** from the Data views menu the `enableESQL` setting must be enabled from **Stack Management > Advanced Settings**. It is enabled by default. [float] [[tutorial-try-esql]] -=== Trying {esql} +=== Use {esql} To load the sample data: @@ -21,7 +21,7 @@ To load the 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}*. +. From the Data views menu, select *Language {esql}*. Let's say we want to find out what operating system users have and how much RAM is on their machine. @@ -36,7 +36,7 @@ FROM kibana_sample_data_logs | KEEP machine.os, machine.ram ---- + -. Click **Update**. +. Click **▶Run**. + [role="screenshot"] image:images/esql-machine-os-ram.png[An image of the query result] @@ -57,7 +57,7 @@ FROM kibana_sample_data_logs | LIMIT 10 ---- + -. Click **Update**. +. Click **▶Run**. + [role="screenshot"] image:images/esql-limit.png[An image of the extended query result] @@ -75,7 +75,7 @@ FROM kibana_sample_data_logs | LIMIT 10 ---- + -. Click **Update**. +. Click **▶Run**. + [role="screenshot"] image:images/esql-full-query.png[] @@ -84,6 +84,9 @@ image:images/esql-full-query.png[] 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}]. - +[TIP] +==== +For the complete {esql} documentation, including tutorials, examples and the full syntax reference, refer to the {ref}/esql.html[{es} documentation]. +For a more detailed overview of {esql} in {kib}, refer to {ref}/esql-kibana.html[Use {esql} in Kibana]. +==== diff --git a/package.json b/package.json index dd5fbd1c06325..04316640a2952 100644 --- a/package.json +++ b/package.json @@ -83,9 +83,7 @@ "**/@langchain/core": "0.1.53", "**/@types/node": "20.10.5", "**/@typescript-eslint/utils": "5.62.0", - "**/axios": "1.6.3", "**/chokidar": "^3.5.3", - "**/follow-redirects": "1.15.2", "**/globule/minimatch": "^3.1.2", "**/hoist-non-react-statics": "^3.3.2", "**/isomorphic-fetch/node-fetch": "^2.6.7", @@ -441,6 +439,7 @@ "@kbn/embedded-lens-example-plugin": "link:x-pack/examples/embedded_lens_example", "@kbn/encrypted-saved-objects-plugin": "link:x-pack/plugins/encrypted_saved_objects", "@kbn/enterprise-search-plugin": "link:x-pack/plugins/enterprise_search", + "@kbn/entities-schema": "link:x-pack/packages/kbn-entities-schema", "@kbn/error-boundary-example-plugin": "link:examples/error_boundary", "@kbn/es-errors": "link:packages/kbn-es-errors", "@kbn/es-query": "link:packages/kbn-es-query", @@ -959,7 +958,7 @@ "archiver": "^5.3.1", "async": "^3.2.3", "aws4": "^1.12.0", - "axios": "1.6.3", + "axios": "^1.6.8", "base64-js": "^1.3.1", "bitmap-sdf": "^1.0.3", "blurhash": "^2.0.1", @@ -1525,7 +1524,7 @@ "@types/source-map-support": "^0.5.3", "@types/stats-lite": "^2.2.0", "@types/styled-components": "^5.1.0", - "@types/supertest": "^2.0.12", + "@types/supertest": "^6.0.2", "@types/tapable": "^1.0.6", "@types/tar": "^6.1.11", "@types/testing-library__jest-dom": "^5.14.7", @@ -1580,7 +1579,7 @@ "cssnano": "^5.1.12", "cssnano-preset-default": "^5.2.12", "csstype": "^3.0.2", - "cypress": "13.6.2", + "cypress": "13.6.3", "cypress-axe": "^1.5.0", "cypress-file-upload": "^5.0.8", "cypress-multi-reporters": "^1.6.4", @@ -1699,8 +1698,8 @@ "style-loader": "^1.1.3", "stylelint": "^14.9.1", "stylelint-scss": "^4.3.0", - "superagent": "^8.1.2", - "supertest": "^6.3.3", + "superagent": "^9.0.2", + "supertest": "^7.0.0", "svgo": "^2.8.0", "table": "^6.8.1", "tape": "^5.0.1", diff --git a/packages/cloud/connection_details/components/copy_input/copy_input.tsx b/packages/cloud/connection_details/components/copy_input/copy_input.tsx index 6111208b06148..ac82407fe1588 100644 --- a/packages/cloud/connection_details/components/copy_input/copy_input.tsx +++ b/packages/cloud/connection_details/components/copy_input/copy_input.tsx @@ -12,9 +12,10 @@ import { i18n } from '@kbn/i18n'; export interface CopyInputProps { value: string; + onCopyClick?: React.MouseEventHandler; } -export const CopyInput: React.FC = ({ value }) => { +export const CopyInput: React.FC = ({ value, onCopyClick }) => { const textRef = React.useRef(null); return ( @@ -52,7 +53,10 @@ export const CopyInput: React.FC = ({ value }) => { {(copy) => ( ) => { + onCopyClick?.(event); + copy(); + }} iconType="copyClipboard" size="m" color={'text'} diff --git a/packages/cloud/connection_details/connection_details_flyout_content.stories.tsx b/packages/cloud/connection_details/connection_details_flyout_content.stories.tsx index 6893acfd8b8b3..542a9f343691b 100644 --- a/packages/cloud/connection_details/connection_details_flyout_content.stories.tsx +++ b/packages/cloud/connection_details/connection_details_flyout_content.stories.tsx @@ -8,6 +8,7 @@ import React from 'react'; import { EuiFlyout } from '@elastic/eui'; +import { action } from '@storybook/addon-actions'; import { StoriesProvider, StoriesProviderKeyCreationError, @@ -22,7 +23,7 @@ export default { export const Default = () => { return ( {}}> - + diff --git a/packages/cloud/connection_details/connection_details_flyout_content.tsx b/packages/cloud/connection_details/connection_details_flyout_content.tsx index 9cbe8042caa42..31dce6dc4f848 100644 --- a/packages/cloud/connection_details/connection_details_flyout_content.tsx +++ b/packages/cloud/connection_details/connection_details_flyout_content.tsx @@ -17,11 +17,12 @@ import { } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { ConnectionDetails } from './connection_details'; -import { useConnectionDetailsOpts } from './context'; +import { useConnectionDetailsOpts, useConnectionDetailsService } from './context'; import { Tabs } from './tabs'; export const ConnectionDetailsFlyoutContent: React.FC = () => { const ctx = useConnectionDetailsOpts(); + const service = useConnectionDetailsService(); const header = ( @@ -39,7 +40,15 @@ export const ConnectionDetailsFlyoutContent: React.FC = () => { defaultMessage: 'Connect to the Elasticsearch API by using the following details.', })}{' '} {!!ctx.links?.learnMore && ( - + // Below onClick is used only for telemetry, but `href` is the real + // semantic action. + // eslint-disable-next-line @elastic/eui/href-or-on-click + service.emitTelemetryEvent(['learn_more_clicked'])} + > {i18n.translate('cloud.connectionDetails.learnMoreButtonLabel', { defaultMessage: 'Learn more', })} diff --git a/packages/cloud/connection_details/kibana/global.ts b/packages/cloud/connection_details/kibana/global.ts index af3767d12ad77..0a2ede8e5157d 100644 --- a/packages/cloud/connection_details/kibana/global.ts +++ b/packages/cloud/connection_details/kibana/global.ts @@ -19,6 +19,7 @@ export interface ConnectionDetailsGlobalDependencies { http: CoreStart['http']; application: CoreStart['application']; overlays: CoreStart['overlays']; + analytics?: CoreStart['analytics']; }; plugins: { cloud?: CloudStart; diff --git a/packages/cloud/connection_details/kibana/kibana_connection_details_provider.tsx b/packages/cloud/connection_details/kibana/kibana_connection_details_provider.tsx index 38bc354e9c912..a8cc79dfcd9d2 100644 --- a/packages/cloud/connection_details/kibana/kibana_connection_details_provider.tsx +++ b/packages/cloud/connection_details/kibana/kibana_connection_details_provider.tsx @@ -17,7 +17,7 @@ import { useAsyncMemo } from '../hooks/use_async_memo'; const createOpts = async (props: KibanaConnectionDetailsProviderProps) => { const { options, start } = props; - const { http, docLinks } = start.core; + const { http, docLinks, analytics } = start.core; const locator = start.plugins?.share?.url?.locators.get('MANAGEMENT_APP_LOCATOR'); const manageKeysLink = await locator?.getUrl({ sectionId: 'security', appId: 'api_keys' }); const result: ConnectionDetailsOpts = { @@ -68,6 +68,51 @@ const createOpts = async (props: KibanaConnectionDetailsProviderProps) => { hasPermission: async () => true, ...options?.apiKeys, }, + onTelemetryEvent: (event) => { + if (!analytics) return; + switch (event[0]) { + case 'learn_more_clicked': { + analytics.reportEvent('connection_details_learn_more_clicked', {}); + break; + } + case 'tab_switched': { + analytics.reportEvent('connection_details_tab_switched', { tab: event[1]!.tab }); + break; + } + case 'copy_endpoint_url_clicked': { + analytics.reportEvent('connection_details_copy_endpoint_url_clicked', {}); + break; + } + case 'show_cloud_id_toggled': { + analytics.reportEvent('connection_details_show_cloud_id_toggled', {}); + break; + } + case 'copy_cloud_id_clicked': { + analytics.reportEvent('connection_details_copy_cloud_id_clicked', {}); + break; + } + case 'new_api_key_created': { + analytics.reportEvent('connection_details_new_api_key_created', {}); + break; + } + case 'manage_api_keys_clicked': { + analytics.reportEvent('connection_details_manage_api_keys_clicked', {}); + break; + } + case 'key_encoding_changed': { + analytics.reportEvent('connection_details_key_encoding_changed', { + format: event[1]!.format, + }); + break; + } + case 'copy_api_key_clicked': { + analytics.reportEvent('connection_details_copy_api_key_clicked', { + format: event[1]!.format, + }); + break; + } + } + }, }; return result; @@ -83,6 +128,7 @@ export interface KibanaConnectionDetailsProviderProps { theme: CoreStart['theme']; http?: CoreStart['http']; application?: CoreStart['application']; + analytics?: CoreStart['analytics']; }; plugins?: { cloud?: CloudStart; diff --git a/packages/cloud/connection_details/service.ts b/packages/cloud/connection_details/service.ts index 1e59206337baa..f07a3edeae201 100644 --- a/packages/cloud/connection_details/service.ts +++ b/packages/cloud/connection_details/service.ts @@ -10,7 +10,7 @@ import { BehaviorSubject } from 'rxjs'; import { i18n } from '@kbn/i18n'; import { ApiKey } from './tabs/api_keys_tab/views/success_form/types'; import type { Format } from './tabs/api_keys_tab/views/success_form/format_select'; -import type { ConnectionDetailsOpts, TabID } from './types'; +import type { ConnectionDetailsOpts, TabID, ConnectionDetailsTelemetryEvents } from './types'; export class ConnectionDetailsService { public readonly tabId$ = new BehaviorSubject('endpoints'); @@ -39,6 +39,7 @@ export class ConnectionDetailsService { }; public readonly toggleShowCloudId = () => { + this.emitTelemetryEvent(['show_cloud_id_toggled']); this.showCloudId$.next(!this.showCloudId$.getValue()); }; @@ -48,6 +49,7 @@ export class ConnectionDetailsService { }; public readonly setApiKeyFormat = (format: Format) => { + this.emitTelemetryEvent(['key_encoding_changed', { format }]); this.apiKeyFormat$.next(format); }; @@ -76,6 +78,7 @@ export class ConnectionDetailsService { name: this.apiKeyName$.getValue(), }); this.apiKey$.next(apiKey); + this.emitTelemetryEvent(['new_api_key_created']); } catch (error) { this.apiKeyError$.next(error); } finally { @@ -88,4 +91,13 @@ export class ConnectionDetailsService { this.apiKeyError$.next(error); }); }; + + public readonly emitTelemetryEvent = (event: ConnectionDetailsTelemetryEvents) => { + try { + this.opts.onTelemetryEvent?.(event); + } catch (error) { + // eslint-disable-next-line no-console + console.error('Error emitting telemetry event', error); + } + }; } diff --git a/packages/cloud/connection_details/stories.tsx b/packages/cloud/connection_details/stories.tsx index f6d15f181835c..41fb267f797e4 100644 --- a/packages/cloud/connection_details/stories.tsx +++ b/packages/cloud/connection_details/stories.tsx @@ -41,8 +41,15 @@ const defaultOpts: ConnectionDetailsOpts = { }, }; -export const StoriesProvider: React.FC = ({ children }) => { - return {children}; +export const StoriesProvider: React.FC> = ({ + children, + ...rest +}) => { + return ( + + {children} + + ); }; export const StoriesProviderKeyCreationError: React.FC = ({ children }) => { diff --git a/packages/cloud/connection_details/tabs/api_keys_tab/components/manage_keys_link.tsx b/packages/cloud/connection_details/tabs/api_keys_tab/components/manage_keys_link.tsx index a6ead0f520bb4..44ec35154874b 100644 --- a/packages/cloud/connection_details/tabs/api_keys_tab/components/manage_keys_link.tsx +++ b/packages/cloud/connection_details/tabs/api_keys_tab/components/manage_keys_link.tsx @@ -21,7 +21,10 @@ export const ManageKeysLink: React.FC = () => { return ( { + service.emitTelemetryEvent(['manage_api_keys_clicked']); + service.opts?.navigateToUrl?.(link); + }} data-test-subj={'connectionDetailsManageApiKeysLink'} > {i18n.translate('cloud.connectionDetails.apiKeys.managerLinkLabel', { diff --git a/packages/cloud/connection_details/tabs/api_keys_tab/views/missing_permissions_panel.tsx b/packages/cloud/connection_details/tabs/api_keys_tab/views/missing_permissions_panel.tsx index 5e2d5dd2da830..fcc58d14443c7 100644 --- a/packages/cloud/connection_details/tabs/api_keys_tab/views/missing_permissions_panel.tsx +++ b/packages/cloud/connection_details/tabs/api_keys_tab/views/missing_permissions_panel.tsx @@ -7,25 +7,32 @@ */ import * as React from 'react'; -import { EuiCallOut } from '@elastic/eui'; +import { EuiCallOut, EuiSpacer } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; +import { ManageKeysLink } from '../components/manage_keys_link'; export const MissingPermissionsPanel: React.FC = () => { return ( - -

- {i18n.translate('cloud.connectionDetails.tabs.apiKeys.missingPermPanel.description', { - defaultMessage: - 'Your assigned role does not have the necessary permissions to create an API key. ' + - 'Please contact your administrator.', + <> + - + > +

+ {i18n.translate('cloud.connectionDetails.tabs.apiKeys.missingPermPanel.description', { + defaultMessage: + 'Your assigned role does not have the necessary permissions to create an API key. ' + + 'Please contact your administrator.', + })} +

+
+ + + + + ); }; diff --git a/packages/cloud/connection_details/tabs/api_keys_tab/views/success_form/success_form.tsx b/packages/cloud/connection_details/tabs/api_keys_tab/views/success_form/success_form.tsx index 154c3c8d2b4bb..f08ab3aec8844 100644 --- a/packages/cloud/connection_details/tabs/api_keys_tab/views/success_form/success_form.tsx +++ b/packages/cloud/connection_details/tabs/api_keys_tab/views/success_form/success_form.tsx @@ -23,6 +23,7 @@ export const SuccessForm: React.FC = () => { apiKey={apiKey} format={format} onFormatChange={service.setApiKeyFormat} + onCopyClick={() => service.emitTelemetryEvent(['copy_api_key_clicked', { format }])} /> ); }; diff --git a/packages/cloud/connection_details/tabs/api_keys_tab/views/success_form/success_form_controlled.tsx b/packages/cloud/connection_details/tabs/api_keys_tab/views/success_form/success_form_controlled.tsx index d5717bee8e244..e4dca6c5fe4f4 100644 --- a/packages/cloud/connection_details/tabs/api_keys_tab/views/success_form/success_form_controlled.tsx +++ b/packages/cloud/connection_details/tabs/api_keys_tab/views/success_form/success_form_controlled.tsx @@ -18,12 +18,14 @@ export interface SuccessFormControlledProps { apiKey: ApiKey; format: Format; onFormatChange: (format: Format) => void; + onCopyClick?: () => void; } export const SuccessFormControlled: React.FC = ({ apiKey, format, onFormatChange, + onCopyClick, }) => { const keyValue = format === 'encoded' ? apiKey.encoded : `${apiKey.id}:${apiKey.key}`; @@ -62,7 +64,7 @@ export const SuccessFormControlled: React.FC = ({ fullWidth data-test-subj={'connectionDetailsApiKeyValueRow'} > - + diff --git a/packages/cloud/connection_details/tabs/endpoints_tab/endpoints_tab.tsx b/packages/cloud/connection_details/tabs/endpoints_tab/endpoints_tab.tsx index 40f442348acf7..ffdea170096ac 100644 --- a/packages/cloud/connection_details/tabs/endpoints_tab/endpoints_tab.tsx +++ b/packages/cloud/connection_details/tabs/endpoints_tab/endpoints_tab.tsx @@ -8,19 +8,35 @@ import { EuiForm } from '@elastic/eui'; import * as React from 'react'; -import { useConnectionDetailsOpts } from '../../context'; +import { useConnectionDetailsOpts, useConnectionDetailsService } from '../../context'; +import { useBehaviorSubject } from '../../hooks/use_behavior_subject'; import { CloudIdRow } from './rows/cloud_id_row'; import { EndpointUrlRow } from './rows/endpoints_url_row'; export const EndpointsTab: React.FC = () => { const { endpoints } = useConnectionDetailsOpts(); + const service = useConnectionDetailsService(); + const showCloudId = useBehaviorSubject(service.showCloudId$); if (!endpoints) return null; return ( - {!!endpoints?.url && } - {!!endpoints?.id && } + {!!endpoints?.url && ( + service.emitTelemetryEvent(['copy_endpoint_url_clicked'])} + /> + )} + {!!endpoints?.id && ( + service.emitTelemetryEvent(['copy_cloud_id_clicked'])} + /> + )} ); }; diff --git a/packages/cloud/connection_details/tabs/endpoints_tab/rows/cloud_id_row/cloud_id_row.tsx b/packages/cloud/connection_details/tabs/endpoints_tab/rows/cloud_id_row/cloud_id_row.tsx index ddaddb8d6ce5d..53d31baaef8f1 100644 --- a/packages/cloud/connection_details/tabs/endpoints_tab/rows/cloud_id_row/cloud_id_row.tsx +++ b/packages/cloud/connection_details/tabs/endpoints_tab/rows/cloud_id_row/cloud_id_row.tsx @@ -10,18 +10,23 @@ import * as React from 'react'; import { EuiFormRow, EuiSpacer, EuiSwitch } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { CopyInput } from '../../../../components/copy_input'; -import { useConnectionDetailsService } from '../../../../context'; -import { useBehaviorSubject } from '../../../../hooks/use_behavior_subject'; import { Label } from './label'; export interface CloudIdRowProps { value: string; + showCloudId: boolean; + learnMoreUrl?: string; + onShowCloudIdToggle: () => void; + onCopyClick?: () => void; } -export const CloudIdRow: React.FC = ({ value }) => { - const service = useConnectionDetailsService(); - const showCloudId = useBehaviorSubject(service.showCloudId$); - +export const CloudIdRow: React.FC = ({ + value, + showCloudId, + learnMoreUrl, + onShowCloudIdToggle, + onCopyClick, +}) => { return ( <> @@ -31,7 +36,7 @@ export const CloudIdRow: React.FC = ({ value }) => { defaultMessage: 'Show Cloud ID', })} checked={showCloudId} - onChange={service.toggleShowCloudId} + onChange={() => onShowCloudIdToggle()} data-test-subj="connectionDetailsCloudIdSwitch" /> @@ -39,7 +44,7 @@ export const CloudIdRow: React.FC = ({ value }) => { {showCloudId && ( } + label={ )} diff --git a/packages/cloud/connection_details/tabs/endpoints_tab/rows/endpoints_url_row.tsx b/packages/cloud/connection_details/tabs/endpoints_tab/rows/endpoints_url_row.tsx index 29f40dcb0c5e2..7eb9683b11ed6 100644 --- a/packages/cloud/connection_details/tabs/endpoints_tab/rows/endpoints_url_row.tsx +++ b/packages/cloud/connection_details/tabs/endpoints_tab/rows/endpoints_url_row.tsx @@ -13,9 +13,10 @@ import { CopyInput } from '../../../components/copy_input'; export interface EndpointUrlProps { url: string; + onCopyClick?: () => void; } -export const EndpointUrlRow: React.FC = ({ url }) => { +export const EndpointUrlRow: React.FC = ({ url, onCopyClick }) => { return ( = ({ url }) => { fullWidth data-test-subj="connectionDetailsEsUrl" > - + onCopyClick?.()} /> ); }; diff --git a/packages/cloud/connection_details/types.ts b/packages/cloud/connection_details/types.ts index 81b51a444ed78..593f2b57ee3ac 100644 --- a/packages/cloud/connection_details/types.ts +++ b/packages/cloud/connection_details/types.ts @@ -13,6 +13,7 @@ export interface ConnectionDetailsOpts { endpoints?: ConnectionDetailsOptsEndpoints; apiKeys?: ConnectionDetailsOptsApiKeys; navigateToUrl?: (url: string) => void; + onTelemetryEvent?: (event: ConnectionDetailsTelemetryEvents) => void; } export interface ConnectionDetailsOptsLinks { @@ -33,4 +34,20 @@ export interface ConnectionDetailsOptsApiKeys { hasPermission: () => Promise; } +export type ConnectionDetailsTelemetryEvent = [ + id: EventId, + payload?: EventPayload +]; + +export type ConnectionDetailsTelemetryEvents = + | ConnectionDetailsTelemetryEvent<'learn_more_clicked'> + | ConnectionDetailsTelemetryEvent<'tab_switched', { tab: string }> + | ConnectionDetailsTelemetryEvent<'copy_endpoint_url_clicked'> + | ConnectionDetailsTelemetryEvent<'show_cloud_id_toggled'> + | ConnectionDetailsTelemetryEvent<'copy_cloud_id_clicked'> + | ConnectionDetailsTelemetryEvent<'new_api_key_created'> + | ConnectionDetailsTelemetryEvent<'manage_api_keys_clicked'> + | ConnectionDetailsTelemetryEvent<'key_encoding_changed', { format: string }> + | ConnectionDetailsTelemetryEvent<'copy_api_key_clicked', { format: string }>; + export type TabID = 'endpoints' | 'apiKeys'; diff --git a/packages/core/http/core-http-server-internal/src/http_server.test.ts b/packages/core/http/core-http-server-internal/src/http_server.test.ts index 129efea82cc8c..235fab185e12d 100644 --- a/packages/core/http/core-http-server-internal/src/http_server.test.ts +++ b/packages/core/http/core-http-server-internal/src/http_server.test.ts @@ -1622,7 +1622,7 @@ describe('setup contract', () => { .get('/static/some_json.json') .expect(200); - const etag = response.get('etag'); + const etag = response.get('etag')!; expect(etag).not.toBeUndefined(); await supertest(innerServer.listener) diff --git a/packages/core/saved-objects/core-saved-objects-base-server-internal/src/constants.ts b/packages/core/saved-objects/core-saved-objects-base-server-internal/src/constants.ts index a04e762eaf67d..4244a5fed91aa 100644 --- a/packages/core/saved-objects/core-saved-objects-base-server-internal/src/constants.ts +++ b/packages/core/saved-objects/core-saved-objects-base-server-internal/src/constants.ts @@ -157,6 +157,7 @@ export const HASH_TO_VERSION_MAP = { 'core-usage-stats|3d1b76c39bfb2cc8296b024d73854724': '7.14.1', 'csp-rule-template|6ee70dc06c0ca3ddffc18222f202ab25': '10.0.0', 'dashboard|b8aa800aa5e0d975c5e8dc57f03d41f8': '10.2.0', + 'endpoint:unified-user-artifact-manifest|393c6e4f5f16288c24ef9057e4d76a4c': '10.0.0', 'endpoint:user-artifact-manifest|7502b5c5bc923abe8aa5ccfd636e8c3d': '10.0.0', 'enterprise_search_telemetry|3d1b76c39bfb2cc8296b024d73854724': '10.0.0', 'epm-packages-assets|44621b2f6052ef966da47b7c3a00f33b': '10.0.0', diff --git a/packages/kbn-apm-synthtrace-client/src/lib/infra/docker_container.ts b/packages/kbn-apm-synthtrace-client/src/lib/infra/docker_container.ts new file mode 100644 index 0000000000000..03f72ee61bc06 --- /dev/null +++ b/packages/kbn-apm-synthtrace-client/src/lib/infra/docker_container.ts @@ -0,0 +1,39 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +/* eslint-disable max-classes-per-file */ +import { Entity, Fields } from '../entity'; +import { Serializable } from '../serializable'; + +interface DockerContainerDocument extends Fields { + 'container.id': string; + 'metricset.name'?: string; +} + +export class DockerContainer extends Entity { + metrics() { + return new DockerContainerMetrics({ + ...this.fields, + 'docker.cpu.total.pct': 25, + 'docker.memory.usage.pct': 20, + }); + } +} + +export interface DockerContainerMetricsDocument extends DockerContainerDocument { + 'docker.cpu.total.pct': number; + 'docker.memory.usage.pct': number; +} + +class DockerContainerMetrics extends Serializable {} + +export function dockerContainer(id: string): DockerContainer { + return new DockerContainer({ + 'container.id': id, + }); +} diff --git a/packages/kbn-apm-synthtrace-client/src/lib/infra/index.ts b/packages/kbn-apm-synthtrace-client/src/lib/infra/index.ts index 961225670e27b..fb81b595c7e2f 100644 --- a/packages/kbn-apm-synthtrace-client/src/lib/infra/index.ts +++ b/packages/kbn-apm-synthtrace-client/src/lib/infra/index.ts @@ -6,14 +6,20 @@ * Side Public License, v 1. */ -import { container, ContainerMetricsDocument } from './container'; +import { dockerContainer, DockerContainerMetricsDocument } from './docker_container'; import { host, HostMetricsDocument } from './host'; +import { k8sContainer, K8sContainerMetricsDocument } from './k8s_container'; import { pod, PodMetricsDocument } from './pod'; -export type InfraDocument = HostMetricsDocument | PodMetricsDocument | ContainerMetricsDocument; +export type InfraDocument = + | HostMetricsDocument + | PodMetricsDocument + | DockerContainerMetricsDocument + | K8sContainerMetricsDocument; export const infra = { host, pod, - container, + dockerContainer, + k8sContainer, }; diff --git a/packages/kbn-apm-synthtrace-client/src/lib/infra/container.ts b/packages/kbn-apm-synthtrace-client/src/lib/infra/k8s_container.ts similarity index 62% rename from packages/kbn-apm-synthtrace-client/src/lib/infra/container.ts rename to packages/kbn-apm-synthtrace-client/src/lib/infra/k8s_container.ts index d9bef38c2fdb5..00d4f0a998960 100644 --- a/packages/kbn-apm-synthtrace-client/src/lib/infra/container.ts +++ b/packages/kbn-apm-synthtrace-client/src/lib/infra/k8s_container.ts @@ -10,30 +10,32 @@ import { Entity, Fields } from '../entity'; import { Serializable } from '../serializable'; -interface ContainerDocument extends Fields { +interface K8sContainerDocument extends Fields { 'container.id': string; 'kubernetes.pod.uid': string; 'kubernetes.node.name': string; 'metricset.name'?: string; } -export class Container extends Entity { +export class K8sContainer extends Entity { metrics() { - return new ContainerMetrics({ + return new K8sContainerMetrics({ ...this.fields, 'kubernetes.container.cpu.usage.limit.pct': 46, + 'kubernetes.container.memory.usage.limit.pct': 30, }); } } -export interface ContainerMetricsDocument extends ContainerDocument { +export interface K8sContainerMetricsDocument extends K8sContainerDocument { 'kubernetes.container.cpu.usage.limit.pct': number; + 'kubernetes.container.memory.usage.limit.pct': number; } -class ContainerMetrics extends Serializable {} +class K8sContainerMetrics extends Serializable {} -export function container(id: string, uid: string, nodeName: string) { - return new Container({ +export function k8sContainer(id: string, uid: string, nodeName: string): K8sContainer { + return new K8sContainer({ 'container.id': id, 'kubernetes.pod.uid': uid, 'kubernetes.node.name': nodeName, diff --git a/packages/kbn-apm-synthtrace-client/src/lib/infra/pod.ts b/packages/kbn-apm-synthtrace-client/src/lib/infra/pod.ts index 9f5c999184176..35ebe94ba6ee1 100644 --- a/packages/kbn-apm-synthtrace-client/src/lib/infra/pod.ts +++ b/packages/kbn-apm-synthtrace-client/src/lib/infra/pod.ts @@ -9,7 +9,7 @@ /* eslint-disable max-classes-per-file */ import { Entity, Fields } from '../entity'; import { Serializable } from '../serializable'; -import { container } from './container'; +import { k8sContainer } from './k8s_container'; interface PodDocument extends Fields { 'kubernetes.pod.uid': string; @@ -26,7 +26,7 @@ export class Pod extends Entity { } container(id: string) { - return container(id, this.fields['kubernetes.pod.uid'], this.fields['kubernetes.node.name']); + return k8sContainer(id, this.fields['kubernetes.pod.uid'], this.fields['kubernetes.node.name']); } } diff --git a/packages/kbn-apm-synthtrace/src/scenarios/infra_docker_containers.ts b/packages/kbn-apm-synthtrace/src/scenarios/infra_docker_containers.ts new file mode 100644 index 0000000000000..c020d2de83db9 --- /dev/null +++ b/packages/kbn-apm-synthtrace/src/scenarios/infra_docker_containers.ts @@ -0,0 +1,41 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { InfraDocument, infra } from '@kbn/apm-synthtrace-client'; + +import { Scenario } from '../cli/scenario'; +import { withClient } from '../lib/utils/with_client'; + +const scenario: Scenario = async (runOptions) => { + return { + generate: ({ range, clients: { infraEsClient } }) => { + const { numContainers = 5 } = runOptions.scenarioOpts || {}; + const { logger } = runOptions; + + const CONTAINERS = Array(numContainers) + .fill(0) + .map((_, idx) => infra.dockerContainer(`container-${idx}`)); + + const containers = range + .interval('30s') + .rate(1) + .generator((timestamp) => + CONTAINERS.flatMap((container) => [container.metrics().timestamp(timestamp)]) + ); + + return [ + withClient( + infraEsClient, + logger.perf('generating_infra_docker_containers', () => containers) + ), + ]; + }, + }; +}; + +export default scenario; diff --git a/packages/kbn-apm-synthtrace/src/scenarios/infra_k8s_containers.ts b/packages/kbn-apm-synthtrace/src/scenarios/infra_k8s_containers.ts new file mode 100644 index 0000000000000..39d2b36b1a03f --- /dev/null +++ b/packages/kbn-apm-synthtrace/src/scenarios/infra_k8s_containers.ts @@ -0,0 +1,41 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { InfraDocument, infra } from '@kbn/apm-synthtrace-client'; + +import { Scenario } from '../cli/scenario'; +import { withClient } from '../lib/utils/with_client'; + +const scenario: Scenario = async (runOptions) => { + return { + generate: ({ range, clients: { infraEsClient } }) => { + const { numContainers = 5 } = runOptions.scenarioOpts || {}; + const { logger } = runOptions; + + const CONTAINERS = Array(numContainers) + .fill(0) + .map((_, idx) => infra.k8sContainer(`container-${idx}`, `pod-${idx}`, `node-${idx}`)); + + const containers = range + .interval('30s') + .rate(1) + .generator((timestamp) => + CONTAINERS.flatMap((container) => [container.metrics().timestamp(timestamp)]) + ); + + return [ + withClient( + infraEsClient, + logger.perf('generating_infra_containers', () => containers) + ), + ]; + }, + }; +}; + +export default scenario; diff --git a/packages/kbn-check-mappings-update-cli/current_fields.json b/packages/kbn-check-mappings-update-cli/current_fields.json index 65fd6af2ce919..04343968ef958 100644 --- a/packages/kbn-check-mappings-update-cli/current_fields.json +++ b/packages/kbn-check-mappings-update-cli/current_fields.json @@ -280,6 +280,11 @@ "title", "version" ], + "endpoint:unified-user-artifact-manifest": [ + "artifactIds", + "policyId", + "semanticVersion" + ], "endpoint:user-artifact-manifest": [ "artifacts", "schemaVersion" diff --git a/packages/kbn-check-mappings-update-cli/current_mappings.json b/packages/kbn-check-mappings-update-cli/current_mappings.json index 03a189b1549be..6ee1f6d13521f 100644 --- a/packages/kbn-check-mappings-update-cli/current_mappings.json +++ b/packages/kbn-check-mappings-update-cli/current_mappings.json @@ -964,6 +964,20 @@ } } }, + "endpoint:unified-user-artifact-manifest": { + "dynamic": false, + "properties": { + "artifactIds": { + "type": "keyword" + }, + "policyId": { + "type": "keyword" + }, + "semanticVersion": { + "type": "keyword" + } + } + }, "endpoint:user-artifact-manifest": { "dynamic": false, "properties": { diff --git a/packages/kbn-cli-dev-mode/src/integration_tests/base_path_proxy_server.test.ts b/packages/kbn-cli-dev-mode/src/integration_tests/base_path_proxy_server.test.ts index 5e8a7a50a7b32..0f0a69638cfa2 100644 --- a/packages/kbn-cli-dev-mode/src/integration_tests/base_path_proxy_server.test.ts +++ b/packages/kbn-cli-dev-mode/src/integration_tests/base_path_proxy_server.test.ts @@ -28,7 +28,7 @@ describe('BasePathProxyServer', () => { let logger: TestLog; let config: IHttpConfig; let basePath: string; - let proxySupertest: supertest.SuperTest; + let proxySupertest: supertest.Agent; beforeEach(async () => { logger = new TestLog(); @@ -330,7 +330,7 @@ describe('BasePathProxyServer', () => { describe('shouldRedirect', () => { let proxyServerWithoutShouldRedirect: BasePathProxyServer; - let proxyWithoutShouldRedirectSupertest: supertest.SuperTest; + let proxyWithoutShouldRedirectSupertest: supertest.Agent; beforeEach(async () => { // setup and start a proxy server which does not use "shouldRedirectFromOldBasePath" @@ -373,7 +373,7 @@ describe('BasePathProxyServer', () => { describe('constructor option for sending in a custom basePath', () => { let proxyServerWithFooBasePath: BasePathProxyServer; - let proxyWithFooBasePath: supertest.SuperTest; + let proxyWithFooBasePath: supertest.Agent; beforeEach(async () => { // setup and start a proxy server which uses a basePath of "foo" diff --git a/packages/kbn-discover-utils/src/data_types/index.ts b/packages/kbn-discover-utils/src/data_types/index.ts new file mode 100644 index 0000000000000..1bb391b454f28 --- /dev/null +++ b/packages/kbn-discover-utils/src/data_types/index.ts @@ -0,0 +1,9 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export * from './logs'; diff --git a/packages/kbn-discover-utils/src/data_types/logs/index.ts b/packages/kbn-discover-utils/src/data_types/logs/index.ts new file mode 100644 index 0000000000000..21d54fd754a3e --- /dev/null +++ b/packages/kbn-discover-utils/src/data_types/logs/index.ts @@ -0,0 +1,10 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export * from './types'; +export * from './utils'; diff --git a/x-pack/plugins/observability_solution/logs_explorer/common/document.ts b/packages/kbn-discover-utils/src/data_types/logs/types.ts similarity index 89% rename from x-pack/plugins/observability_solution/logs_explorer/common/document.ts rename to packages/kbn-discover-utils/src/data_types/logs/types.ts index 778d8546c2d1c..27a4313fe2548 100644 --- a/x-pack/plugins/observability_solution/logs_explorer/common/document.ts +++ b/packages/kbn-discover-utils/src/data_types/logs/types.ts @@ -1,11 +1,12 @@ /* * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. */ -import type { DataTableRecord } from '@kbn/discover-utils/src/types'; +import { DataTableRecord } from '../../types'; export interface LogDocument extends DataTableRecord { flattened: { @@ -40,7 +41,7 @@ export interface LogDocument extends DataTableRecord { }; } -export interface FlyoutDoc { +export interface LogFlyoutDoc { '@timestamp': string; 'log.level'?: string; message?: string; diff --git a/x-pack/plugins/observability_solution/logs_explorer/public/utils/get_field_from_flattened_doc.ts b/packages/kbn-discover-utils/src/data_types/logs/utils/get_field_from_doc.ts similarity index 65% rename from x-pack/plugins/observability_solution/logs_explorer/public/utils/get_field_from_flattened_doc.ts rename to packages/kbn-discover-utils/src/data_types/logs/utils/get_field_from_doc.ts index 7d05d9ab61583..f399976dcb85a 100644 --- a/x-pack/plugins/observability_solution/logs_explorer/public/utils/get_field_from_flattened_doc.ts +++ b/packages/kbn-discover-utils/src/data_types/logs/utils/get_field_from_doc.ts @@ -1,11 +1,12 @@ /* * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. */ -import { LogDocument } from '../../common/document'; +import { LogDocument } from '../types'; type Field = keyof LogDocument['flattened']; diff --git a/packages/kbn-discover-utils/src/data_types/logs/utils/index.ts b/packages/kbn-discover-utils/src/data_types/logs/utils/index.ts new file mode 100644 index 0000000000000..1c26d5efff12d --- /dev/null +++ b/packages/kbn-discover-utils/src/data_types/logs/utils/index.ts @@ -0,0 +1,9 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export * from './get_field_from_doc'; diff --git a/packages/kbn-discover-utils/src/index.ts b/packages/kbn-discover-utils/src/index.ts index b1dc190111746..0e811d862b6ff 100644 --- a/packages/kbn-discover-utils/src/index.ts +++ b/packages/kbn-discover-utils/src/index.ts @@ -10,3 +10,4 @@ export * from './constants'; export * as fieldConstants from './field_constants'; export * from './hooks'; export * from './utils'; +export * from './data_types'; diff --git a/packages/kbn-doc-links/src/get_doc_links.ts b/packages/kbn-doc-links/src/get_doc_links.ts index 136e5f7bc95b1..68bd793b3d5c9 100644 --- a/packages/kbn-doc-links/src/get_doc_links.ts +++ b/packages/kbn-doc-links/src/get_doc_links.ts @@ -479,6 +479,7 @@ export const getDocLinks = ({ kibanaBranch, buildFlavor }: GetDocLinkOptions): D }, privileges: `${SECURITY_SOLUTION_DOCS}endpoint-management-req.html`, manageDetectionRules: `${SECURITY_SOLUTION_DOCS}rules-ui-management.html`, + createDetectionRules: `${SECURITY_SOLUTION_DOCS}rules-ui-create.html`, createEsqlRuleType: `${SECURITY_SOLUTION_DOCS}rules-ui-create.html#create-esql-rule`, ruleUiAdvancedParams: `${SECURITY_SOLUTION_DOCS}rules-ui-create.html#rule-ui-advanced-params`, entityAnalytics: { diff --git a/packages/kbn-doc-links/src/types.ts b/packages/kbn-doc-links/src/types.ts index 29e09d8b25672..fb59c867cff9d 100644 --- a/packages/kbn-doc-links/src/types.ts +++ b/packages/kbn-doc-links/src/types.ts @@ -354,6 +354,7 @@ export interface DocLinks { }; readonly privileges: string; readonly manageDetectionRules: string; + readonly createDetectionRules: string; readonly createEsqlRuleType: string; readonly ruleUiAdvancedParams: string; readonly entityAnalytics: { diff --git a/packages/kbn-es/src/cluster.ts b/packages/kbn-es/src/cluster.ts index e2ddf43f32dc7..65e232a9bbd48 100644 --- a/packages/kbn-es/src/cluster.ts +++ b/packages/kbn-es/src/cluster.ts @@ -89,8 +89,9 @@ export class Cluster { async installSource(options: InstallSourceOptions) { this.log.info(chalk.bold('Installing from source')); return await this.log.indent(4, async () => { - const { installPath } = await installSource({ log: this.log, ...options }); - return { installPath }; + const { installPath, disableEsTmpDir } = await installSource({ log: this.log, ...options }); + + return { installPath, disableEsTmpDir }; }); } @@ -115,12 +116,12 @@ export class Cluster { async installSnapshot(options: InstallSnapshotOptions) { this.log.info(chalk.bold('Installing from snapshot')); return await this.log.indent(4, async () => { - const { installPath } = await installSnapshot({ + const { installPath, disableEsTmpDir } = await installSnapshot({ log: this.log, ...options, }); - return { installPath }; + return { installPath, disableEsTmpDir }; }); } @@ -130,12 +131,12 @@ export class Cluster { async installArchive(archivePath: string, options?: InstallArchiveOptions) { this.log.info(chalk.bold('Installing from an archive')); return await this.log.indent(4, async () => { - const { installPath } = await installArchive(archivePath, { + const { installPath, disableEsTmpDir } = await installArchive(archivePath, { log: this.log, ...(options || {}), }); - return { installPath }; + return { installPath, disableEsTmpDir }; }); } @@ -317,6 +318,7 @@ export class Cluster { skipReadyCheck, readyTimeout, writeLogsToPath, + disableEsTmpDir, ...options } = opts; @@ -389,7 +391,9 @@ export class Cluster { this.process = execa(ES_BIN, args, { cwd: installPath, env: { - ...(installPath ? { ES_TMPDIR: path.resolve(installPath, 'ES_TMPDIR') } : {}), + ...(installPath && !disableEsTmpDir + ? { ES_TMPDIR: path.resolve(installPath, 'ES_TMPDIR') } + : {}), ...process.env, JAVA_HOME: '', // By default, we want to always unset JAVA_HOME so that the bundled JDK will be used ES_JAVA_OPTS: esJavaOpts, diff --git a/packages/kbn-es/src/cluster_exec_options.ts b/packages/kbn-es/src/cluster_exec_options.ts index 30aeabbab903a..362af62c57954 100644 --- a/packages/kbn-es/src/cluster_exec_options.ts +++ b/packages/kbn-es/src/cluster_exec_options.ts @@ -17,4 +17,6 @@ export interface EsClusterExecOptions { readyTimeout?: number; onEarlyExit?: (msg: string) => void; writeLogsToPath?: string; + /** Disable creating a temp directory, allowing ES to write to OS's /tmp directory */ + disableEsTmpDir?: boolean; } diff --git a/packages/kbn-es/src/install/install_archive.ts b/packages/kbn-es/src/install/install_archive.ts index 78e200d4d47fb..2bfef3ab7abef 100644 --- a/packages/kbn-es/src/install/install_archive.ts +++ b/packages/kbn-es/src/install/install_archive.ts @@ -40,6 +40,7 @@ export async function installArchive(archive: string, options?: InstallArchiveOp installPath = path.resolve(basePath, path.basename(archive, '.tar.gz')), log = defaultLog, esArgs = [], + disableEsTmpDir = process.env.FTR_DISABLE_ES_TMPDIR?.toLowerCase() === 'true', } = options || {}; let dest = archive; @@ -62,9 +63,16 @@ export async function installArchive(archive: string, options?: InstallArchiveOp }); log.info('extracted to %s', chalk.bold(installPath)); - const tmpdir = path.resolve(installPath, 'ES_TMPDIR'); - fs.mkdirSync(tmpdir, { recursive: true }); - log.info('created %s', chalk.bold(tmpdir)); + /** + * If we're running inside a Vagrant VM, and this is running in a synced folder, + * ES will fail to start due to ML being unable to write a pipe in the synced folder. + * Disabling allows ES to write to the OS's /tmp directory. + */ + if (!disableEsTmpDir) { + const tmpdir = path.resolve(installPath, 'ES_TMPDIR'); + fs.mkdirSync(tmpdir, { recursive: true }); + log.info('created %s', chalk.bold(tmpdir)); + } // starting in 6.3, security is disabled by default. Since we bootstrap // the keystore, we can enable security ourselves. @@ -76,7 +84,7 @@ export async function installArchive(archive: string, options?: InstallArchiveOp ...parseSettings(esArgs, { filter: SettingsFilter.SecureOnly }), ]); - return { installPath }; + return { installPath, disableEsTmpDir }; } /** diff --git a/packages/kbn-es/src/install/types.ts b/packages/kbn-es/src/install/types.ts index e4b750c0ec472..6217f5b93c7f6 100644 --- a/packages/kbn-es/src/install/types.ts +++ b/packages/kbn-es/src/install/types.ts @@ -40,4 +40,6 @@ export interface InstallArchiveOptions { installPath?: string; log?: ToolingLog; esArgs?: string[]; + /** Disable creating a temp directory, allowing ES to write to OS's /tmp directory */ + disableEsTmpDir?: boolean; } diff --git a/packages/kbn-es/src/integration_tests/cluster.test.ts b/packages/kbn-es/src/integration_tests/cluster.test.ts index e8246558732c0..0ef9803539fdd 100644 --- a/packages/kbn-es/src/integration_tests/cluster.test.ts +++ b/packages/kbn-es/src/integration_tests/cluster.test.ts @@ -179,13 +179,13 @@ describe('#downloadSnapshot()', () => { }); describe('#installSource()', () => { - test('awaits installSource() promise and returns { installPath }', async () => { + test('awaits installSource() promise and returns { installPath, disableEsTmpDir }', async () => { let resolveInstallSource: Function; installSourceMock.mockImplementationOnce( () => new Promise((resolve) => { resolveInstallSource = () => { - resolve({ installPath: 'foo' }); + resolve({ installPath: 'foo', disableEsTmpDir: false }); }; }) ); @@ -196,11 +196,12 @@ describe('#installSource()', () => { resolveInstallSource!(); await expect(ensureResolve(promise, 'installSource()')).resolves.toEqual({ installPath: 'foo', + disableEsTmpDir: false, }); }); test('passes through all options+log to installSource()', async () => { - installSourceMock.mockResolvedValue({ installPath: 'foo' }); + installSourceMock.mockResolvedValue({ installPath: 'foo', disableEsTmpDir: false }); const options: InstallSourceOptions = { sourcePath: 'bar', license: 'trial', @@ -228,13 +229,13 @@ describe('#installSource()', () => { }); describe('#installSnapshot()', () => { - test('awaits installSnapshot() promise and returns { installPath }', async () => { + test('awaits installSnapshot() promise and returns { installPath, disableEsTmpDir }', async () => { let resolveInstallSnapshot: Function; installSnapshotMock.mockImplementationOnce( () => new Promise((resolve) => { resolveInstallSnapshot = () => { - resolve({ installPath: 'foo' }); + resolve({ installPath: 'foo', disableEsTmpDir: false }); }; }) ); @@ -245,11 +246,12 @@ describe('#installSnapshot()', () => { resolveInstallSnapshot!(); await expect(ensureResolve(promise, 'installSnapshot()')).resolves.toEqual({ installPath: 'foo', + disableEsTmpDir: false, }); }); test('passes through all options+log to installSnapshot()', async () => { - installSnapshotMock.mockResolvedValue({ installPath: 'foo' }); + installSnapshotMock.mockResolvedValue({ installPath: 'foo', disableEsTmpDir: false }); const options: InstallSnapshotOptions = { version: '8.10.0', license: 'trial', @@ -278,13 +280,13 @@ describe('#installSnapshot()', () => { }); describe('#installArchive()', () => { - test('awaits installArchive() promise and returns { installPath }', async () => { + test('awaits installArchive() promise and returns { installPath, disableEsTmpDir }', async () => { let resolveInstallArchive: Function; installArchiveMock.mockImplementationOnce( () => new Promise((resolve) => { resolveInstallArchive = () => { - resolve({ installPath: 'foo' }); + resolve({ installPath: 'foo', disableEsTmpDir: false }); }; }) ); @@ -295,11 +297,12 @@ describe('#installArchive()', () => { resolveInstallArchive!(); await expect(ensureResolve(promise, 'installArchive()')).resolves.toEqual({ installPath: 'foo', + disableEsTmpDir: false, }); }); test('passes through all options+log to installArchive()', async () => { - installArchiveMock.mockResolvedValue({ installPath: 'foo' }); + installArchiveMock.mockResolvedValue({ installPath: 'foo', disableEsTmpDir: true }); const options: InstallArchiveOptions = { license: 'trial', password: 'changeme', @@ -307,6 +310,7 @@ describe('#installArchive()', () => { installPath: 'someInstallPath', esArgs: ['foo=true'], log, + disableEsTmpDir: true, }; const cluster = new Cluster({ log }); await cluster.installArchive('bar', options); diff --git a/packages/kbn-esql-ast/src/antlr/esql_lexer.g4 b/packages/kbn-esql-ast/src/antlr/esql_lexer.g4 index 39c21a950f278..a4e0492ce1c61 100644 --- a/packages/kbn-esql-ast/src/antlr/esql_lexer.g4 +++ b/packages/kbn-esql-ast/src/antlr/esql_lexer.g4 @@ -199,7 +199,6 @@ FROM_COMMA : COMMA -> type(COMMA); FROM_ASSIGN : ASSIGN -> type(ASSIGN); FROM_QUOTED_STRING : QUOTED_STRING -> type(QUOTED_STRING); -OPTIONS : 'options'; METADATA : 'metadata'; fragment FROM_UNQUOTED_IDENTIFIER_PART @@ -432,4 +431,4 @@ SETTTING_MULTILINE_COMMENT SETTING_WS : WS -> channel(HIDDEN) - ; \ No newline at end of file + ; diff --git a/packages/kbn-esql-ast/src/antlr/esql_lexer.interp b/packages/kbn-esql-ast/src/antlr/esql_lexer.interp index 0fdcdb1939bd1..fad6acad9ab58 100644 --- a/packages/kbn-esql-ast/src/antlr/esql_lexer.interp +++ b/packages/kbn-esql-ast/src/antlr/esql_lexer.interp @@ -71,7 +71,6 @@ null null null null -'options' 'metadata' null null @@ -184,7 +183,6 @@ QUOTED_IDENTIFIER EXPR_LINE_COMMENT EXPR_MULTILINE_COMMENT EXPR_WS -OPTIONS METADATA FROM_UNQUOTED_IDENTIFIER FROM_LINE_COMMENT @@ -315,7 +313,6 @@ FROM_CLOSING_BRACKET FROM_COMMA FROM_ASSIGN FROM_QUOTED_STRING -OPTIONS METADATA FROM_UNQUOTED_IDENTIFIER_PART FROM_UNQUOTED_IDENTIFIER @@ -404,4 +401,4 @@ META_MODE SETTING_MODE atn: -[4, 0, 110, 1197, 6, -1, 6, -1, 6, -1, 6, -1, 6, -1, 6, -1, 6, -1, 6, -1, 6, -1, 6, -1, 6, -1, 6, -1, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15, 2, 16, 7, 16, 2, 17, 7, 17, 2, 18, 7, 18, 2, 19, 7, 19, 2, 20, 7, 20, 2, 21, 7, 21, 2, 22, 7, 22, 2, 23, 7, 23, 2, 24, 7, 24, 2, 25, 7, 25, 2, 26, 7, 26, 2, 27, 7, 27, 2, 28, 7, 28, 2, 29, 7, 29, 2, 30, 7, 30, 2, 31, 7, 31, 2, 32, 7, 32, 2, 33, 7, 33, 2, 34, 7, 34, 2, 35, 7, 35, 2, 36, 7, 36, 2, 37, 7, 37, 2, 38, 7, 38, 2, 39, 7, 39, 2, 40, 7, 40, 2, 41, 7, 41, 2, 42, 7, 42, 2, 43, 7, 43, 2, 44, 7, 44, 2, 45, 7, 45, 2, 46, 7, 46, 2, 47, 7, 47, 2, 48, 7, 48, 2, 49, 7, 49, 2, 50, 7, 50, 2, 51, 7, 51, 2, 52, 7, 52, 2, 53, 7, 53, 2, 54, 7, 54, 2, 55, 7, 55, 2, 56, 7, 56, 2, 57, 7, 57, 2, 58, 7, 58, 2, 59, 7, 59, 2, 60, 7, 60, 2, 61, 7, 61, 2, 62, 7, 62, 2, 63, 7, 63, 2, 64, 7, 64, 2, 65, 7, 65, 2, 66, 7, 66, 2, 67, 7, 67, 2, 68, 7, 68, 2, 69, 7, 69, 2, 70, 7, 70, 2, 71, 7, 71, 2, 72, 7, 72, 2, 73, 7, 73, 2, 74, 7, 74, 2, 75, 7, 75, 2, 76, 7, 76, 2, 77, 7, 77, 2, 78, 7, 78, 2, 79, 7, 79, 2, 80, 7, 80, 2, 81, 7, 81, 2, 82, 7, 82, 2, 83, 7, 83, 2, 84, 7, 84, 2, 85, 7, 85, 2, 86, 7, 86, 2, 87, 7, 87, 2, 88, 7, 88, 2, 89, 7, 89, 2, 90, 7, 90, 2, 91, 7, 91, 2, 92, 7, 92, 2, 93, 7, 93, 2, 94, 7, 94, 2, 95, 7, 95, 2, 96, 7, 96, 2, 97, 7, 97, 2, 98, 7, 98, 2, 99, 7, 99, 2, 100, 7, 100, 2, 101, 7, 101, 2, 102, 7, 102, 2, 103, 7, 103, 2, 104, 7, 104, 2, 105, 7, 105, 2, 106, 7, 106, 2, 107, 7, 107, 2, 108, 7, 108, 2, 109, 7, 109, 2, 110, 7, 110, 2, 111, 7, 111, 2, 112, 7, 112, 2, 113, 7, 113, 2, 114, 7, 114, 2, 115, 7, 115, 2, 116, 7, 116, 2, 117, 7, 117, 2, 118, 7, 118, 2, 119, 7, 119, 2, 120, 7, 120, 2, 121, 7, 121, 2, 122, 7, 122, 2, 123, 7, 123, 2, 124, 7, 124, 2, 125, 7, 125, 2, 126, 7, 126, 2, 127, 7, 127, 2, 128, 7, 128, 2, 129, 7, 129, 2, 130, 7, 130, 2, 131, 7, 131, 2, 132, 7, 132, 2, 133, 7, 133, 2, 134, 7, 134, 2, 135, 7, 135, 2, 136, 7, 136, 2, 137, 7, 137, 2, 138, 7, 138, 2, 139, 7, 139, 2, 140, 7, 140, 2, 141, 7, 141, 2, 142, 7, 142, 2, 143, 7, 143, 2, 144, 7, 144, 2, 145, 7, 145, 2, 146, 7, 146, 2, 147, 7, 147, 2, 148, 7, 148, 2, 149, 7, 149, 2, 150, 7, 150, 2, 151, 7, 151, 2, 152, 7, 152, 2, 153, 7, 153, 2, 154, 7, 154, 2, 155, 7, 155, 2, 156, 7, 156, 2, 157, 7, 157, 2, 158, 7, 158, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 1, 18, 4, 18, 482, 8, 18, 11, 18, 12, 18, 483, 1, 18, 1, 18, 1, 19, 1, 19, 1, 19, 1, 19, 5, 19, 492, 8, 19, 10, 19, 12, 19, 495, 9, 19, 1, 19, 3, 19, 498, 8, 19, 1, 19, 3, 19, 501, 8, 19, 1, 19, 1, 19, 1, 20, 1, 20, 1, 20, 1, 20, 1, 20, 5, 20, 510, 8, 20, 10, 20, 12, 20, 513, 9, 20, 1, 20, 1, 20, 1, 20, 1, 20, 1, 20, 1, 21, 4, 21, 521, 8, 21, 11, 21, 12, 21, 522, 1, 21, 1, 21, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 23, 1, 23, 1, 23, 1, 23, 1, 23, 1, 24, 1, 24, 1, 24, 1, 24, 1, 25, 1, 25, 1, 25, 1, 25, 1, 26, 1, 26, 1, 26, 1, 26, 1, 27, 1, 27, 1, 27, 1, 27, 1, 28, 1, 28, 1, 29, 1, 29, 1, 30, 1, 30, 1, 30, 1, 31, 1, 31, 1, 32, 1, 32, 3, 32, 564, 8, 32, 1, 32, 4, 32, 567, 8, 32, 11, 32, 12, 32, 568, 1, 33, 1, 33, 1, 34, 1, 34, 1, 35, 1, 35, 1, 35, 3, 35, 578, 8, 35, 1, 36, 1, 36, 1, 37, 1, 37, 1, 37, 3, 37, 585, 8, 37, 1, 38, 1, 38, 1, 38, 5, 38, 590, 8, 38, 10, 38, 12, 38, 593, 9, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 5, 38, 601, 8, 38, 10, 38, 12, 38, 604, 9, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 3, 38, 611, 8, 38, 1, 38, 3, 38, 614, 8, 38, 3, 38, 616, 8, 38, 1, 39, 4, 39, 619, 8, 39, 11, 39, 12, 39, 620, 1, 40, 4, 40, 624, 8, 40, 11, 40, 12, 40, 625, 1, 40, 1, 40, 5, 40, 630, 8, 40, 10, 40, 12, 40, 633, 9, 40, 1, 40, 1, 40, 4, 40, 637, 8, 40, 11, 40, 12, 40, 638, 1, 40, 4, 40, 642, 8, 40, 11, 40, 12, 40, 643, 1, 40, 1, 40, 5, 40, 648, 8, 40, 10, 40, 12, 40, 651, 9, 40, 3, 40, 653, 8, 40, 1, 40, 1, 40, 1, 40, 1, 40, 4, 40, 659, 8, 40, 11, 40, 12, 40, 660, 1, 40, 1, 40, 3, 40, 665, 8, 40, 1, 41, 1, 41, 1, 41, 1, 42, 1, 42, 1, 42, 1, 42, 1, 43, 1, 43, 1, 43, 1, 43, 1, 44, 1, 44, 1, 45, 1, 45, 1, 45, 1, 46, 1, 46, 1, 47, 1, 47, 1, 47, 1, 47, 1, 47, 1, 48, 1, 48, 1, 49, 1, 49, 1, 49, 1, 49, 1, 49, 1, 49, 1, 50, 1, 50, 1, 50, 1, 50, 1, 50, 1, 50, 1, 51, 1, 51, 1, 51, 1, 51, 1, 51, 1, 52, 1, 52, 1, 53, 1, 53, 1, 53, 1, 54, 1, 54, 1, 54, 1, 55, 1, 55, 1, 55, 1, 55, 1, 55, 1, 56, 1, 56, 1, 56, 1, 56, 1, 57, 1, 57, 1, 57, 1, 57, 1, 57, 1, 58, 1, 58, 1, 58, 1, 58, 1, 58, 1, 58, 1, 59, 1, 59, 1, 59, 1, 60, 1, 60, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 62, 1, 62, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 64, 1, 64, 1, 64, 1, 65, 1, 65, 1, 65, 1, 66, 1, 66, 1, 66, 1, 67, 1, 67, 1, 68, 1, 68, 1, 68, 1, 69, 1, 69, 1, 70, 1, 70, 1, 70, 1, 71, 1, 71, 1, 72, 1, 72, 1, 73, 1, 73, 1, 74, 1, 74, 1, 75, 1, 75, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 77, 1, 77, 1, 77, 1, 77, 1, 77, 1, 78, 1, 78, 5, 78, 796, 8, 78, 10, 78, 12, 78, 799, 9, 78, 1, 78, 1, 78, 3, 78, 803, 8, 78, 1, 78, 4, 78, 806, 8, 78, 11, 78, 12, 78, 807, 3, 78, 810, 8, 78, 1, 79, 1, 79, 4, 79, 814, 8, 79, 11, 79, 12, 79, 815, 1, 79, 1, 79, 1, 80, 1, 80, 1, 81, 1, 81, 1, 81, 1, 81, 1, 82, 1, 82, 1, 82, 1, 82, 1, 83, 1, 83, 1, 83, 1, 83, 1, 84, 1, 84, 1, 84, 1, 84, 1, 84, 1, 85, 1, 85, 1, 85, 1, 85, 1, 86, 1, 86, 1, 86, 1, 86, 1, 87, 1, 87, 1, 87, 1, 87, 1, 88, 1, 88, 1, 88, 1, 88, 1, 89, 1, 89, 1, 89, 1, 89, 1, 90, 1, 90, 1, 90, 1, 90, 1, 90, 1, 90, 1, 90, 1, 90, 1, 91, 1, 91, 1, 91, 1, 91, 1, 91, 1, 91, 1, 91, 1, 91, 1, 91, 1, 92, 1, 92, 1, 92, 3, 92, 879, 8, 92, 1, 93, 4, 93, 882, 8, 93, 11, 93, 12, 93, 883, 1, 94, 1, 94, 1, 94, 1, 94, 1, 95, 1, 95, 1, 95, 1, 95, 1, 96, 1, 96, 1, 96, 1, 96, 1, 97, 1, 97, 1, 97, 1, 97, 1, 97, 1, 98, 1, 98, 1, 98, 1, 98, 1, 99, 1, 99, 1, 99, 1, 99, 1, 100, 1, 100, 1, 100, 1, 100, 3, 100, 915, 8, 100, 1, 101, 1, 101, 3, 101, 919, 8, 101, 1, 101, 5, 101, 922, 8, 101, 10, 101, 12, 101, 925, 9, 101, 1, 101, 1, 101, 3, 101, 929, 8, 101, 1, 101, 4, 101, 932, 8, 101, 11, 101, 12, 101, 933, 3, 101, 936, 8, 101, 1, 102, 1, 102, 4, 102, 940, 8, 102, 11, 102, 12, 102, 941, 1, 103, 1, 103, 1, 103, 1, 103, 1, 104, 1, 104, 1, 104, 1, 104, 1, 105, 1, 105, 1, 105, 1, 105, 1, 106, 1, 106, 1, 106, 1, 106, 1, 106, 1, 107, 1, 107, 1, 107, 1, 107, 1, 108, 1, 108, 1, 108, 1, 108, 1, 109, 1, 109, 1, 109, 1, 109, 1, 110, 1, 110, 1, 110, 1, 111, 1, 111, 1, 111, 1, 111, 1, 112, 1, 112, 1, 112, 1, 112, 1, 113, 1, 113, 1, 113, 1, 113, 1, 114, 1, 114, 1, 114, 1, 114, 1, 115, 1, 115, 1, 115, 1, 115, 1, 115, 1, 116, 1, 116, 1, 116, 1, 116, 1, 116, 1, 117, 1, 117, 1, 117, 1, 117, 1, 117, 1, 118, 1, 118, 1, 118, 1, 118, 1, 118, 1, 118, 1, 118, 1, 119, 1, 119, 1, 120, 4, 120, 1017, 8, 120, 11, 120, 12, 120, 1018, 1, 120, 1, 120, 3, 120, 1023, 8, 120, 1, 120, 4, 120, 1026, 8, 120, 11, 120, 12, 120, 1027, 1, 121, 1, 121, 1, 121, 1, 121, 1, 122, 1, 122, 1, 122, 1, 122, 1, 123, 1, 123, 1, 123, 1, 123, 1, 124, 1, 124, 1, 124, 1, 124, 1, 125, 1, 125, 1, 125, 1, 125, 1, 126, 1, 126, 1, 126, 1, 126, 1, 126, 1, 126, 1, 127, 1, 127, 1, 127, 1, 127, 1, 128, 1, 128, 1, 128, 1, 128, 1, 129, 1, 129, 1, 129, 1, 129, 1, 130, 1, 130, 1, 130, 1, 130, 1, 131, 1, 131, 1, 131, 1, 131, 1, 132, 1, 132, 1, 132, 1, 132, 1, 133, 1, 133, 1, 133, 1, 133, 1, 134, 1, 134, 1, 134, 1, 134, 1, 135, 1, 135, 1, 135, 1, 135, 1, 136, 1, 136, 1, 136, 1, 136, 1, 136, 1, 137, 1, 137, 1, 137, 1, 137, 1, 138, 1, 138, 1, 138, 1, 138, 1, 139, 1, 139, 1, 139, 1, 139, 1, 140, 1, 140, 1, 140, 1, 140, 1, 141, 1, 141, 1, 141, 1, 141, 1, 142, 1, 142, 1, 142, 1, 142, 1, 143, 1, 143, 1, 143, 1, 143, 1, 143, 1, 144, 1, 144, 1, 144, 1, 144, 1, 144, 1, 145, 1, 145, 1, 145, 1, 145, 1, 146, 1, 146, 1, 146, 1, 146, 1, 147, 1, 147, 1, 147, 1, 147, 1, 148, 1, 148, 1, 148, 1, 148, 1, 148, 1, 149, 1, 149, 1, 149, 1, 149, 1, 149, 1, 149, 1, 149, 1, 149, 1, 149, 1, 149, 1, 150, 1, 150, 1, 150, 1, 150, 1, 151, 1, 151, 1, 151, 1, 151, 1, 152, 1, 152, 1, 152, 1, 152, 1, 153, 1, 153, 1, 153, 1, 153, 1, 153, 1, 154, 1, 154, 1, 155, 1, 155, 1, 155, 1, 155, 1, 155, 4, 155, 1182, 8, 155, 11, 155, 12, 155, 1183, 1, 156, 1, 156, 1, 156, 1, 156, 1, 157, 1, 157, 1, 157, 1, 157, 1, 158, 1, 158, 1, 158, 1, 158, 2, 511, 602, 0, 159, 12, 1, 14, 2, 16, 3, 18, 4, 20, 5, 22, 6, 24, 7, 26, 8, 28, 9, 30, 10, 32, 11, 34, 12, 36, 13, 38, 14, 40, 15, 42, 16, 44, 17, 46, 18, 48, 19, 50, 20, 52, 21, 54, 22, 56, 0, 58, 0, 60, 23, 62, 24, 64, 25, 66, 26, 68, 0, 70, 0, 72, 0, 74, 0, 76, 0, 78, 0, 80, 0, 82, 0, 84, 0, 86, 0, 88, 27, 90, 28, 92, 29, 94, 30, 96, 31, 98, 32, 100, 33, 102, 34, 104, 35, 106, 36, 108, 37, 110, 38, 112, 39, 114, 40, 116, 41, 118, 42, 120, 43, 122, 44, 124, 45, 126, 46, 128, 47, 130, 48, 132, 49, 134, 50, 136, 51, 138, 52, 140, 53, 142, 54, 144, 55, 146, 56, 148, 57, 150, 58, 152, 59, 154, 60, 156, 61, 158, 62, 160, 63, 162, 64, 164, 65, 166, 66, 168, 67, 170, 0, 172, 68, 174, 69, 176, 70, 178, 71, 180, 0, 182, 0, 184, 0, 186, 0, 188, 0, 190, 0, 192, 72, 194, 73, 196, 0, 198, 74, 200, 75, 202, 76, 204, 77, 206, 0, 208, 0, 210, 0, 212, 0, 214, 0, 216, 78, 218, 79, 220, 80, 222, 81, 224, 0, 226, 0, 228, 0, 230, 0, 232, 82, 234, 0, 236, 83, 238, 84, 240, 85, 242, 0, 244, 0, 246, 86, 248, 87, 250, 0, 252, 88, 254, 0, 256, 0, 258, 89, 260, 90, 262, 91, 264, 0, 266, 0, 268, 0, 270, 0, 272, 0, 274, 0, 276, 0, 278, 92, 280, 93, 282, 94, 284, 0, 286, 0, 288, 0, 290, 0, 292, 95, 294, 96, 296, 97, 298, 0, 300, 98, 302, 99, 304, 100, 306, 101, 308, 0, 310, 102, 312, 103, 314, 104, 316, 105, 318, 0, 320, 106, 322, 107, 324, 108, 326, 109, 328, 110, 12, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 35, 2, 0, 68, 68, 100, 100, 2, 0, 73, 73, 105, 105, 2, 0, 83, 83, 115, 115, 2, 0, 69, 69, 101, 101, 2, 0, 67, 67, 99, 99, 2, 0, 84, 84, 116, 116, 2, 0, 82, 82, 114, 114, 2, 0, 79, 79, 111, 111, 2, 0, 80, 80, 112, 112, 2, 0, 78, 78, 110, 110, 2, 0, 72, 72, 104, 104, 2, 0, 86, 86, 118, 118, 2, 0, 65, 65, 97, 97, 2, 0, 76, 76, 108, 108, 2, 0, 88, 88, 120, 120, 2, 0, 70, 70, 102, 102, 2, 0, 77, 77, 109, 109, 2, 0, 71, 71, 103, 103, 2, 0, 75, 75, 107, 107, 2, 0, 87, 87, 119, 119, 6, 0, 9, 10, 13, 13, 32, 32, 47, 47, 91, 91, 93, 93, 2, 0, 10, 10, 13, 13, 3, 0, 9, 10, 13, 13, 32, 32, 1, 0, 48, 57, 2, 0, 65, 90, 97, 122, 8, 0, 34, 34, 78, 78, 82, 82, 84, 84, 92, 92, 110, 110, 114, 114, 116, 116, 4, 0, 10, 10, 13, 13, 34, 34, 92, 92, 2, 0, 43, 43, 45, 45, 1, 0, 96, 96, 2, 0, 66, 66, 98, 98, 2, 0, 89, 89, 121, 121, 2, 0, 85, 85, 117, 117, 10, 0, 9, 10, 13, 13, 32, 32, 44, 44, 47, 47, 61, 61, 91, 91, 93, 93, 96, 96, 124, 124, 2, 0, 42, 42, 47, 47, 11, 0, 9, 10, 13, 13, 32, 32, 34, 35, 44, 44, 47, 47, 58, 58, 60, 60, 62, 63, 92, 92, 124, 124, 1224, 0, 12, 1, 0, 0, 0, 0, 14, 1, 0, 0, 0, 0, 16, 1, 0, 0, 0, 0, 18, 1, 0, 0, 0, 0, 20, 1, 0, 0, 0, 0, 22, 1, 0, 0, 0, 0, 24, 1, 0, 0, 0, 0, 26, 1, 0, 0, 0, 0, 28, 1, 0, 0, 0, 0, 30, 1, 0, 0, 0, 0, 32, 1, 0, 0, 0, 0, 34, 1, 0, 0, 0, 0, 36, 1, 0, 0, 0, 0, 38, 1, 0, 0, 0, 0, 40, 1, 0, 0, 0, 0, 42, 1, 0, 0, 0, 0, 44, 1, 0, 0, 0, 0, 46, 1, 0, 0, 0, 0, 48, 1, 0, 0, 0, 0, 50, 1, 0, 0, 0, 0, 52, 1, 0, 0, 0, 0, 54, 1, 0, 0, 0, 1, 56, 1, 0, 0, 0, 1, 58, 1, 0, 0, 0, 1, 60, 1, 0, 0, 0, 1, 62, 1, 0, 0, 0, 1, 64, 1, 0, 0, 0, 2, 66, 1, 0, 0, 0, 2, 88, 1, 0, 0, 0, 2, 90, 1, 0, 0, 0, 2, 92, 1, 0, 0, 0, 2, 94, 1, 0, 0, 0, 2, 96, 1, 0, 0, 0, 2, 98, 1, 0, 0, 0, 2, 100, 1, 0, 0, 0, 2, 102, 1, 0, 0, 0, 2, 104, 1, 0, 0, 0, 2, 106, 1, 0, 0, 0, 2, 108, 1, 0, 0, 0, 2, 110, 1, 0, 0, 0, 2, 112, 1, 0, 0, 0, 2, 114, 1, 0, 0, 0, 2, 116, 1, 0, 0, 0, 2, 118, 1, 0, 0, 0, 2, 120, 1, 0, 0, 0, 2, 122, 1, 0, 0, 0, 2, 124, 1, 0, 0, 0, 2, 126, 1, 0, 0, 0, 2, 128, 1, 0, 0, 0, 2, 130, 1, 0, 0, 0, 2, 132, 1, 0, 0, 0, 2, 134, 1, 0, 0, 0, 2, 136, 1, 0, 0, 0, 2, 138, 1, 0, 0, 0, 2, 140, 1, 0, 0, 0, 2, 142, 1, 0, 0, 0, 2, 144, 1, 0, 0, 0, 2, 146, 1, 0, 0, 0, 2, 148, 1, 0, 0, 0, 2, 150, 1, 0, 0, 0, 2, 152, 1, 0, 0, 0, 2, 154, 1, 0, 0, 0, 2, 156, 1, 0, 0, 0, 2, 158, 1, 0, 0, 0, 2, 160, 1, 0, 0, 0, 2, 162, 1, 0, 0, 0, 2, 164, 1, 0, 0, 0, 2, 166, 1, 0, 0, 0, 2, 168, 1, 0, 0, 0, 2, 172, 1, 0, 0, 0, 2, 174, 1, 0, 0, 0, 2, 176, 1, 0, 0, 0, 2, 178, 1, 0, 0, 0, 3, 180, 1, 0, 0, 0, 3, 182, 1, 0, 0, 0, 3, 184, 1, 0, 0, 0, 3, 186, 1, 0, 0, 0, 3, 188, 1, 0, 0, 0, 3, 190, 1, 0, 0, 0, 3, 192, 1, 0, 0, 0, 3, 194, 1, 0, 0, 0, 3, 198, 1, 0, 0, 0, 3, 200, 1, 0, 0, 0, 3, 202, 1, 0, 0, 0, 3, 204, 1, 0, 0, 0, 4, 206, 1, 0, 0, 0, 4, 208, 1, 0, 0, 0, 4, 210, 1, 0, 0, 0, 4, 216, 1, 0, 0, 0, 4, 218, 1, 0, 0, 0, 4, 220, 1, 0, 0, 0, 4, 222, 1, 0, 0, 0, 5, 224, 1, 0, 0, 0, 5, 226, 1, 0, 0, 0, 5, 228, 1, 0, 0, 0, 5, 230, 1, 0, 0, 0, 5, 232, 1, 0, 0, 0, 5, 234, 1, 0, 0, 0, 5, 236, 1, 0, 0, 0, 5, 238, 1, 0, 0, 0, 5, 240, 1, 0, 0, 0, 6, 242, 1, 0, 0, 0, 6, 244, 1, 0, 0, 0, 6, 246, 1, 0, 0, 0, 6, 248, 1, 0, 0, 0, 6, 252, 1, 0, 0, 0, 6, 254, 1, 0, 0, 0, 6, 256, 1, 0, 0, 0, 6, 258, 1, 0, 0, 0, 6, 260, 1, 0, 0, 0, 6, 262, 1, 0, 0, 0, 7, 264, 1, 0, 0, 0, 7, 266, 1, 0, 0, 0, 7, 268, 1, 0, 0, 0, 7, 270, 1, 0, 0, 0, 7, 272, 1, 0, 0, 0, 7, 274, 1, 0, 0, 0, 7, 276, 1, 0, 0, 0, 7, 278, 1, 0, 0, 0, 7, 280, 1, 0, 0, 0, 7, 282, 1, 0, 0, 0, 8, 284, 1, 0, 0, 0, 8, 286, 1, 0, 0, 0, 8, 288, 1, 0, 0, 0, 8, 290, 1, 0, 0, 0, 8, 292, 1, 0, 0, 0, 8, 294, 1, 0, 0, 0, 8, 296, 1, 0, 0, 0, 9, 298, 1, 0, 0, 0, 9, 300, 1, 0, 0, 0, 9, 302, 1, 0, 0, 0, 9, 304, 1, 0, 0, 0, 9, 306, 1, 0, 0, 0, 10, 308, 1, 0, 0, 0, 10, 310, 1, 0, 0, 0, 10, 312, 1, 0, 0, 0, 10, 314, 1, 0, 0, 0, 10, 316, 1, 0, 0, 0, 11, 318, 1, 0, 0, 0, 11, 320, 1, 0, 0, 0, 11, 322, 1, 0, 0, 0, 11, 324, 1, 0, 0, 0, 11, 326, 1, 0, 0, 0, 11, 328, 1, 0, 0, 0, 12, 330, 1, 0, 0, 0, 14, 340, 1, 0, 0, 0, 16, 347, 1, 0, 0, 0, 18, 356, 1, 0, 0, 0, 20, 363, 1, 0, 0, 0, 22, 373, 1, 0, 0, 0, 24, 380, 1, 0, 0, 0, 26, 387, 1, 0, 0, 0, 28, 401, 1, 0, 0, 0, 30, 408, 1, 0, 0, 0, 32, 416, 1, 0, 0, 0, 34, 423, 1, 0, 0, 0, 36, 435, 1, 0, 0, 0, 38, 444, 1, 0, 0, 0, 40, 450, 1, 0, 0, 0, 42, 457, 1, 0, 0, 0, 44, 464, 1, 0, 0, 0, 46, 472, 1, 0, 0, 0, 48, 481, 1, 0, 0, 0, 50, 487, 1, 0, 0, 0, 52, 504, 1, 0, 0, 0, 54, 520, 1, 0, 0, 0, 56, 526, 1, 0, 0, 0, 58, 531, 1, 0, 0, 0, 60, 536, 1, 0, 0, 0, 62, 540, 1, 0, 0, 0, 64, 544, 1, 0, 0, 0, 66, 548, 1, 0, 0, 0, 68, 552, 1, 0, 0, 0, 70, 554, 1, 0, 0, 0, 72, 556, 1, 0, 0, 0, 74, 559, 1, 0, 0, 0, 76, 561, 1, 0, 0, 0, 78, 570, 1, 0, 0, 0, 80, 572, 1, 0, 0, 0, 82, 577, 1, 0, 0, 0, 84, 579, 1, 0, 0, 0, 86, 584, 1, 0, 0, 0, 88, 615, 1, 0, 0, 0, 90, 618, 1, 0, 0, 0, 92, 664, 1, 0, 0, 0, 94, 666, 1, 0, 0, 0, 96, 669, 1, 0, 0, 0, 98, 673, 1, 0, 0, 0, 100, 677, 1, 0, 0, 0, 102, 679, 1, 0, 0, 0, 104, 682, 1, 0, 0, 0, 106, 684, 1, 0, 0, 0, 108, 689, 1, 0, 0, 0, 110, 691, 1, 0, 0, 0, 112, 697, 1, 0, 0, 0, 114, 703, 1, 0, 0, 0, 116, 708, 1, 0, 0, 0, 118, 710, 1, 0, 0, 0, 120, 713, 1, 0, 0, 0, 122, 716, 1, 0, 0, 0, 124, 721, 1, 0, 0, 0, 126, 725, 1, 0, 0, 0, 128, 730, 1, 0, 0, 0, 130, 736, 1, 0, 0, 0, 132, 739, 1, 0, 0, 0, 134, 741, 1, 0, 0, 0, 136, 747, 1, 0, 0, 0, 138, 749, 1, 0, 0, 0, 140, 754, 1, 0, 0, 0, 142, 757, 1, 0, 0, 0, 144, 760, 1, 0, 0, 0, 146, 763, 1, 0, 0, 0, 148, 765, 1, 0, 0, 0, 150, 768, 1, 0, 0, 0, 152, 770, 1, 0, 0, 0, 154, 773, 1, 0, 0, 0, 156, 775, 1, 0, 0, 0, 158, 777, 1, 0, 0, 0, 160, 779, 1, 0, 0, 0, 162, 781, 1, 0, 0, 0, 164, 783, 1, 0, 0, 0, 166, 788, 1, 0, 0, 0, 168, 809, 1, 0, 0, 0, 170, 811, 1, 0, 0, 0, 172, 819, 1, 0, 0, 0, 174, 821, 1, 0, 0, 0, 176, 825, 1, 0, 0, 0, 178, 829, 1, 0, 0, 0, 180, 833, 1, 0, 0, 0, 182, 838, 1, 0, 0, 0, 184, 842, 1, 0, 0, 0, 186, 846, 1, 0, 0, 0, 188, 850, 1, 0, 0, 0, 190, 854, 1, 0, 0, 0, 192, 858, 1, 0, 0, 0, 194, 866, 1, 0, 0, 0, 196, 878, 1, 0, 0, 0, 198, 881, 1, 0, 0, 0, 200, 885, 1, 0, 0, 0, 202, 889, 1, 0, 0, 0, 204, 893, 1, 0, 0, 0, 206, 897, 1, 0, 0, 0, 208, 902, 1, 0, 0, 0, 210, 906, 1, 0, 0, 0, 212, 914, 1, 0, 0, 0, 214, 935, 1, 0, 0, 0, 216, 939, 1, 0, 0, 0, 218, 943, 1, 0, 0, 0, 220, 947, 1, 0, 0, 0, 222, 951, 1, 0, 0, 0, 224, 955, 1, 0, 0, 0, 226, 960, 1, 0, 0, 0, 228, 964, 1, 0, 0, 0, 230, 968, 1, 0, 0, 0, 232, 972, 1, 0, 0, 0, 234, 975, 1, 0, 0, 0, 236, 979, 1, 0, 0, 0, 238, 983, 1, 0, 0, 0, 240, 987, 1, 0, 0, 0, 242, 991, 1, 0, 0, 0, 244, 996, 1, 0, 0, 0, 246, 1001, 1, 0, 0, 0, 248, 1006, 1, 0, 0, 0, 250, 1013, 1, 0, 0, 0, 252, 1022, 1, 0, 0, 0, 254, 1029, 1, 0, 0, 0, 256, 1033, 1, 0, 0, 0, 258, 1037, 1, 0, 0, 0, 260, 1041, 1, 0, 0, 0, 262, 1045, 1, 0, 0, 0, 264, 1049, 1, 0, 0, 0, 266, 1055, 1, 0, 0, 0, 268, 1059, 1, 0, 0, 0, 270, 1063, 1, 0, 0, 0, 272, 1067, 1, 0, 0, 0, 274, 1071, 1, 0, 0, 0, 276, 1075, 1, 0, 0, 0, 278, 1079, 1, 0, 0, 0, 280, 1083, 1, 0, 0, 0, 282, 1087, 1, 0, 0, 0, 284, 1091, 1, 0, 0, 0, 286, 1096, 1, 0, 0, 0, 288, 1100, 1, 0, 0, 0, 290, 1104, 1, 0, 0, 0, 292, 1108, 1, 0, 0, 0, 294, 1112, 1, 0, 0, 0, 296, 1116, 1, 0, 0, 0, 298, 1120, 1, 0, 0, 0, 300, 1125, 1, 0, 0, 0, 302, 1130, 1, 0, 0, 0, 304, 1134, 1, 0, 0, 0, 306, 1138, 1, 0, 0, 0, 308, 1142, 1, 0, 0, 0, 310, 1147, 1, 0, 0, 0, 312, 1157, 1, 0, 0, 0, 314, 1161, 1, 0, 0, 0, 316, 1165, 1, 0, 0, 0, 318, 1169, 1, 0, 0, 0, 320, 1174, 1, 0, 0, 0, 322, 1181, 1, 0, 0, 0, 324, 1185, 1, 0, 0, 0, 326, 1189, 1, 0, 0, 0, 328, 1193, 1, 0, 0, 0, 330, 331, 7, 0, 0, 0, 331, 332, 7, 1, 0, 0, 332, 333, 7, 2, 0, 0, 333, 334, 7, 2, 0, 0, 334, 335, 7, 3, 0, 0, 335, 336, 7, 4, 0, 0, 336, 337, 7, 5, 0, 0, 337, 338, 1, 0, 0, 0, 338, 339, 6, 0, 0, 0, 339, 13, 1, 0, 0, 0, 340, 341, 7, 0, 0, 0, 341, 342, 7, 6, 0, 0, 342, 343, 7, 7, 0, 0, 343, 344, 7, 8, 0, 0, 344, 345, 1, 0, 0, 0, 345, 346, 6, 1, 1, 0, 346, 15, 1, 0, 0, 0, 347, 348, 7, 3, 0, 0, 348, 349, 7, 9, 0, 0, 349, 350, 7, 6, 0, 0, 350, 351, 7, 1, 0, 0, 351, 352, 7, 4, 0, 0, 352, 353, 7, 10, 0, 0, 353, 354, 1, 0, 0, 0, 354, 355, 6, 2, 2, 0, 355, 17, 1, 0, 0, 0, 356, 357, 7, 3, 0, 0, 357, 358, 7, 11, 0, 0, 358, 359, 7, 12, 0, 0, 359, 360, 7, 13, 0, 0, 360, 361, 1, 0, 0, 0, 361, 362, 6, 3, 0, 0, 362, 19, 1, 0, 0, 0, 363, 364, 7, 3, 0, 0, 364, 365, 7, 14, 0, 0, 365, 366, 7, 8, 0, 0, 366, 367, 7, 13, 0, 0, 367, 368, 7, 12, 0, 0, 368, 369, 7, 1, 0, 0, 369, 370, 7, 9, 0, 0, 370, 371, 1, 0, 0, 0, 371, 372, 6, 4, 3, 0, 372, 21, 1, 0, 0, 0, 373, 374, 7, 15, 0, 0, 374, 375, 7, 6, 0, 0, 375, 376, 7, 7, 0, 0, 376, 377, 7, 16, 0, 0, 377, 378, 1, 0, 0, 0, 378, 379, 6, 5, 4, 0, 379, 23, 1, 0, 0, 0, 380, 381, 7, 17, 0, 0, 381, 382, 7, 6, 0, 0, 382, 383, 7, 7, 0, 0, 383, 384, 7, 18, 0, 0, 384, 385, 1, 0, 0, 0, 385, 386, 6, 6, 0, 0, 386, 25, 1, 0, 0, 0, 387, 388, 7, 1, 0, 0, 388, 389, 7, 9, 0, 0, 389, 390, 7, 13, 0, 0, 390, 391, 7, 1, 0, 0, 391, 392, 7, 9, 0, 0, 392, 393, 7, 3, 0, 0, 393, 394, 7, 2, 0, 0, 394, 395, 7, 5, 0, 0, 395, 396, 7, 12, 0, 0, 396, 397, 7, 5, 0, 0, 397, 398, 7, 2, 0, 0, 398, 399, 1, 0, 0, 0, 399, 400, 6, 7, 0, 0, 400, 27, 1, 0, 0, 0, 401, 402, 7, 18, 0, 0, 402, 403, 7, 3, 0, 0, 403, 404, 7, 3, 0, 0, 404, 405, 7, 8, 0, 0, 405, 406, 1, 0, 0, 0, 406, 407, 6, 8, 1, 0, 407, 29, 1, 0, 0, 0, 408, 409, 7, 13, 0, 0, 409, 410, 7, 1, 0, 0, 410, 411, 7, 16, 0, 0, 411, 412, 7, 1, 0, 0, 412, 413, 7, 5, 0, 0, 413, 414, 1, 0, 0, 0, 414, 415, 6, 9, 0, 0, 415, 31, 1, 0, 0, 0, 416, 417, 7, 16, 0, 0, 417, 418, 7, 3, 0, 0, 418, 419, 7, 5, 0, 0, 419, 420, 7, 12, 0, 0, 420, 421, 1, 0, 0, 0, 421, 422, 6, 10, 5, 0, 422, 33, 1, 0, 0, 0, 423, 424, 7, 16, 0, 0, 424, 425, 7, 11, 0, 0, 425, 426, 5, 95, 0, 0, 426, 427, 7, 3, 0, 0, 427, 428, 7, 14, 0, 0, 428, 429, 7, 8, 0, 0, 429, 430, 7, 12, 0, 0, 430, 431, 7, 9, 0, 0, 431, 432, 7, 0, 0, 0, 432, 433, 1, 0, 0, 0, 433, 434, 6, 11, 6, 0, 434, 35, 1, 0, 0, 0, 435, 436, 7, 6, 0, 0, 436, 437, 7, 3, 0, 0, 437, 438, 7, 9, 0, 0, 438, 439, 7, 12, 0, 0, 439, 440, 7, 16, 0, 0, 440, 441, 7, 3, 0, 0, 441, 442, 1, 0, 0, 0, 442, 443, 6, 12, 7, 0, 443, 37, 1, 0, 0, 0, 444, 445, 7, 6, 0, 0, 445, 446, 7, 7, 0, 0, 446, 447, 7, 19, 0, 0, 447, 448, 1, 0, 0, 0, 448, 449, 6, 13, 0, 0, 449, 39, 1, 0, 0, 0, 450, 451, 7, 2, 0, 0, 451, 452, 7, 10, 0, 0, 452, 453, 7, 7, 0, 0, 453, 454, 7, 19, 0, 0, 454, 455, 1, 0, 0, 0, 455, 456, 6, 14, 8, 0, 456, 41, 1, 0, 0, 0, 457, 458, 7, 2, 0, 0, 458, 459, 7, 7, 0, 0, 459, 460, 7, 6, 0, 0, 460, 461, 7, 5, 0, 0, 461, 462, 1, 0, 0, 0, 462, 463, 6, 15, 0, 0, 463, 43, 1, 0, 0, 0, 464, 465, 7, 2, 0, 0, 465, 466, 7, 5, 0, 0, 466, 467, 7, 12, 0, 0, 467, 468, 7, 5, 0, 0, 468, 469, 7, 2, 0, 0, 469, 470, 1, 0, 0, 0, 470, 471, 6, 16, 0, 0, 471, 45, 1, 0, 0, 0, 472, 473, 7, 19, 0, 0, 473, 474, 7, 10, 0, 0, 474, 475, 7, 3, 0, 0, 475, 476, 7, 6, 0, 0, 476, 477, 7, 3, 0, 0, 477, 478, 1, 0, 0, 0, 478, 479, 6, 17, 0, 0, 479, 47, 1, 0, 0, 0, 480, 482, 8, 20, 0, 0, 481, 480, 1, 0, 0, 0, 482, 483, 1, 0, 0, 0, 483, 481, 1, 0, 0, 0, 483, 484, 1, 0, 0, 0, 484, 485, 1, 0, 0, 0, 485, 486, 6, 18, 0, 0, 486, 49, 1, 0, 0, 0, 487, 488, 5, 47, 0, 0, 488, 489, 5, 47, 0, 0, 489, 493, 1, 0, 0, 0, 490, 492, 8, 21, 0, 0, 491, 490, 1, 0, 0, 0, 492, 495, 1, 0, 0, 0, 493, 491, 1, 0, 0, 0, 493, 494, 1, 0, 0, 0, 494, 497, 1, 0, 0, 0, 495, 493, 1, 0, 0, 0, 496, 498, 5, 13, 0, 0, 497, 496, 1, 0, 0, 0, 497, 498, 1, 0, 0, 0, 498, 500, 1, 0, 0, 0, 499, 501, 5, 10, 0, 0, 500, 499, 1, 0, 0, 0, 500, 501, 1, 0, 0, 0, 501, 502, 1, 0, 0, 0, 502, 503, 6, 19, 9, 0, 503, 51, 1, 0, 0, 0, 504, 505, 5, 47, 0, 0, 505, 506, 5, 42, 0, 0, 506, 511, 1, 0, 0, 0, 507, 510, 3, 52, 20, 0, 508, 510, 9, 0, 0, 0, 509, 507, 1, 0, 0, 0, 509, 508, 1, 0, 0, 0, 510, 513, 1, 0, 0, 0, 511, 512, 1, 0, 0, 0, 511, 509, 1, 0, 0, 0, 512, 514, 1, 0, 0, 0, 513, 511, 1, 0, 0, 0, 514, 515, 5, 42, 0, 0, 515, 516, 5, 47, 0, 0, 516, 517, 1, 0, 0, 0, 517, 518, 6, 20, 9, 0, 518, 53, 1, 0, 0, 0, 519, 521, 7, 22, 0, 0, 520, 519, 1, 0, 0, 0, 521, 522, 1, 0, 0, 0, 522, 520, 1, 0, 0, 0, 522, 523, 1, 0, 0, 0, 523, 524, 1, 0, 0, 0, 524, 525, 6, 21, 9, 0, 525, 55, 1, 0, 0, 0, 526, 527, 3, 164, 76, 0, 527, 528, 1, 0, 0, 0, 528, 529, 6, 22, 10, 0, 529, 530, 6, 22, 11, 0, 530, 57, 1, 0, 0, 0, 531, 532, 3, 66, 27, 0, 532, 533, 1, 0, 0, 0, 533, 534, 6, 23, 12, 0, 534, 535, 6, 23, 13, 0, 535, 59, 1, 0, 0, 0, 536, 537, 3, 54, 21, 0, 537, 538, 1, 0, 0, 0, 538, 539, 6, 24, 9, 0, 539, 61, 1, 0, 0, 0, 540, 541, 3, 50, 19, 0, 541, 542, 1, 0, 0, 0, 542, 543, 6, 25, 9, 0, 543, 63, 1, 0, 0, 0, 544, 545, 3, 52, 20, 0, 545, 546, 1, 0, 0, 0, 546, 547, 6, 26, 9, 0, 547, 65, 1, 0, 0, 0, 548, 549, 5, 124, 0, 0, 549, 550, 1, 0, 0, 0, 550, 551, 6, 27, 13, 0, 551, 67, 1, 0, 0, 0, 552, 553, 7, 23, 0, 0, 553, 69, 1, 0, 0, 0, 554, 555, 7, 24, 0, 0, 555, 71, 1, 0, 0, 0, 556, 557, 5, 92, 0, 0, 557, 558, 7, 25, 0, 0, 558, 73, 1, 0, 0, 0, 559, 560, 8, 26, 0, 0, 560, 75, 1, 0, 0, 0, 561, 563, 7, 3, 0, 0, 562, 564, 7, 27, 0, 0, 563, 562, 1, 0, 0, 0, 563, 564, 1, 0, 0, 0, 564, 566, 1, 0, 0, 0, 565, 567, 3, 68, 28, 0, 566, 565, 1, 0, 0, 0, 567, 568, 1, 0, 0, 0, 568, 566, 1, 0, 0, 0, 568, 569, 1, 0, 0, 0, 569, 77, 1, 0, 0, 0, 570, 571, 5, 64, 0, 0, 571, 79, 1, 0, 0, 0, 572, 573, 5, 96, 0, 0, 573, 81, 1, 0, 0, 0, 574, 578, 8, 28, 0, 0, 575, 576, 5, 96, 0, 0, 576, 578, 5, 96, 0, 0, 577, 574, 1, 0, 0, 0, 577, 575, 1, 0, 0, 0, 578, 83, 1, 0, 0, 0, 579, 580, 5, 95, 0, 0, 580, 85, 1, 0, 0, 0, 581, 585, 3, 70, 29, 0, 582, 585, 3, 68, 28, 0, 583, 585, 3, 84, 36, 0, 584, 581, 1, 0, 0, 0, 584, 582, 1, 0, 0, 0, 584, 583, 1, 0, 0, 0, 585, 87, 1, 0, 0, 0, 586, 591, 5, 34, 0, 0, 587, 590, 3, 72, 30, 0, 588, 590, 3, 74, 31, 0, 589, 587, 1, 0, 0, 0, 589, 588, 1, 0, 0, 0, 590, 593, 1, 0, 0, 0, 591, 589, 1, 0, 0, 0, 591, 592, 1, 0, 0, 0, 592, 594, 1, 0, 0, 0, 593, 591, 1, 0, 0, 0, 594, 616, 5, 34, 0, 0, 595, 596, 5, 34, 0, 0, 596, 597, 5, 34, 0, 0, 597, 598, 5, 34, 0, 0, 598, 602, 1, 0, 0, 0, 599, 601, 8, 21, 0, 0, 600, 599, 1, 0, 0, 0, 601, 604, 1, 0, 0, 0, 602, 603, 1, 0, 0, 0, 602, 600, 1, 0, 0, 0, 603, 605, 1, 0, 0, 0, 604, 602, 1, 0, 0, 0, 605, 606, 5, 34, 0, 0, 606, 607, 5, 34, 0, 0, 607, 608, 5, 34, 0, 0, 608, 610, 1, 0, 0, 0, 609, 611, 5, 34, 0, 0, 610, 609, 1, 0, 0, 0, 610, 611, 1, 0, 0, 0, 611, 613, 1, 0, 0, 0, 612, 614, 5, 34, 0, 0, 613, 612, 1, 0, 0, 0, 613, 614, 1, 0, 0, 0, 614, 616, 1, 0, 0, 0, 615, 586, 1, 0, 0, 0, 615, 595, 1, 0, 0, 0, 616, 89, 1, 0, 0, 0, 617, 619, 3, 68, 28, 0, 618, 617, 1, 0, 0, 0, 619, 620, 1, 0, 0, 0, 620, 618, 1, 0, 0, 0, 620, 621, 1, 0, 0, 0, 621, 91, 1, 0, 0, 0, 622, 624, 3, 68, 28, 0, 623, 622, 1, 0, 0, 0, 624, 625, 1, 0, 0, 0, 625, 623, 1, 0, 0, 0, 625, 626, 1, 0, 0, 0, 626, 627, 1, 0, 0, 0, 627, 631, 3, 108, 48, 0, 628, 630, 3, 68, 28, 0, 629, 628, 1, 0, 0, 0, 630, 633, 1, 0, 0, 0, 631, 629, 1, 0, 0, 0, 631, 632, 1, 0, 0, 0, 632, 665, 1, 0, 0, 0, 633, 631, 1, 0, 0, 0, 634, 636, 3, 108, 48, 0, 635, 637, 3, 68, 28, 0, 636, 635, 1, 0, 0, 0, 637, 638, 1, 0, 0, 0, 638, 636, 1, 0, 0, 0, 638, 639, 1, 0, 0, 0, 639, 665, 1, 0, 0, 0, 640, 642, 3, 68, 28, 0, 641, 640, 1, 0, 0, 0, 642, 643, 1, 0, 0, 0, 643, 641, 1, 0, 0, 0, 643, 644, 1, 0, 0, 0, 644, 652, 1, 0, 0, 0, 645, 649, 3, 108, 48, 0, 646, 648, 3, 68, 28, 0, 647, 646, 1, 0, 0, 0, 648, 651, 1, 0, 0, 0, 649, 647, 1, 0, 0, 0, 649, 650, 1, 0, 0, 0, 650, 653, 1, 0, 0, 0, 651, 649, 1, 0, 0, 0, 652, 645, 1, 0, 0, 0, 652, 653, 1, 0, 0, 0, 653, 654, 1, 0, 0, 0, 654, 655, 3, 76, 32, 0, 655, 665, 1, 0, 0, 0, 656, 658, 3, 108, 48, 0, 657, 659, 3, 68, 28, 0, 658, 657, 1, 0, 0, 0, 659, 660, 1, 0, 0, 0, 660, 658, 1, 0, 0, 0, 660, 661, 1, 0, 0, 0, 661, 662, 1, 0, 0, 0, 662, 663, 3, 76, 32, 0, 663, 665, 1, 0, 0, 0, 664, 623, 1, 0, 0, 0, 664, 634, 1, 0, 0, 0, 664, 641, 1, 0, 0, 0, 664, 656, 1, 0, 0, 0, 665, 93, 1, 0, 0, 0, 666, 667, 7, 29, 0, 0, 667, 668, 7, 30, 0, 0, 668, 95, 1, 0, 0, 0, 669, 670, 7, 12, 0, 0, 670, 671, 7, 9, 0, 0, 671, 672, 7, 0, 0, 0, 672, 97, 1, 0, 0, 0, 673, 674, 7, 12, 0, 0, 674, 675, 7, 2, 0, 0, 675, 676, 7, 4, 0, 0, 676, 99, 1, 0, 0, 0, 677, 678, 5, 61, 0, 0, 678, 101, 1, 0, 0, 0, 679, 680, 5, 58, 0, 0, 680, 681, 5, 58, 0, 0, 681, 103, 1, 0, 0, 0, 682, 683, 5, 44, 0, 0, 683, 105, 1, 0, 0, 0, 684, 685, 7, 0, 0, 0, 685, 686, 7, 3, 0, 0, 686, 687, 7, 2, 0, 0, 687, 688, 7, 4, 0, 0, 688, 107, 1, 0, 0, 0, 689, 690, 5, 46, 0, 0, 690, 109, 1, 0, 0, 0, 691, 692, 7, 15, 0, 0, 692, 693, 7, 12, 0, 0, 693, 694, 7, 13, 0, 0, 694, 695, 7, 2, 0, 0, 695, 696, 7, 3, 0, 0, 696, 111, 1, 0, 0, 0, 697, 698, 7, 15, 0, 0, 698, 699, 7, 1, 0, 0, 699, 700, 7, 6, 0, 0, 700, 701, 7, 2, 0, 0, 701, 702, 7, 5, 0, 0, 702, 113, 1, 0, 0, 0, 703, 704, 7, 13, 0, 0, 704, 705, 7, 12, 0, 0, 705, 706, 7, 2, 0, 0, 706, 707, 7, 5, 0, 0, 707, 115, 1, 0, 0, 0, 708, 709, 5, 40, 0, 0, 709, 117, 1, 0, 0, 0, 710, 711, 7, 1, 0, 0, 711, 712, 7, 9, 0, 0, 712, 119, 1, 0, 0, 0, 713, 714, 7, 1, 0, 0, 714, 715, 7, 2, 0, 0, 715, 121, 1, 0, 0, 0, 716, 717, 7, 13, 0, 0, 717, 718, 7, 1, 0, 0, 718, 719, 7, 18, 0, 0, 719, 720, 7, 3, 0, 0, 720, 123, 1, 0, 0, 0, 721, 722, 7, 9, 0, 0, 722, 723, 7, 7, 0, 0, 723, 724, 7, 5, 0, 0, 724, 125, 1, 0, 0, 0, 725, 726, 7, 9, 0, 0, 726, 727, 7, 31, 0, 0, 727, 728, 7, 13, 0, 0, 728, 729, 7, 13, 0, 0, 729, 127, 1, 0, 0, 0, 730, 731, 7, 9, 0, 0, 731, 732, 7, 31, 0, 0, 732, 733, 7, 13, 0, 0, 733, 734, 7, 13, 0, 0, 734, 735, 7, 2, 0, 0, 735, 129, 1, 0, 0, 0, 736, 737, 7, 7, 0, 0, 737, 738, 7, 6, 0, 0, 738, 131, 1, 0, 0, 0, 739, 740, 5, 63, 0, 0, 740, 133, 1, 0, 0, 0, 741, 742, 7, 6, 0, 0, 742, 743, 7, 13, 0, 0, 743, 744, 7, 1, 0, 0, 744, 745, 7, 18, 0, 0, 745, 746, 7, 3, 0, 0, 746, 135, 1, 0, 0, 0, 747, 748, 5, 41, 0, 0, 748, 137, 1, 0, 0, 0, 749, 750, 7, 5, 0, 0, 750, 751, 7, 6, 0, 0, 751, 752, 7, 31, 0, 0, 752, 753, 7, 3, 0, 0, 753, 139, 1, 0, 0, 0, 754, 755, 5, 61, 0, 0, 755, 756, 5, 61, 0, 0, 756, 141, 1, 0, 0, 0, 757, 758, 5, 61, 0, 0, 758, 759, 5, 126, 0, 0, 759, 143, 1, 0, 0, 0, 760, 761, 5, 33, 0, 0, 761, 762, 5, 61, 0, 0, 762, 145, 1, 0, 0, 0, 763, 764, 5, 60, 0, 0, 764, 147, 1, 0, 0, 0, 765, 766, 5, 60, 0, 0, 766, 767, 5, 61, 0, 0, 767, 149, 1, 0, 0, 0, 768, 769, 5, 62, 0, 0, 769, 151, 1, 0, 0, 0, 770, 771, 5, 62, 0, 0, 771, 772, 5, 61, 0, 0, 772, 153, 1, 0, 0, 0, 773, 774, 5, 43, 0, 0, 774, 155, 1, 0, 0, 0, 775, 776, 5, 45, 0, 0, 776, 157, 1, 0, 0, 0, 777, 778, 5, 42, 0, 0, 778, 159, 1, 0, 0, 0, 779, 780, 5, 47, 0, 0, 780, 161, 1, 0, 0, 0, 781, 782, 5, 37, 0, 0, 782, 163, 1, 0, 0, 0, 783, 784, 5, 91, 0, 0, 784, 785, 1, 0, 0, 0, 785, 786, 6, 76, 0, 0, 786, 787, 6, 76, 0, 0, 787, 165, 1, 0, 0, 0, 788, 789, 5, 93, 0, 0, 789, 790, 1, 0, 0, 0, 790, 791, 6, 77, 13, 0, 791, 792, 6, 77, 13, 0, 792, 167, 1, 0, 0, 0, 793, 797, 3, 70, 29, 0, 794, 796, 3, 86, 37, 0, 795, 794, 1, 0, 0, 0, 796, 799, 1, 0, 0, 0, 797, 795, 1, 0, 0, 0, 797, 798, 1, 0, 0, 0, 798, 810, 1, 0, 0, 0, 799, 797, 1, 0, 0, 0, 800, 803, 3, 84, 36, 0, 801, 803, 3, 78, 33, 0, 802, 800, 1, 0, 0, 0, 802, 801, 1, 0, 0, 0, 803, 805, 1, 0, 0, 0, 804, 806, 3, 86, 37, 0, 805, 804, 1, 0, 0, 0, 806, 807, 1, 0, 0, 0, 807, 805, 1, 0, 0, 0, 807, 808, 1, 0, 0, 0, 808, 810, 1, 0, 0, 0, 809, 793, 1, 0, 0, 0, 809, 802, 1, 0, 0, 0, 810, 169, 1, 0, 0, 0, 811, 813, 3, 80, 34, 0, 812, 814, 3, 82, 35, 0, 813, 812, 1, 0, 0, 0, 814, 815, 1, 0, 0, 0, 815, 813, 1, 0, 0, 0, 815, 816, 1, 0, 0, 0, 816, 817, 1, 0, 0, 0, 817, 818, 3, 80, 34, 0, 818, 171, 1, 0, 0, 0, 819, 820, 3, 170, 79, 0, 820, 173, 1, 0, 0, 0, 821, 822, 3, 50, 19, 0, 822, 823, 1, 0, 0, 0, 823, 824, 6, 81, 9, 0, 824, 175, 1, 0, 0, 0, 825, 826, 3, 52, 20, 0, 826, 827, 1, 0, 0, 0, 827, 828, 6, 82, 9, 0, 828, 177, 1, 0, 0, 0, 829, 830, 3, 54, 21, 0, 830, 831, 1, 0, 0, 0, 831, 832, 6, 83, 9, 0, 832, 179, 1, 0, 0, 0, 833, 834, 3, 66, 27, 0, 834, 835, 1, 0, 0, 0, 835, 836, 6, 84, 12, 0, 836, 837, 6, 84, 13, 0, 837, 181, 1, 0, 0, 0, 838, 839, 3, 164, 76, 0, 839, 840, 1, 0, 0, 0, 840, 841, 6, 85, 10, 0, 841, 183, 1, 0, 0, 0, 842, 843, 3, 166, 77, 0, 843, 844, 1, 0, 0, 0, 844, 845, 6, 86, 14, 0, 845, 185, 1, 0, 0, 0, 846, 847, 3, 104, 46, 0, 847, 848, 1, 0, 0, 0, 848, 849, 6, 87, 15, 0, 849, 187, 1, 0, 0, 0, 850, 851, 3, 100, 44, 0, 851, 852, 1, 0, 0, 0, 852, 853, 6, 88, 16, 0, 853, 189, 1, 0, 0, 0, 854, 855, 3, 88, 38, 0, 855, 856, 1, 0, 0, 0, 856, 857, 6, 89, 17, 0, 857, 191, 1, 0, 0, 0, 858, 859, 7, 7, 0, 0, 859, 860, 7, 8, 0, 0, 860, 861, 7, 5, 0, 0, 861, 862, 7, 1, 0, 0, 862, 863, 7, 7, 0, 0, 863, 864, 7, 9, 0, 0, 864, 865, 7, 2, 0, 0, 865, 193, 1, 0, 0, 0, 866, 867, 7, 16, 0, 0, 867, 868, 7, 3, 0, 0, 868, 869, 7, 5, 0, 0, 869, 870, 7, 12, 0, 0, 870, 871, 7, 0, 0, 0, 871, 872, 7, 12, 0, 0, 872, 873, 7, 5, 0, 0, 873, 874, 7, 12, 0, 0, 874, 195, 1, 0, 0, 0, 875, 879, 8, 32, 0, 0, 876, 877, 5, 47, 0, 0, 877, 879, 8, 33, 0, 0, 878, 875, 1, 0, 0, 0, 878, 876, 1, 0, 0, 0, 879, 197, 1, 0, 0, 0, 880, 882, 3, 196, 92, 0, 881, 880, 1, 0, 0, 0, 882, 883, 1, 0, 0, 0, 883, 881, 1, 0, 0, 0, 883, 884, 1, 0, 0, 0, 884, 199, 1, 0, 0, 0, 885, 886, 3, 50, 19, 0, 886, 887, 1, 0, 0, 0, 887, 888, 6, 94, 9, 0, 888, 201, 1, 0, 0, 0, 889, 890, 3, 52, 20, 0, 890, 891, 1, 0, 0, 0, 891, 892, 6, 95, 9, 0, 892, 203, 1, 0, 0, 0, 893, 894, 3, 54, 21, 0, 894, 895, 1, 0, 0, 0, 895, 896, 6, 96, 9, 0, 896, 205, 1, 0, 0, 0, 897, 898, 3, 66, 27, 0, 898, 899, 1, 0, 0, 0, 899, 900, 6, 97, 12, 0, 900, 901, 6, 97, 13, 0, 901, 207, 1, 0, 0, 0, 902, 903, 3, 108, 48, 0, 903, 904, 1, 0, 0, 0, 904, 905, 6, 98, 18, 0, 905, 209, 1, 0, 0, 0, 906, 907, 3, 104, 46, 0, 907, 908, 1, 0, 0, 0, 908, 909, 6, 99, 15, 0, 909, 211, 1, 0, 0, 0, 910, 915, 3, 70, 29, 0, 911, 915, 3, 68, 28, 0, 912, 915, 3, 84, 36, 0, 913, 915, 3, 158, 73, 0, 914, 910, 1, 0, 0, 0, 914, 911, 1, 0, 0, 0, 914, 912, 1, 0, 0, 0, 914, 913, 1, 0, 0, 0, 915, 213, 1, 0, 0, 0, 916, 919, 3, 70, 29, 0, 917, 919, 3, 158, 73, 0, 918, 916, 1, 0, 0, 0, 918, 917, 1, 0, 0, 0, 919, 923, 1, 0, 0, 0, 920, 922, 3, 212, 100, 0, 921, 920, 1, 0, 0, 0, 922, 925, 1, 0, 0, 0, 923, 921, 1, 0, 0, 0, 923, 924, 1, 0, 0, 0, 924, 936, 1, 0, 0, 0, 925, 923, 1, 0, 0, 0, 926, 929, 3, 84, 36, 0, 927, 929, 3, 78, 33, 0, 928, 926, 1, 0, 0, 0, 928, 927, 1, 0, 0, 0, 929, 931, 1, 0, 0, 0, 930, 932, 3, 212, 100, 0, 931, 930, 1, 0, 0, 0, 932, 933, 1, 0, 0, 0, 933, 931, 1, 0, 0, 0, 933, 934, 1, 0, 0, 0, 934, 936, 1, 0, 0, 0, 935, 918, 1, 0, 0, 0, 935, 928, 1, 0, 0, 0, 936, 215, 1, 0, 0, 0, 937, 940, 3, 214, 101, 0, 938, 940, 3, 170, 79, 0, 939, 937, 1, 0, 0, 0, 939, 938, 1, 0, 0, 0, 940, 941, 1, 0, 0, 0, 941, 939, 1, 0, 0, 0, 941, 942, 1, 0, 0, 0, 942, 217, 1, 0, 0, 0, 943, 944, 3, 50, 19, 0, 944, 945, 1, 0, 0, 0, 945, 946, 6, 103, 9, 0, 946, 219, 1, 0, 0, 0, 947, 948, 3, 52, 20, 0, 948, 949, 1, 0, 0, 0, 949, 950, 6, 104, 9, 0, 950, 221, 1, 0, 0, 0, 951, 952, 3, 54, 21, 0, 952, 953, 1, 0, 0, 0, 953, 954, 6, 105, 9, 0, 954, 223, 1, 0, 0, 0, 955, 956, 3, 66, 27, 0, 956, 957, 1, 0, 0, 0, 957, 958, 6, 106, 12, 0, 958, 959, 6, 106, 13, 0, 959, 225, 1, 0, 0, 0, 960, 961, 3, 100, 44, 0, 961, 962, 1, 0, 0, 0, 962, 963, 6, 107, 16, 0, 963, 227, 1, 0, 0, 0, 964, 965, 3, 104, 46, 0, 965, 966, 1, 0, 0, 0, 966, 967, 6, 108, 15, 0, 967, 229, 1, 0, 0, 0, 968, 969, 3, 108, 48, 0, 969, 970, 1, 0, 0, 0, 970, 971, 6, 109, 18, 0, 971, 231, 1, 0, 0, 0, 972, 973, 7, 12, 0, 0, 973, 974, 7, 2, 0, 0, 974, 233, 1, 0, 0, 0, 975, 976, 3, 216, 102, 0, 976, 977, 1, 0, 0, 0, 977, 978, 6, 111, 19, 0, 978, 235, 1, 0, 0, 0, 979, 980, 3, 50, 19, 0, 980, 981, 1, 0, 0, 0, 981, 982, 6, 112, 9, 0, 982, 237, 1, 0, 0, 0, 983, 984, 3, 52, 20, 0, 984, 985, 1, 0, 0, 0, 985, 986, 6, 113, 9, 0, 986, 239, 1, 0, 0, 0, 987, 988, 3, 54, 21, 0, 988, 989, 1, 0, 0, 0, 989, 990, 6, 114, 9, 0, 990, 241, 1, 0, 0, 0, 991, 992, 3, 66, 27, 0, 992, 993, 1, 0, 0, 0, 993, 994, 6, 115, 12, 0, 994, 995, 6, 115, 13, 0, 995, 243, 1, 0, 0, 0, 996, 997, 3, 164, 76, 0, 997, 998, 1, 0, 0, 0, 998, 999, 6, 116, 10, 0, 999, 1000, 6, 116, 20, 0, 1000, 245, 1, 0, 0, 0, 1001, 1002, 7, 7, 0, 0, 1002, 1003, 7, 9, 0, 0, 1003, 1004, 1, 0, 0, 0, 1004, 1005, 6, 117, 21, 0, 1005, 247, 1, 0, 0, 0, 1006, 1007, 7, 19, 0, 0, 1007, 1008, 7, 1, 0, 0, 1008, 1009, 7, 5, 0, 0, 1009, 1010, 7, 10, 0, 0, 1010, 1011, 1, 0, 0, 0, 1011, 1012, 6, 118, 21, 0, 1012, 249, 1, 0, 0, 0, 1013, 1014, 8, 34, 0, 0, 1014, 251, 1, 0, 0, 0, 1015, 1017, 3, 250, 119, 0, 1016, 1015, 1, 0, 0, 0, 1017, 1018, 1, 0, 0, 0, 1018, 1016, 1, 0, 0, 0, 1018, 1019, 1, 0, 0, 0, 1019, 1020, 1, 0, 0, 0, 1020, 1021, 3, 320, 154, 0, 1021, 1023, 1, 0, 0, 0, 1022, 1016, 1, 0, 0, 0, 1022, 1023, 1, 0, 0, 0, 1023, 1025, 1, 0, 0, 0, 1024, 1026, 3, 250, 119, 0, 1025, 1024, 1, 0, 0, 0, 1026, 1027, 1, 0, 0, 0, 1027, 1025, 1, 0, 0, 0, 1027, 1028, 1, 0, 0, 0, 1028, 253, 1, 0, 0, 0, 1029, 1030, 3, 172, 80, 0, 1030, 1031, 1, 0, 0, 0, 1031, 1032, 6, 121, 22, 0, 1032, 255, 1, 0, 0, 0, 1033, 1034, 3, 252, 120, 0, 1034, 1035, 1, 0, 0, 0, 1035, 1036, 6, 122, 23, 0, 1036, 257, 1, 0, 0, 0, 1037, 1038, 3, 50, 19, 0, 1038, 1039, 1, 0, 0, 0, 1039, 1040, 6, 123, 9, 0, 1040, 259, 1, 0, 0, 0, 1041, 1042, 3, 52, 20, 0, 1042, 1043, 1, 0, 0, 0, 1043, 1044, 6, 124, 9, 0, 1044, 261, 1, 0, 0, 0, 1045, 1046, 3, 54, 21, 0, 1046, 1047, 1, 0, 0, 0, 1047, 1048, 6, 125, 9, 0, 1048, 263, 1, 0, 0, 0, 1049, 1050, 3, 66, 27, 0, 1050, 1051, 1, 0, 0, 0, 1051, 1052, 6, 126, 12, 0, 1052, 1053, 6, 126, 13, 0, 1053, 1054, 6, 126, 13, 0, 1054, 265, 1, 0, 0, 0, 1055, 1056, 3, 100, 44, 0, 1056, 1057, 1, 0, 0, 0, 1057, 1058, 6, 127, 16, 0, 1058, 267, 1, 0, 0, 0, 1059, 1060, 3, 104, 46, 0, 1060, 1061, 1, 0, 0, 0, 1061, 1062, 6, 128, 15, 0, 1062, 269, 1, 0, 0, 0, 1063, 1064, 3, 108, 48, 0, 1064, 1065, 1, 0, 0, 0, 1065, 1066, 6, 129, 18, 0, 1066, 271, 1, 0, 0, 0, 1067, 1068, 3, 248, 118, 0, 1068, 1069, 1, 0, 0, 0, 1069, 1070, 6, 130, 24, 0, 1070, 273, 1, 0, 0, 0, 1071, 1072, 3, 216, 102, 0, 1072, 1073, 1, 0, 0, 0, 1073, 1074, 6, 131, 19, 0, 1074, 275, 1, 0, 0, 0, 1075, 1076, 3, 172, 80, 0, 1076, 1077, 1, 0, 0, 0, 1077, 1078, 6, 132, 22, 0, 1078, 277, 1, 0, 0, 0, 1079, 1080, 3, 50, 19, 0, 1080, 1081, 1, 0, 0, 0, 1081, 1082, 6, 133, 9, 0, 1082, 279, 1, 0, 0, 0, 1083, 1084, 3, 52, 20, 0, 1084, 1085, 1, 0, 0, 0, 1085, 1086, 6, 134, 9, 0, 1086, 281, 1, 0, 0, 0, 1087, 1088, 3, 54, 21, 0, 1088, 1089, 1, 0, 0, 0, 1089, 1090, 6, 135, 9, 0, 1090, 283, 1, 0, 0, 0, 1091, 1092, 3, 66, 27, 0, 1092, 1093, 1, 0, 0, 0, 1093, 1094, 6, 136, 12, 0, 1094, 1095, 6, 136, 13, 0, 1095, 285, 1, 0, 0, 0, 1096, 1097, 3, 108, 48, 0, 1097, 1098, 1, 0, 0, 0, 1098, 1099, 6, 137, 18, 0, 1099, 287, 1, 0, 0, 0, 1100, 1101, 3, 172, 80, 0, 1101, 1102, 1, 0, 0, 0, 1102, 1103, 6, 138, 22, 0, 1103, 289, 1, 0, 0, 0, 1104, 1105, 3, 168, 78, 0, 1105, 1106, 1, 0, 0, 0, 1106, 1107, 6, 139, 25, 0, 1107, 291, 1, 0, 0, 0, 1108, 1109, 3, 50, 19, 0, 1109, 1110, 1, 0, 0, 0, 1110, 1111, 6, 140, 9, 0, 1111, 293, 1, 0, 0, 0, 1112, 1113, 3, 52, 20, 0, 1113, 1114, 1, 0, 0, 0, 1114, 1115, 6, 141, 9, 0, 1115, 295, 1, 0, 0, 0, 1116, 1117, 3, 54, 21, 0, 1117, 1118, 1, 0, 0, 0, 1118, 1119, 6, 142, 9, 0, 1119, 297, 1, 0, 0, 0, 1120, 1121, 3, 66, 27, 0, 1121, 1122, 1, 0, 0, 0, 1122, 1123, 6, 143, 12, 0, 1123, 1124, 6, 143, 13, 0, 1124, 299, 1, 0, 0, 0, 1125, 1126, 7, 1, 0, 0, 1126, 1127, 7, 9, 0, 0, 1127, 1128, 7, 15, 0, 0, 1128, 1129, 7, 7, 0, 0, 1129, 301, 1, 0, 0, 0, 1130, 1131, 3, 50, 19, 0, 1131, 1132, 1, 0, 0, 0, 1132, 1133, 6, 145, 9, 0, 1133, 303, 1, 0, 0, 0, 1134, 1135, 3, 52, 20, 0, 1135, 1136, 1, 0, 0, 0, 1136, 1137, 6, 146, 9, 0, 1137, 305, 1, 0, 0, 0, 1138, 1139, 3, 54, 21, 0, 1139, 1140, 1, 0, 0, 0, 1140, 1141, 6, 147, 9, 0, 1141, 307, 1, 0, 0, 0, 1142, 1143, 3, 66, 27, 0, 1143, 1144, 1, 0, 0, 0, 1144, 1145, 6, 148, 12, 0, 1145, 1146, 6, 148, 13, 0, 1146, 309, 1, 0, 0, 0, 1147, 1148, 7, 15, 0, 0, 1148, 1149, 7, 31, 0, 0, 1149, 1150, 7, 9, 0, 0, 1150, 1151, 7, 4, 0, 0, 1151, 1152, 7, 5, 0, 0, 1152, 1153, 7, 1, 0, 0, 1153, 1154, 7, 7, 0, 0, 1154, 1155, 7, 9, 0, 0, 1155, 1156, 7, 2, 0, 0, 1156, 311, 1, 0, 0, 0, 1157, 1158, 3, 50, 19, 0, 1158, 1159, 1, 0, 0, 0, 1159, 1160, 6, 150, 9, 0, 1160, 313, 1, 0, 0, 0, 1161, 1162, 3, 52, 20, 0, 1162, 1163, 1, 0, 0, 0, 1163, 1164, 6, 151, 9, 0, 1164, 315, 1, 0, 0, 0, 1165, 1166, 3, 54, 21, 0, 1166, 1167, 1, 0, 0, 0, 1167, 1168, 6, 152, 9, 0, 1168, 317, 1, 0, 0, 0, 1169, 1170, 3, 166, 77, 0, 1170, 1171, 1, 0, 0, 0, 1171, 1172, 6, 153, 14, 0, 1172, 1173, 6, 153, 13, 0, 1173, 319, 1, 0, 0, 0, 1174, 1175, 5, 58, 0, 0, 1175, 321, 1, 0, 0, 0, 1176, 1182, 3, 78, 33, 0, 1177, 1182, 3, 68, 28, 0, 1178, 1182, 3, 108, 48, 0, 1179, 1182, 3, 70, 29, 0, 1180, 1182, 3, 84, 36, 0, 1181, 1176, 1, 0, 0, 0, 1181, 1177, 1, 0, 0, 0, 1181, 1178, 1, 0, 0, 0, 1181, 1179, 1, 0, 0, 0, 1181, 1180, 1, 0, 0, 0, 1182, 1183, 1, 0, 0, 0, 1183, 1181, 1, 0, 0, 0, 1183, 1184, 1, 0, 0, 0, 1184, 323, 1, 0, 0, 0, 1185, 1186, 3, 50, 19, 0, 1186, 1187, 1, 0, 0, 0, 1187, 1188, 6, 156, 9, 0, 1188, 325, 1, 0, 0, 0, 1189, 1190, 3, 52, 20, 0, 1190, 1191, 1, 0, 0, 0, 1191, 1192, 6, 157, 9, 0, 1192, 327, 1, 0, 0, 0, 1193, 1194, 3, 54, 21, 0, 1194, 1195, 1, 0, 0, 0, 1195, 1196, 6, 158, 9, 0, 1196, 329, 1, 0, 0, 0, 58, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 483, 493, 497, 500, 509, 511, 522, 563, 568, 577, 584, 589, 591, 602, 610, 613, 615, 620, 625, 631, 638, 643, 649, 652, 660, 664, 797, 802, 807, 809, 815, 878, 883, 914, 918, 923, 928, 933, 935, 939, 941, 1018, 1022, 1027, 1181, 1183, 26, 5, 2, 0, 5, 4, 0, 5, 6, 0, 5, 1, 0, 5, 3, 0, 5, 10, 0, 5, 8, 0, 5, 5, 0, 5, 9, 0, 0, 1, 0, 7, 65, 0, 5, 0, 0, 7, 26, 0, 4, 0, 0, 7, 66, 0, 7, 35, 0, 7, 33, 0, 7, 27, 0, 7, 37, 0, 7, 78, 0, 5, 11, 0, 5, 7, 0, 7, 68, 0, 7, 88, 0, 7, 87, 0, 7, 67, 0] \ No newline at end of file +[4, 0, 109, 1187, 6, -1, 6, -1, 6, -1, 6, -1, 6, -1, 6, -1, 6, -1, 6, -1, 6, -1, 6, -1, 6, -1, 6, -1, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15, 2, 16, 7, 16, 2, 17, 7, 17, 2, 18, 7, 18, 2, 19, 7, 19, 2, 20, 7, 20, 2, 21, 7, 21, 2, 22, 7, 22, 2, 23, 7, 23, 2, 24, 7, 24, 2, 25, 7, 25, 2, 26, 7, 26, 2, 27, 7, 27, 2, 28, 7, 28, 2, 29, 7, 29, 2, 30, 7, 30, 2, 31, 7, 31, 2, 32, 7, 32, 2, 33, 7, 33, 2, 34, 7, 34, 2, 35, 7, 35, 2, 36, 7, 36, 2, 37, 7, 37, 2, 38, 7, 38, 2, 39, 7, 39, 2, 40, 7, 40, 2, 41, 7, 41, 2, 42, 7, 42, 2, 43, 7, 43, 2, 44, 7, 44, 2, 45, 7, 45, 2, 46, 7, 46, 2, 47, 7, 47, 2, 48, 7, 48, 2, 49, 7, 49, 2, 50, 7, 50, 2, 51, 7, 51, 2, 52, 7, 52, 2, 53, 7, 53, 2, 54, 7, 54, 2, 55, 7, 55, 2, 56, 7, 56, 2, 57, 7, 57, 2, 58, 7, 58, 2, 59, 7, 59, 2, 60, 7, 60, 2, 61, 7, 61, 2, 62, 7, 62, 2, 63, 7, 63, 2, 64, 7, 64, 2, 65, 7, 65, 2, 66, 7, 66, 2, 67, 7, 67, 2, 68, 7, 68, 2, 69, 7, 69, 2, 70, 7, 70, 2, 71, 7, 71, 2, 72, 7, 72, 2, 73, 7, 73, 2, 74, 7, 74, 2, 75, 7, 75, 2, 76, 7, 76, 2, 77, 7, 77, 2, 78, 7, 78, 2, 79, 7, 79, 2, 80, 7, 80, 2, 81, 7, 81, 2, 82, 7, 82, 2, 83, 7, 83, 2, 84, 7, 84, 2, 85, 7, 85, 2, 86, 7, 86, 2, 87, 7, 87, 2, 88, 7, 88, 2, 89, 7, 89, 2, 90, 7, 90, 2, 91, 7, 91, 2, 92, 7, 92, 2, 93, 7, 93, 2, 94, 7, 94, 2, 95, 7, 95, 2, 96, 7, 96, 2, 97, 7, 97, 2, 98, 7, 98, 2, 99, 7, 99, 2, 100, 7, 100, 2, 101, 7, 101, 2, 102, 7, 102, 2, 103, 7, 103, 2, 104, 7, 104, 2, 105, 7, 105, 2, 106, 7, 106, 2, 107, 7, 107, 2, 108, 7, 108, 2, 109, 7, 109, 2, 110, 7, 110, 2, 111, 7, 111, 2, 112, 7, 112, 2, 113, 7, 113, 2, 114, 7, 114, 2, 115, 7, 115, 2, 116, 7, 116, 2, 117, 7, 117, 2, 118, 7, 118, 2, 119, 7, 119, 2, 120, 7, 120, 2, 121, 7, 121, 2, 122, 7, 122, 2, 123, 7, 123, 2, 124, 7, 124, 2, 125, 7, 125, 2, 126, 7, 126, 2, 127, 7, 127, 2, 128, 7, 128, 2, 129, 7, 129, 2, 130, 7, 130, 2, 131, 7, 131, 2, 132, 7, 132, 2, 133, 7, 133, 2, 134, 7, 134, 2, 135, 7, 135, 2, 136, 7, 136, 2, 137, 7, 137, 2, 138, 7, 138, 2, 139, 7, 139, 2, 140, 7, 140, 2, 141, 7, 141, 2, 142, 7, 142, 2, 143, 7, 143, 2, 144, 7, 144, 2, 145, 7, 145, 2, 146, 7, 146, 2, 147, 7, 147, 2, 148, 7, 148, 2, 149, 7, 149, 2, 150, 7, 150, 2, 151, 7, 151, 2, 152, 7, 152, 2, 153, 7, 153, 2, 154, 7, 154, 2, 155, 7, 155, 2, 156, 7, 156, 2, 157, 7, 157, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 4, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 1, 18, 4, 18, 480, 8, 18, 11, 18, 12, 18, 481, 1, 18, 1, 18, 1, 19, 1, 19, 1, 19, 1, 19, 5, 19, 490, 8, 19, 10, 19, 12, 19, 493, 9, 19, 1, 19, 3, 19, 496, 8, 19, 1, 19, 3, 19, 499, 8, 19, 1, 19, 1, 19, 1, 20, 1, 20, 1, 20, 1, 20, 1, 20, 5, 20, 508, 8, 20, 10, 20, 12, 20, 511, 9, 20, 1, 20, 1, 20, 1, 20, 1, 20, 1, 20, 1, 21, 4, 21, 519, 8, 21, 11, 21, 12, 21, 520, 1, 21, 1, 21, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 23, 1, 23, 1, 23, 1, 23, 1, 23, 1, 24, 1, 24, 1, 24, 1, 24, 1, 25, 1, 25, 1, 25, 1, 25, 1, 26, 1, 26, 1, 26, 1, 26, 1, 27, 1, 27, 1, 27, 1, 27, 1, 28, 1, 28, 1, 29, 1, 29, 1, 30, 1, 30, 1, 30, 1, 31, 1, 31, 1, 32, 1, 32, 3, 32, 562, 8, 32, 1, 32, 4, 32, 565, 8, 32, 11, 32, 12, 32, 566, 1, 33, 1, 33, 1, 34, 1, 34, 1, 35, 1, 35, 1, 35, 3, 35, 576, 8, 35, 1, 36, 1, 36, 1, 37, 1, 37, 1, 37, 3, 37, 583, 8, 37, 1, 38, 1, 38, 1, 38, 5, 38, 588, 8, 38, 10, 38, 12, 38, 591, 9, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 5, 38, 599, 8, 38, 10, 38, 12, 38, 602, 9, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 3, 38, 609, 8, 38, 1, 38, 3, 38, 612, 8, 38, 3, 38, 614, 8, 38, 1, 39, 4, 39, 617, 8, 39, 11, 39, 12, 39, 618, 1, 40, 4, 40, 622, 8, 40, 11, 40, 12, 40, 623, 1, 40, 1, 40, 5, 40, 628, 8, 40, 10, 40, 12, 40, 631, 9, 40, 1, 40, 1, 40, 4, 40, 635, 8, 40, 11, 40, 12, 40, 636, 1, 40, 4, 40, 640, 8, 40, 11, 40, 12, 40, 641, 1, 40, 1, 40, 5, 40, 646, 8, 40, 10, 40, 12, 40, 649, 9, 40, 3, 40, 651, 8, 40, 1, 40, 1, 40, 1, 40, 1, 40, 4, 40, 657, 8, 40, 11, 40, 12, 40, 658, 1, 40, 1, 40, 3, 40, 663, 8, 40, 1, 41, 1, 41, 1, 41, 1, 42, 1, 42, 1, 42, 1, 42, 1, 43, 1, 43, 1, 43, 1, 43, 1, 44, 1, 44, 1, 45, 1, 45, 1, 45, 1, 46, 1, 46, 1, 47, 1, 47, 1, 47, 1, 47, 1, 47, 1, 48, 1, 48, 1, 49, 1, 49, 1, 49, 1, 49, 1, 49, 1, 49, 1, 50, 1, 50, 1, 50, 1, 50, 1, 50, 1, 50, 1, 51, 1, 51, 1, 51, 1, 51, 1, 51, 1, 52, 1, 52, 1, 53, 1, 53, 1, 53, 1, 54, 1, 54, 1, 54, 1, 55, 1, 55, 1, 55, 1, 55, 1, 55, 1, 56, 1, 56, 1, 56, 1, 56, 1, 57, 1, 57, 1, 57, 1, 57, 1, 57, 1, 58, 1, 58, 1, 58, 1, 58, 1, 58, 1, 58, 1, 59, 1, 59, 1, 59, 1, 60, 1, 60, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 62, 1, 62, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 64, 1, 64, 1, 64, 1, 65, 1, 65, 1, 65, 1, 66, 1, 66, 1, 66, 1, 67, 1, 67, 1, 68, 1, 68, 1, 68, 1, 69, 1, 69, 1, 70, 1, 70, 1, 70, 1, 71, 1, 71, 1, 72, 1, 72, 1, 73, 1, 73, 1, 74, 1, 74, 1, 75, 1, 75, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 77, 1, 77, 1, 77, 1, 77, 1, 77, 1, 78, 1, 78, 5, 78, 794, 8, 78, 10, 78, 12, 78, 797, 9, 78, 1, 78, 1, 78, 3, 78, 801, 8, 78, 1, 78, 4, 78, 804, 8, 78, 11, 78, 12, 78, 805, 3, 78, 808, 8, 78, 1, 79, 1, 79, 4, 79, 812, 8, 79, 11, 79, 12, 79, 813, 1, 79, 1, 79, 1, 80, 1, 80, 1, 81, 1, 81, 1, 81, 1, 81, 1, 82, 1, 82, 1, 82, 1, 82, 1, 83, 1, 83, 1, 83, 1, 83, 1, 84, 1, 84, 1, 84, 1, 84, 1, 84, 1, 85, 1, 85, 1, 85, 1, 85, 1, 86, 1, 86, 1, 86, 1, 86, 1, 87, 1, 87, 1, 87, 1, 87, 1, 88, 1, 88, 1, 88, 1, 88, 1, 89, 1, 89, 1, 89, 1, 89, 1, 90, 1, 90, 1, 90, 1, 90, 1, 90, 1, 90, 1, 90, 1, 90, 1, 90, 1, 91, 1, 91, 1, 91, 3, 91, 869, 8, 91, 1, 92, 4, 92, 872, 8, 92, 11, 92, 12, 92, 873, 1, 93, 1, 93, 1, 93, 1, 93, 1, 94, 1, 94, 1, 94, 1, 94, 1, 95, 1, 95, 1, 95, 1, 95, 1, 96, 1, 96, 1, 96, 1, 96, 1, 96, 1, 97, 1, 97, 1, 97, 1, 97, 1, 98, 1, 98, 1, 98, 1, 98, 1, 99, 1, 99, 1, 99, 1, 99, 3, 99, 905, 8, 99, 1, 100, 1, 100, 3, 100, 909, 8, 100, 1, 100, 5, 100, 912, 8, 100, 10, 100, 12, 100, 915, 9, 100, 1, 100, 1, 100, 3, 100, 919, 8, 100, 1, 100, 4, 100, 922, 8, 100, 11, 100, 12, 100, 923, 3, 100, 926, 8, 100, 1, 101, 1, 101, 4, 101, 930, 8, 101, 11, 101, 12, 101, 931, 1, 102, 1, 102, 1, 102, 1, 102, 1, 103, 1, 103, 1, 103, 1, 103, 1, 104, 1, 104, 1, 104, 1, 104, 1, 105, 1, 105, 1, 105, 1, 105, 1, 105, 1, 106, 1, 106, 1, 106, 1, 106, 1, 107, 1, 107, 1, 107, 1, 107, 1, 108, 1, 108, 1, 108, 1, 108, 1, 109, 1, 109, 1, 109, 1, 110, 1, 110, 1, 110, 1, 110, 1, 111, 1, 111, 1, 111, 1, 111, 1, 112, 1, 112, 1, 112, 1, 112, 1, 113, 1, 113, 1, 113, 1, 113, 1, 114, 1, 114, 1, 114, 1, 114, 1, 114, 1, 115, 1, 115, 1, 115, 1, 115, 1, 115, 1, 116, 1, 116, 1, 116, 1, 116, 1, 116, 1, 117, 1, 117, 1, 117, 1, 117, 1, 117, 1, 117, 1, 117, 1, 118, 1, 118, 1, 119, 4, 119, 1007, 8, 119, 11, 119, 12, 119, 1008, 1, 119, 1, 119, 3, 119, 1013, 8, 119, 1, 119, 4, 119, 1016, 8, 119, 11, 119, 12, 119, 1017, 1, 120, 1, 120, 1, 120, 1, 120, 1, 121, 1, 121, 1, 121, 1, 121, 1, 122, 1, 122, 1, 122, 1, 122, 1, 123, 1, 123, 1, 123, 1, 123, 1, 124, 1, 124, 1, 124, 1, 124, 1, 125, 1, 125, 1, 125, 1, 125, 1, 125, 1, 125, 1, 126, 1, 126, 1, 126, 1, 126, 1, 127, 1, 127, 1, 127, 1, 127, 1, 128, 1, 128, 1, 128, 1, 128, 1, 129, 1, 129, 1, 129, 1, 129, 1, 130, 1, 130, 1, 130, 1, 130, 1, 131, 1, 131, 1, 131, 1, 131, 1, 132, 1, 132, 1, 132, 1, 132, 1, 133, 1, 133, 1, 133, 1, 133, 1, 134, 1, 134, 1, 134, 1, 134, 1, 135, 1, 135, 1, 135, 1, 135, 1, 135, 1, 136, 1, 136, 1, 136, 1, 136, 1, 137, 1, 137, 1, 137, 1, 137, 1, 138, 1, 138, 1, 138, 1, 138, 1, 139, 1, 139, 1, 139, 1, 139, 1, 140, 1, 140, 1, 140, 1, 140, 1, 141, 1, 141, 1, 141, 1, 141, 1, 142, 1, 142, 1, 142, 1, 142, 1, 142, 1, 143, 1, 143, 1, 143, 1, 143, 1, 143, 1, 144, 1, 144, 1, 144, 1, 144, 1, 145, 1, 145, 1, 145, 1, 145, 1, 146, 1, 146, 1, 146, 1, 146, 1, 147, 1, 147, 1, 147, 1, 147, 1, 147, 1, 148, 1, 148, 1, 148, 1, 148, 1, 148, 1, 148, 1, 148, 1, 148, 1, 148, 1, 148, 1, 149, 1, 149, 1, 149, 1, 149, 1, 150, 1, 150, 1, 150, 1, 150, 1, 151, 1, 151, 1, 151, 1, 151, 1, 152, 1, 152, 1, 152, 1, 152, 1, 152, 1, 153, 1, 153, 1, 154, 1, 154, 1, 154, 1, 154, 1, 154, 4, 154, 1172, 8, 154, 11, 154, 12, 154, 1173, 1, 155, 1, 155, 1, 155, 1, 155, 1, 156, 1, 156, 1, 156, 1, 156, 1, 157, 1, 157, 1, 157, 1, 157, 2, 509, 600, 0, 158, 12, 1, 14, 2, 16, 3, 18, 4, 20, 5, 22, 6, 24, 7, 26, 8, 28, 9, 30, 10, 32, 11, 34, 12, 36, 13, 38, 14, 40, 15, 42, 16, 44, 17, 46, 18, 48, 19, 50, 20, 52, 21, 54, 22, 56, 0, 58, 0, 60, 23, 62, 24, 64, 25, 66, 26, 68, 0, 70, 0, 72, 0, 74, 0, 76, 0, 78, 0, 80, 0, 82, 0, 84, 0, 86, 0, 88, 27, 90, 28, 92, 29, 94, 30, 96, 31, 98, 32, 100, 33, 102, 34, 104, 35, 106, 36, 108, 37, 110, 38, 112, 39, 114, 40, 116, 41, 118, 42, 120, 43, 122, 44, 124, 45, 126, 46, 128, 47, 130, 48, 132, 49, 134, 50, 136, 51, 138, 52, 140, 53, 142, 54, 144, 55, 146, 56, 148, 57, 150, 58, 152, 59, 154, 60, 156, 61, 158, 62, 160, 63, 162, 64, 164, 65, 166, 66, 168, 67, 170, 0, 172, 68, 174, 69, 176, 70, 178, 71, 180, 0, 182, 0, 184, 0, 186, 0, 188, 0, 190, 0, 192, 72, 194, 0, 196, 73, 198, 74, 200, 75, 202, 76, 204, 0, 206, 0, 208, 0, 210, 0, 212, 0, 214, 77, 216, 78, 218, 79, 220, 80, 222, 0, 224, 0, 226, 0, 228, 0, 230, 81, 232, 0, 234, 82, 236, 83, 238, 84, 240, 0, 242, 0, 244, 85, 246, 86, 248, 0, 250, 87, 252, 0, 254, 0, 256, 88, 258, 89, 260, 90, 262, 0, 264, 0, 266, 0, 268, 0, 270, 0, 272, 0, 274, 0, 276, 91, 278, 92, 280, 93, 282, 0, 284, 0, 286, 0, 288, 0, 290, 94, 292, 95, 294, 96, 296, 0, 298, 97, 300, 98, 302, 99, 304, 100, 306, 0, 308, 101, 310, 102, 312, 103, 314, 104, 316, 0, 318, 105, 320, 106, 322, 107, 324, 108, 326, 109, 12, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 35, 2, 0, 68, 68, 100, 100, 2, 0, 73, 73, 105, 105, 2, 0, 83, 83, 115, 115, 2, 0, 69, 69, 101, 101, 2, 0, 67, 67, 99, 99, 2, 0, 84, 84, 116, 116, 2, 0, 82, 82, 114, 114, 2, 0, 79, 79, 111, 111, 2, 0, 80, 80, 112, 112, 2, 0, 78, 78, 110, 110, 2, 0, 72, 72, 104, 104, 2, 0, 86, 86, 118, 118, 2, 0, 65, 65, 97, 97, 2, 0, 76, 76, 108, 108, 2, 0, 88, 88, 120, 120, 2, 0, 70, 70, 102, 102, 2, 0, 77, 77, 109, 109, 2, 0, 71, 71, 103, 103, 2, 0, 75, 75, 107, 107, 2, 0, 87, 87, 119, 119, 6, 0, 9, 10, 13, 13, 32, 32, 47, 47, 91, 91, 93, 93, 2, 0, 10, 10, 13, 13, 3, 0, 9, 10, 13, 13, 32, 32, 1, 0, 48, 57, 2, 0, 65, 90, 97, 122, 8, 0, 34, 34, 78, 78, 82, 82, 84, 84, 92, 92, 110, 110, 114, 114, 116, 116, 4, 0, 10, 10, 13, 13, 34, 34, 92, 92, 2, 0, 43, 43, 45, 45, 1, 0, 96, 96, 2, 0, 66, 66, 98, 98, 2, 0, 89, 89, 121, 121, 2, 0, 85, 85, 117, 117, 10, 0, 9, 10, 13, 13, 32, 32, 44, 44, 47, 47, 61, 61, 91, 91, 93, 93, 96, 96, 124, 124, 2, 0, 42, 42, 47, 47, 11, 0, 9, 10, 13, 13, 32, 32, 34, 35, 44, 44, 47, 47, 58, 58, 60, 60, 62, 63, 92, 92, 124, 124, 1214, 0, 12, 1, 0, 0, 0, 0, 14, 1, 0, 0, 0, 0, 16, 1, 0, 0, 0, 0, 18, 1, 0, 0, 0, 0, 20, 1, 0, 0, 0, 0, 22, 1, 0, 0, 0, 0, 24, 1, 0, 0, 0, 0, 26, 1, 0, 0, 0, 0, 28, 1, 0, 0, 0, 0, 30, 1, 0, 0, 0, 0, 32, 1, 0, 0, 0, 0, 34, 1, 0, 0, 0, 0, 36, 1, 0, 0, 0, 0, 38, 1, 0, 0, 0, 0, 40, 1, 0, 0, 0, 0, 42, 1, 0, 0, 0, 0, 44, 1, 0, 0, 0, 0, 46, 1, 0, 0, 0, 0, 48, 1, 0, 0, 0, 0, 50, 1, 0, 0, 0, 0, 52, 1, 0, 0, 0, 0, 54, 1, 0, 0, 0, 1, 56, 1, 0, 0, 0, 1, 58, 1, 0, 0, 0, 1, 60, 1, 0, 0, 0, 1, 62, 1, 0, 0, 0, 1, 64, 1, 0, 0, 0, 2, 66, 1, 0, 0, 0, 2, 88, 1, 0, 0, 0, 2, 90, 1, 0, 0, 0, 2, 92, 1, 0, 0, 0, 2, 94, 1, 0, 0, 0, 2, 96, 1, 0, 0, 0, 2, 98, 1, 0, 0, 0, 2, 100, 1, 0, 0, 0, 2, 102, 1, 0, 0, 0, 2, 104, 1, 0, 0, 0, 2, 106, 1, 0, 0, 0, 2, 108, 1, 0, 0, 0, 2, 110, 1, 0, 0, 0, 2, 112, 1, 0, 0, 0, 2, 114, 1, 0, 0, 0, 2, 116, 1, 0, 0, 0, 2, 118, 1, 0, 0, 0, 2, 120, 1, 0, 0, 0, 2, 122, 1, 0, 0, 0, 2, 124, 1, 0, 0, 0, 2, 126, 1, 0, 0, 0, 2, 128, 1, 0, 0, 0, 2, 130, 1, 0, 0, 0, 2, 132, 1, 0, 0, 0, 2, 134, 1, 0, 0, 0, 2, 136, 1, 0, 0, 0, 2, 138, 1, 0, 0, 0, 2, 140, 1, 0, 0, 0, 2, 142, 1, 0, 0, 0, 2, 144, 1, 0, 0, 0, 2, 146, 1, 0, 0, 0, 2, 148, 1, 0, 0, 0, 2, 150, 1, 0, 0, 0, 2, 152, 1, 0, 0, 0, 2, 154, 1, 0, 0, 0, 2, 156, 1, 0, 0, 0, 2, 158, 1, 0, 0, 0, 2, 160, 1, 0, 0, 0, 2, 162, 1, 0, 0, 0, 2, 164, 1, 0, 0, 0, 2, 166, 1, 0, 0, 0, 2, 168, 1, 0, 0, 0, 2, 172, 1, 0, 0, 0, 2, 174, 1, 0, 0, 0, 2, 176, 1, 0, 0, 0, 2, 178, 1, 0, 0, 0, 3, 180, 1, 0, 0, 0, 3, 182, 1, 0, 0, 0, 3, 184, 1, 0, 0, 0, 3, 186, 1, 0, 0, 0, 3, 188, 1, 0, 0, 0, 3, 190, 1, 0, 0, 0, 3, 192, 1, 0, 0, 0, 3, 196, 1, 0, 0, 0, 3, 198, 1, 0, 0, 0, 3, 200, 1, 0, 0, 0, 3, 202, 1, 0, 0, 0, 4, 204, 1, 0, 0, 0, 4, 206, 1, 0, 0, 0, 4, 208, 1, 0, 0, 0, 4, 214, 1, 0, 0, 0, 4, 216, 1, 0, 0, 0, 4, 218, 1, 0, 0, 0, 4, 220, 1, 0, 0, 0, 5, 222, 1, 0, 0, 0, 5, 224, 1, 0, 0, 0, 5, 226, 1, 0, 0, 0, 5, 228, 1, 0, 0, 0, 5, 230, 1, 0, 0, 0, 5, 232, 1, 0, 0, 0, 5, 234, 1, 0, 0, 0, 5, 236, 1, 0, 0, 0, 5, 238, 1, 0, 0, 0, 6, 240, 1, 0, 0, 0, 6, 242, 1, 0, 0, 0, 6, 244, 1, 0, 0, 0, 6, 246, 1, 0, 0, 0, 6, 250, 1, 0, 0, 0, 6, 252, 1, 0, 0, 0, 6, 254, 1, 0, 0, 0, 6, 256, 1, 0, 0, 0, 6, 258, 1, 0, 0, 0, 6, 260, 1, 0, 0, 0, 7, 262, 1, 0, 0, 0, 7, 264, 1, 0, 0, 0, 7, 266, 1, 0, 0, 0, 7, 268, 1, 0, 0, 0, 7, 270, 1, 0, 0, 0, 7, 272, 1, 0, 0, 0, 7, 274, 1, 0, 0, 0, 7, 276, 1, 0, 0, 0, 7, 278, 1, 0, 0, 0, 7, 280, 1, 0, 0, 0, 8, 282, 1, 0, 0, 0, 8, 284, 1, 0, 0, 0, 8, 286, 1, 0, 0, 0, 8, 288, 1, 0, 0, 0, 8, 290, 1, 0, 0, 0, 8, 292, 1, 0, 0, 0, 8, 294, 1, 0, 0, 0, 9, 296, 1, 0, 0, 0, 9, 298, 1, 0, 0, 0, 9, 300, 1, 0, 0, 0, 9, 302, 1, 0, 0, 0, 9, 304, 1, 0, 0, 0, 10, 306, 1, 0, 0, 0, 10, 308, 1, 0, 0, 0, 10, 310, 1, 0, 0, 0, 10, 312, 1, 0, 0, 0, 10, 314, 1, 0, 0, 0, 11, 316, 1, 0, 0, 0, 11, 318, 1, 0, 0, 0, 11, 320, 1, 0, 0, 0, 11, 322, 1, 0, 0, 0, 11, 324, 1, 0, 0, 0, 11, 326, 1, 0, 0, 0, 12, 328, 1, 0, 0, 0, 14, 338, 1, 0, 0, 0, 16, 345, 1, 0, 0, 0, 18, 354, 1, 0, 0, 0, 20, 361, 1, 0, 0, 0, 22, 371, 1, 0, 0, 0, 24, 378, 1, 0, 0, 0, 26, 385, 1, 0, 0, 0, 28, 399, 1, 0, 0, 0, 30, 406, 1, 0, 0, 0, 32, 414, 1, 0, 0, 0, 34, 421, 1, 0, 0, 0, 36, 433, 1, 0, 0, 0, 38, 442, 1, 0, 0, 0, 40, 448, 1, 0, 0, 0, 42, 455, 1, 0, 0, 0, 44, 462, 1, 0, 0, 0, 46, 470, 1, 0, 0, 0, 48, 479, 1, 0, 0, 0, 50, 485, 1, 0, 0, 0, 52, 502, 1, 0, 0, 0, 54, 518, 1, 0, 0, 0, 56, 524, 1, 0, 0, 0, 58, 529, 1, 0, 0, 0, 60, 534, 1, 0, 0, 0, 62, 538, 1, 0, 0, 0, 64, 542, 1, 0, 0, 0, 66, 546, 1, 0, 0, 0, 68, 550, 1, 0, 0, 0, 70, 552, 1, 0, 0, 0, 72, 554, 1, 0, 0, 0, 74, 557, 1, 0, 0, 0, 76, 559, 1, 0, 0, 0, 78, 568, 1, 0, 0, 0, 80, 570, 1, 0, 0, 0, 82, 575, 1, 0, 0, 0, 84, 577, 1, 0, 0, 0, 86, 582, 1, 0, 0, 0, 88, 613, 1, 0, 0, 0, 90, 616, 1, 0, 0, 0, 92, 662, 1, 0, 0, 0, 94, 664, 1, 0, 0, 0, 96, 667, 1, 0, 0, 0, 98, 671, 1, 0, 0, 0, 100, 675, 1, 0, 0, 0, 102, 677, 1, 0, 0, 0, 104, 680, 1, 0, 0, 0, 106, 682, 1, 0, 0, 0, 108, 687, 1, 0, 0, 0, 110, 689, 1, 0, 0, 0, 112, 695, 1, 0, 0, 0, 114, 701, 1, 0, 0, 0, 116, 706, 1, 0, 0, 0, 118, 708, 1, 0, 0, 0, 120, 711, 1, 0, 0, 0, 122, 714, 1, 0, 0, 0, 124, 719, 1, 0, 0, 0, 126, 723, 1, 0, 0, 0, 128, 728, 1, 0, 0, 0, 130, 734, 1, 0, 0, 0, 132, 737, 1, 0, 0, 0, 134, 739, 1, 0, 0, 0, 136, 745, 1, 0, 0, 0, 138, 747, 1, 0, 0, 0, 140, 752, 1, 0, 0, 0, 142, 755, 1, 0, 0, 0, 144, 758, 1, 0, 0, 0, 146, 761, 1, 0, 0, 0, 148, 763, 1, 0, 0, 0, 150, 766, 1, 0, 0, 0, 152, 768, 1, 0, 0, 0, 154, 771, 1, 0, 0, 0, 156, 773, 1, 0, 0, 0, 158, 775, 1, 0, 0, 0, 160, 777, 1, 0, 0, 0, 162, 779, 1, 0, 0, 0, 164, 781, 1, 0, 0, 0, 166, 786, 1, 0, 0, 0, 168, 807, 1, 0, 0, 0, 170, 809, 1, 0, 0, 0, 172, 817, 1, 0, 0, 0, 174, 819, 1, 0, 0, 0, 176, 823, 1, 0, 0, 0, 178, 827, 1, 0, 0, 0, 180, 831, 1, 0, 0, 0, 182, 836, 1, 0, 0, 0, 184, 840, 1, 0, 0, 0, 186, 844, 1, 0, 0, 0, 188, 848, 1, 0, 0, 0, 190, 852, 1, 0, 0, 0, 192, 856, 1, 0, 0, 0, 194, 868, 1, 0, 0, 0, 196, 871, 1, 0, 0, 0, 198, 875, 1, 0, 0, 0, 200, 879, 1, 0, 0, 0, 202, 883, 1, 0, 0, 0, 204, 887, 1, 0, 0, 0, 206, 892, 1, 0, 0, 0, 208, 896, 1, 0, 0, 0, 210, 904, 1, 0, 0, 0, 212, 925, 1, 0, 0, 0, 214, 929, 1, 0, 0, 0, 216, 933, 1, 0, 0, 0, 218, 937, 1, 0, 0, 0, 220, 941, 1, 0, 0, 0, 222, 945, 1, 0, 0, 0, 224, 950, 1, 0, 0, 0, 226, 954, 1, 0, 0, 0, 228, 958, 1, 0, 0, 0, 230, 962, 1, 0, 0, 0, 232, 965, 1, 0, 0, 0, 234, 969, 1, 0, 0, 0, 236, 973, 1, 0, 0, 0, 238, 977, 1, 0, 0, 0, 240, 981, 1, 0, 0, 0, 242, 986, 1, 0, 0, 0, 244, 991, 1, 0, 0, 0, 246, 996, 1, 0, 0, 0, 248, 1003, 1, 0, 0, 0, 250, 1012, 1, 0, 0, 0, 252, 1019, 1, 0, 0, 0, 254, 1023, 1, 0, 0, 0, 256, 1027, 1, 0, 0, 0, 258, 1031, 1, 0, 0, 0, 260, 1035, 1, 0, 0, 0, 262, 1039, 1, 0, 0, 0, 264, 1045, 1, 0, 0, 0, 266, 1049, 1, 0, 0, 0, 268, 1053, 1, 0, 0, 0, 270, 1057, 1, 0, 0, 0, 272, 1061, 1, 0, 0, 0, 274, 1065, 1, 0, 0, 0, 276, 1069, 1, 0, 0, 0, 278, 1073, 1, 0, 0, 0, 280, 1077, 1, 0, 0, 0, 282, 1081, 1, 0, 0, 0, 284, 1086, 1, 0, 0, 0, 286, 1090, 1, 0, 0, 0, 288, 1094, 1, 0, 0, 0, 290, 1098, 1, 0, 0, 0, 292, 1102, 1, 0, 0, 0, 294, 1106, 1, 0, 0, 0, 296, 1110, 1, 0, 0, 0, 298, 1115, 1, 0, 0, 0, 300, 1120, 1, 0, 0, 0, 302, 1124, 1, 0, 0, 0, 304, 1128, 1, 0, 0, 0, 306, 1132, 1, 0, 0, 0, 308, 1137, 1, 0, 0, 0, 310, 1147, 1, 0, 0, 0, 312, 1151, 1, 0, 0, 0, 314, 1155, 1, 0, 0, 0, 316, 1159, 1, 0, 0, 0, 318, 1164, 1, 0, 0, 0, 320, 1171, 1, 0, 0, 0, 322, 1175, 1, 0, 0, 0, 324, 1179, 1, 0, 0, 0, 326, 1183, 1, 0, 0, 0, 328, 329, 7, 0, 0, 0, 329, 330, 7, 1, 0, 0, 330, 331, 7, 2, 0, 0, 331, 332, 7, 2, 0, 0, 332, 333, 7, 3, 0, 0, 333, 334, 7, 4, 0, 0, 334, 335, 7, 5, 0, 0, 335, 336, 1, 0, 0, 0, 336, 337, 6, 0, 0, 0, 337, 13, 1, 0, 0, 0, 338, 339, 7, 0, 0, 0, 339, 340, 7, 6, 0, 0, 340, 341, 7, 7, 0, 0, 341, 342, 7, 8, 0, 0, 342, 343, 1, 0, 0, 0, 343, 344, 6, 1, 1, 0, 344, 15, 1, 0, 0, 0, 345, 346, 7, 3, 0, 0, 346, 347, 7, 9, 0, 0, 347, 348, 7, 6, 0, 0, 348, 349, 7, 1, 0, 0, 349, 350, 7, 4, 0, 0, 350, 351, 7, 10, 0, 0, 351, 352, 1, 0, 0, 0, 352, 353, 6, 2, 2, 0, 353, 17, 1, 0, 0, 0, 354, 355, 7, 3, 0, 0, 355, 356, 7, 11, 0, 0, 356, 357, 7, 12, 0, 0, 357, 358, 7, 13, 0, 0, 358, 359, 1, 0, 0, 0, 359, 360, 6, 3, 0, 0, 360, 19, 1, 0, 0, 0, 361, 362, 7, 3, 0, 0, 362, 363, 7, 14, 0, 0, 363, 364, 7, 8, 0, 0, 364, 365, 7, 13, 0, 0, 365, 366, 7, 12, 0, 0, 366, 367, 7, 1, 0, 0, 367, 368, 7, 9, 0, 0, 368, 369, 1, 0, 0, 0, 369, 370, 6, 4, 3, 0, 370, 21, 1, 0, 0, 0, 371, 372, 7, 15, 0, 0, 372, 373, 7, 6, 0, 0, 373, 374, 7, 7, 0, 0, 374, 375, 7, 16, 0, 0, 375, 376, 1, 0, 0, 0, 376, 377, 6, 5, 4, 0, 377, 23, 1, 0, 0, 0, 378, 379, 7, 17, 0, 0, 379, 380, 7, 6, 0, 0, 380, 381, 7, 7, 0, 0, 381, 382, 7, 18, 0, 0, 382, 383, 1, 0, 0, 0, 383, 384, 6, 6, 0, 0, 384, 25, 1, 0, 0, 0, 385, 386, 7, 1, 0, 0, 386, 387, 7, 9, 0, 0, 387, 388, 7, 13, 0, 0, 388, 389, 7, 1, 0, 0, 389, 390, 7, 9, 0, 0, 390, 391, 7, 3, 0, 0, 391, 392, 7, 2, 0, 0, 392, 393, 7, 5, 0, 0, 393, 394, 7, 12, 0, 0, 394, 395, 7, 5, 0, 0, 395, 396, 7, 2, 0, 0, 396, 397, 1, 0, 0, 0, 397, 398, 6, 7, 0, 0, 398, 27, 1, 0, 0, 0, 399, 400, 7, 18, 0, 0, 400, 401, 7, 3, 0, 0, 401, 402, 7, 3, 0, 0, 402, 403, 7, 8, 0, 0, 403, 404, 1, 0, 0, 0, 404, 405, 6, 8, 1, 0, 405, 29, 1, 0, 0, 0, 406, 407, 7, 13, 0, 0, 407, 408, 7, 1, 0, 0, 408, 409, 7, 16, 0, 0, 409, 410, 7, 1, 0, 0, 410, 411, 7, 5, 0, 0, 411, 412, 1, 0, 0, 0, 412, 413, 6, 9, 0, 0, 413, 31, 1, 0, 0, 0, 414, 415, 7, 16, 0, 0, 415, 416, 7, 3, 0, 0, 416, 417, 7, 5, 0, 0, 417, 418, 7, 12, 0, 0, 418, 419, 1, 0, 0, 0, 419, 420, 6, 10, 5, 0, 420, 33, 1, 0, 0, 0, 421, 422, 7, 16, 0, 0, 422, 423, 7, 11, 0, 0, 423, 424, 5, 95, 0, 0, 424, 425, 7, 3, 0, 0, 425, 426, 7, 14, 0, 0, 426, 427, 7, 8, 0, 0, 427, 428, 7, 12, 0, 0, 428, 429, 7, 9, 0, 0, 429, 430, 7, 0, 0, 0, 430, 431, 1, 0, 0, 0, 431, 432, 6, 11, 6, 0, 432, 35, 1, 0, 0, 0, 433, 434, 7, 6, 0, 0, 434, 435, 7, 3, 0, 0, 435, 436, 7, 9, 0, 0, 436, 437, 7, 12, 0, 0, 437, 438, 7, 16, 0, 0, 438, 439, 7, 3, 0, 0, 439, 440, 1, 0, 0, 0, 440, 441, 6, 12, 7, 0, 441, 37, 1, 0, 0, 0, 442, 443, 7, 6, 0, 0, 443, 444, 7, 7, 0, 0, 444, 445, 7, 19, 0, 0, 445, 446, 1, 0, 0, 0, 446, 447, 6, 13, 0, 0, 447, 39, 1, 0, 0, 0, 448, 449, 7, 2, 0, 0, 449, 450, 7, 10, 0, 0, 450, 451, 7, 7, 0, 0, 451, 452, 7, 19, 0, 0, 452, 453, 1, 0, 0, 0, 453, 454, 6, 14, 8, 0, 454, 41, 1, 0, 0, 0, 455, 456, 7, 2, 0, 0, 456, 457, 7, 7, 0, 0, 457, 458, 7, 6, 0, 0, 458, 459, 7, 5, 0, 0, 459, 460, 1, 0, 0, 0, 460, 461, 6, 15, 0, 0, 461, 43, 1, 0, 0, 0, 462, 463, 7, 2, 0, 0, 463, 464, 7, 5, 0, 0, 464, 465, 7, 12, 0, 0, 465, 466, 7, 5, 0, 0, 466, 467, 7, 2, 0, 0, 467, 468, 1, 0, 0, 0, 468, 469, 6, 16, 0, 0, 469, 45, 1, 0, 0, 0, 470, 471, 7, 19, 0, 0, 471, 472, 7, 10, 0, 0, 472, 473, 7, 3, 0, 0, 473, 474, 7, 6, 0, 0, 474, 475, 7, 3, 0, 0, 475, 476, 1, 0, 0, 0, 476, 477, 6, 17, 0, 0, 477, 47, 1, 0, 0, 0, 478, 480, 8, 20, 0, 0, 479, 478, 1, 0, 0, 0, 480, 481, 1, 0, 0, 0, 481, 479, 1, 0, 0, 0, 481, 482, 1, 0, 0, 0, 482, 483, 1, 0, 0, 0, 483, 484, 6, 18, 0, 0, 484, 49, 1, 0, 0, 0, 485, 486, 5, 47, 0, 0, 486, 487, 5, 47, 0, 0, 487, 491, 1, 0, 0, 0, 488, 490, 8, 21, 0, 0, 489, 488, 1, 0, 0, 0, 490, 493, 1, 0, 0, 0, 491, 489, 1, 0, 0, 0, 491, 492, 1, 0, 0, 0, 492, 495, 1, 0, 0, 0, 493, 491, 1, 0, 0, 0, 494, 496, 5, 13, 0, 0, 495, 494, 1, 0, 0, 0, 495, 496, 1, 0, 0, 0, 496, 498, 1, 0, 0, 0, 497, 499, 5, 10, 0, 0, 498, 497, 1, 0, 0, 0, 498, 499, 1, 0, 0, 0, 499, 500, 1, 0, 0, 0, 500, 501, 6, 19, 9, 0, 501, 51, 1, 0, 0, 0, 502, 503, 5, 47, 0, 0, 503, 504, 5, 42, 0, 0, 504, 509, 1, 0, 0, 0, 505, 508, 3, 52, 20, 0, 506, 508, 9, 0, 0, 0, 507, 505, 1, 0, 0, 0, 507, 506, 1, 0, 0, 0, 508, 511, 1, 0, 0, 0, 509, 510, 1, 0, 0, 0, 509, 507, 1, 0, 0, 0, 510, 512, 1, 0, 0, 0, 511, 509, 1, 0, 0, 0, 512, 513, 5, 42, 0, 0, 513, 514, 5, 47, 0, 0, 514, 515, 1, 0, 0, 0, 515, 516, 6, 20, 9, 0, 516, 53, 1, 0, 0, 0, 517, 519, 7, 22, 0, 0, 518, 517, 1, 0, 0, 0, 519, 520, 1, 0, 0, 0, 520, 518, 1, 0, 0, 0, 520, 521, 1, 0, 0, 0, 521, 522, 1, 0, 0, 0, 522, 523, 6, 21, 9, 0, 523, 55, 1, 0, 0, 0, 524, 525, 3, 164, 76, 0, 525, 526, 1, 0, 0, 0, 526, 527, 6, 22, 10, 0, 527, 528, 6, 22, 11, 0, 528, 57, 1, 0, 0, 0, 529, 530, 3, 66, 27, 0, 530, 531, 1, 0, 0, 0, 531, 532, 6, 23, 12, 0, 532, 533, 6, 23, 13, 0, 533, 59, 1, 0, 0, 0, 534, 535, 3, 54, 21, 0, 535, 536, 1, 0, 0, 0, 536, 537, 6, 24, 9, 0, 537, 61, 1, 0, 0, 0, 538, 539, 3, 50, 19, 0, 539, 540, 1, 0, 0, 0, 540, 541, 6, 25, 9, 0, 541, 63, 1, 0, 0, 0, 542, 543, 3, 52, 20, 0, 543, 544, 1, 0, 0, 0, 544, 545, 6, 26, 9, 0, 545, 65, 1, 0, 0, 0, 546, 547, 5, 124, 0, 0, 547, 548, 1, 0, 0, 0, 548, 549, 6, 27, 13, 0, 549, 67, 1, 0, 0, 0, 550, 551, 7, 23, 0, 0, 551, 69, 1, 0, 0, 0, 552, 553, 7, 24, 0, 0, 553, 71, 1, 0, 0, 0, 554, 555, 5, 92, 0, 0, 555, 556, 7, 25, 0, 0, 556, 73, 1, 0, 0, 0, 557, 558, 8, 26, 0, 0, 558, 75, 1, 0, 0, 0, 559, 561, 7, 3, 0, 0, 560, 562, 7, 27, 0, 0, 561, 560, 1, 0, 0, 0, 561, 562, 1, 0, 0, 0, 562, 564, 1, 0, 0, 0, 563, 565, 3, 68, 28, 0, 564, 563, 1, 0, 0, 0, 565, 566, 1, 0, 0, 0, 566, 564, 1, 0, 0, 0, 566, 567, 1, 0, 0, 0, 567, 77, 1, 0, 0, 0, 568, 569, 5, 64, 0, 0, 569, 79, 1, 0, 0, 0, 570, 571, 5, 96, 0, 0, 571, 81, 1, 0, 0, 0, 572, 576, 8, 28, 0, 0, 573, 574, 5, 96, 0, 0, 574, 576, 5, 96, 0, 0, 575, 572, 1, 0, 0, 0, 575, 573, 1, 0, 0, 0, 576, 83, 1, 0, 0, 0, 577, 578, 5, 95, 0, 0, 578, 85, 1, 0, 0, 0, 579, 583, 3, 70, 29, 0, 580, 583, 3, 68, 28, 0, 581, 583, 3, 84, 36, 0, 582, 579, 1, 0, 0, 0, 582, 580, 1, 0, 0, 0, 582, 581, 1, 0, 0, 0, 583, 87, 1, 0, 0, 0, 584, 589, 5, 34, 0, 0, 585, 588, 3, 72, 30, 0, 586, 588, 3, 74, 31, 0, 587, 585, 1, 0, 0, 0, 587, 586, 1, 0, 0, 0, 588, 591, 1, 0, 0, 0, 589, 587, 1, 0, 0, 0, 589, 590, 1, 0, 0, 0, 590, 592, 1, 0, 0, 0, 591, 589, 1, 0, 0, 0, 592, 614, 5, 34, 0, 0, 593, 594, 5, 34, 0, 0, 594, 595, 5, 34, 0, 0, 595, 596, 5, 34, 0, 0, 596, 600, 1, 0, 0, 0, 597, 599, 8, 21, 0, 0, 598, 597, 1, 0, 0, 0, 599, 602, 1, 0, 0, 0, 600, 601, 1, 0, 0, 0, 600, 598, 1, 0, 0, 0, 601, 603, 1, 0, 0, 0, 602, 600, 1, 0, 0, 0, 603, 604, 5, 34, 0, 0, 604, 605, 5, 34, 0, 0, 605, 606, 5, 34, 0, 0, 606, 608, 1, 0, 0, 0, 607, 609, 5, 34, 0, 0, 608, 607, 1, 0, 0, 0, 608, 609, 1, 0, 0, 0, 609, 611, 1, 0, 0, 0, 610, 612, 5, 34, 0, 0, 611, 610, 1, 0, 0, 0, 611, 612, 1, 0, 0, 0, 612, 614, 1, 0, 0, 0, 613, 584, 1, 0, 0, 0, 613, 593, 1, 0, 0, 0, 614, 89, 1, 0, 0, 0, 615, 617, 3, 68, 28, 0, 616, 615, 1, 0, 0, 0, 617, 618, 1, 0, 0, 0, 618, 616, 1, 0, 0, 0, 618, 619, 1, 0, 0, 0, 619, 91, 1, 0, 0, 0, 620, 622, 3, 68, 28, 0, 621, 620, 1, 0, 0, 0, 622, 623, 1, 0, 0, 0, 623, 621, 1, 0, 0, 0, 623, 624, 1, 0, 0, 0, 624, 625, 1, 0, 0, 0, 625, 629, 3, 108, 48, 0, 626, 628, 3, 68, 28, 0, 627, 626, 1, 0, 0, 0, 628, 631, 1, 0, 0, 0, 629, 627, 1, 0, 0, 0, 629, 630, 1, 0, 0, 0, 630, 663, 1, 0, 0, 0, 631, 629, 1, 0, 0, 0, 632, 634, 3, 108, 48, 0, 633, 635, 3, 68, 28, 0, 634, 633, 1, 0, 0, 0, 635, 636, 1, 0, 0, 0, 636, 634, 1, 0, 0, 0, 636, 637, 1, 0, 0, 0, 637, 663, 1, 0, 0, 0, 638, 640, 3, 68, 28, 0, 639, 638, 1, 0, 0, 0, 640, 641, 1, 0, 0, 0, 641, 639, 1, 0, 0, 0, 641, 642, 1, 0, 0, 0, 642, 650, 1, 0, 0, 0, 643, 647, 3, 108, 48, 0, 644, 646, 3, 68, 28, 0, 645, 644, 1, 0, 0, 0, 646, 649, 1, 0, 0, 0, 647, 645, 1, 0, 0, 0, 647, 648, 1, 0, 0, 0, 648, 651, 1, 0, 0, 0, 649, 647, 1, 0, 0, 0, 650, 643, 1, 0, 0, 0, 650, 651, 1, 0, 0, 0, 651, 652, 1, 0, 0, 0, 652, 653, 3, 76, 32, 0, 653, 663, 1, 0, 0, 0, 654, 656, 3, 108, 48, 0, 655, 657, 3, 68, 28, 0, 656, 655, 1, 0, 0, 0, 657, 658, 1, 0, 0, 0, 658, 656, 1, 0, 0, 0, 658, 659, 1, 0, 0, 0, 659, 660, 1, 0, 0, 0, 660, 661, 3, 76, 32, 0, 661, 663, 1, 0, 0, 0, 662, 621, 1, 0, 0, 0, 662, 632, 1, 0, 0, 0, 662, 639, 1, 0, 0, 0, 662, 654, 1, 0, 0, 0, 663, 93, 1, 0, 0, 0, 664, 665, 7, 29, 0, 0, 665, 666, 7, 30, 0, 0, 666, 95, 1, 0, 0, 0, 667, 668, 7, 12, 0, 0, 668, 669, 7, 9, 0, 0, 669, 670, 7, 0, 0, 0, 670, 97, 1, 0, 0, 0, 671, 672, 7, 12, 0, 0, 672, 673, 7, 2, 0, 0, 673, 674, 7, 4, 0, 0, 674, 99, 1, 0, 0, 0, 675, 676, 5, 61, 0, 0, 676, 101, 1, 0, 0, 0, 677, 678, 5, 58, 0, 0, 678, 679, 5, 58, 0, 0, 679, 103, 1, 0, 0, 0, 680, 681, 5, 44, 0, 0, 681, 105, 1, 0, 0, 0, 682, 683, 7, 0, 0, 0, 683, 684, 7, 3, 0, 0, 684, 685, 7, 2, 0, 0, 685, 686, 7, 4, 0, 0, 686, 107, 1, 0, 0, 0, 687, 688, 5, 46, 0, 0, 688, 109, 1, 0, 0, 0, 689, 690, 7, 15, 0, 0, 690, 691, 7, 12, 0, 0, 691, 692, 7, 13, 0, 0, 692, 693, 7, 2, 0, 0, 693, 694, 7, 3, 0, 0, 694, 111, 1, 0, 0, 0, 695, 696, 7, 15, 0, 0, 696, 697, 7, 1, 0, 0, 697, 698, 7, 6, 0, 0, 698, 699, 7, 2, 0, 0, 699, 700, 7, 5, 0, 0, 700, 113, 1, 0, 0, 0, 701, 702, 7, 13, 0, 0, 702, 703, 7, 12, 0, 0, 703, 704, 7, 2, 0, 0, 704, 705, 7, 5, 0, 0, 705, 115, 1, 0, 0, 0, 706, 707, 5, 40, 0, 0, 707, 117, 1, 0, 0, 0, 708, 709, 7, 1, 0, 0, 709, 710, 7, 9, 0, 0, 710, 119, 1, 0, 0, 0, 711, 712, 7, 1, 0, 0, 712, 713, 7, 2, 0, 0, 713, 121, 1, 0, 0, 0, 714, 715, 7, 13, 0, 0, 715, 716, 7, 1, 0, 0, 716, 717, 7, 18, 0, 0, 717, 718, 7, 3, 0, 0, 718, 123, 1, 0, 0, 0, 719, 720, 7, 9, 0, 0, 720, 721, 7, 7, 0, 0, 721, 722, 7, 5, 0, 0, 722, 125, 1, 0, 0, 0, 723, 724, 7, 9, 0, 0, 724, 725, 7, 31, 0, 0, 725, 726, 7, 13, 0, 0, 726, 727, 7, 13, 0, 0, 727, 127, 1, 0, 0, 0, 728, 729, 7, 9, 0, 0, 729, 730, 7, 31, 0, 0, 730, 731, 7, 13, 0, 0, 731, 732, 7, 13, 0, 0, 732, 733, 7, 2, 0, 0, 733, 129, 1, 0, 0, 0, 734, 735, 7, 7, 0, 0, 735, 736, 7, 6, 0, 0, 736, 131, 1, 0, 0, 0, 737, 738, 5, 63, 0, 0, 738, 133, 1, 0, 0, 0, 739, 740, 7, 6, 0, 0, 740, 741, 7, 13, 0, 0, 741, 742, 7, 1, 0, 0, 742, 743, 7, 18, 0, 0, 743, 744, 7, 3, 0, 0, 744, 135, 1, 0, 0, 0, 745, 746, 5, 41, 0, 0, 746, 137, 1, 0, 0, 0, 747, 748, 7, 5, 0, 0, 748, 749, 7, 6, 0, 0, 749, 750, 7, 31, 0, 0, 750, 751, 7, 3, 0, 0, 751, 139, 1, 0, 0, 0, 752, 753, 5, 61, 0, 0, 753, 754, 5, 61, 0, 0, 754, 141, 1, 0, 0, 0, 755, 756, 5, 61, 0, 0, 756, 757, 5, 126, 0, 0, 757, 143, 1, 0, 0, 0, 758, 759, 5, 33, 0, 0, 759, 760, 5, 61, 0, 0, 760, 145, 1, 0, 0, 0, 761, 762, 5, 60, 0, 0, 762, 147, 1, 0, 0, 0, 763, 764, 5, 60, 0, 0, 764, 765, 5, 61, 0, 0, 765, 149, 1, 0, 0, 0, 766, 767, 5, 62, 0, 0, 767, 151, 1, 0, 0, 0, 768, 769, 5, 62, 0, 0, 769, 770, 5, 61, 0, 0, 770, 153, 1, 0, 0, 0, 771, 772, 5, 43, 0, 0, 772, 155, 1, 0, 0, 0, 773, 774, 5, 45, 0, 0, 774, 157, 1, 0, 0, 0, 775, 776, 5, 42, 0, 0, 776, 159, 1, 0, 0, 0, 777, 778, 5, 47, 0, 0, 778, 161, 1, 0, 0, 0, 779, 780, 5, 37, 0, 0, 780, 163, 1, 0, 0, 0, 781, 782, 5, 91, 0, 0, 782, 783, 1, 0, 0, 0, 783, 784, 6, 76, 0, 0, 784, 785, 6, 76, 0, 0, 785, 165, 1, 0, 0, 0, 786, 787, 5, 93, 0, 0, 787, 788, 1, 0, 0, 0, 788, 789, 6, 77, 13, 0, 789, 790, 6, 77, 13, 0, 790, 167, 1, 0, 0, 0, 791, 795, 3, 70, 29, 0, 792, 794, 3, 86, 37, 0, 793, 792, 1, 0, 0, 0, 794, 797, 1, 0, 0, 0, 795, 793, 1, 0, 0, 0, 795, 796, 1, 0, 0, 0, 796, 808, 1, 0, 0, 0, 797, 795, 1, 0, 0, 0, 798, 801, 3, 84, 36, 0, 799, 801, 3, 78, 33, 0, 800, 798, 1, 0, 0, 0, 800, 799, 1, 0, 0, 0, 801, 803, 1, 0, 0, 0, 802, 804, 3, 86, 37, 0, 803, 802, 1, 0, 0, 0, 804, 805, 1, 0, 0, 0, 805, 803, 1, 0, 0, 0, 805, 806, 1, 0, 0, 0, 806, 808, 1, 0, 0, 0, 807, 791, 1, 0, 0, 0, 807, 800, 1, 0, 0, 0, 808, 169, 1, 0, 0, 0, 809, 811, 3, 80, 34, 0, 810, 812, 3, 82, 35, 0, 811, 810, 1, 0, 0, 0, 812, 813, 1, 0, 0, 0, 813, 811, 1, 0, 0, 0, 813, 814, 1, 0, 0, 0, 814, 815, 1, 0, 0, 0, 815, 816, 3, 80, 34, 0, 816, 171, 1, 0, 0, 0, 817, 818, 3, 170, 79, 0, 818, 173, 1, 0, 0, 0, 819, 820, 3, 50, 19, 0, 820, 821, 1, 0, 0, 0, 821, 822, 6, 81, 9, 0, 822, 175, 1, 0, 0, 0, 823, 824, 3, 52, 20, 0, 824, 825, 1, 0, 0, 0, 825, 826, 6, 82, 9, 0, 826, 177, 1, 0, 0, 0, 827, 828, 3, 54, 21, 0, 828, 829, 1, 0, 0, 0, 829, 830, 6, 83, 9, 0, 830, 179, 1, 0, 0, 0, 831, 832, 3, 66, 27, 0, 832, 833, 1, 0, 0, 0, 833, 834, 6, 84, 12, 0, 834, 835, 6, 84, 13, 0, 835, 181, 1, 0, 0, 0, 836, 837, 3, 164, 76, 0, 837, 838, 1, 0, 0, 0, 838, 839, 6, 85, 10, 0, 839, 183, 1, 0, 0, 0, 840, 841, 3, 166, 77, 0, 841, 842, 1, 0, 0, 0, 842, 843, 6, 86, 14, 0, 843, 185, 1, 0, 0, 0, 844, 845, 3, 104, 46, 0, 845, 846, 1, 0, 0, 0, 846, 847, 6, 87, 15, 0, 847, 187, 1, 0, 0, 0, 848, 849, 3, 100, 44, 0, 849, 850, 1, 0, 0, 0, 850, 851, 6, 88, 16, 0, 851, 189, 1, 0, 0, 0, 852, 853, 3, 88, 38, 0, 853, 854, 1, 0, 0, 0, 854, 855, 6, 89, 17, 0, 855, 191, 1, 0, 0, 0, 856, 857, 7, 16, 0, 0, 857, 858, 7, 3, 0, 0, 858, 859, 7, 5, 0, 0, 859, 860, 7, 12, 0, 0, 860, 861, 7, 0, 0, 0, 861, 862, 7, 12, 0, 0, 862, 863, 7, 5, 0, 0, 863, 864, 7, 12, 0, 0, 864, 193, 1, 0, 0, 0, 865, 869, 8, 32, 0, 0, 866, 867, 5, 47, 0, 0, 867, 869, 8, 33, 0, 0, 868, 865, 1, 0, 0, 0, 868, 866, 1, 0, 0, 0, 869, 195, 1, 0, 0, 0, 870, 872, 3, 194, 91, 0, 871, 870, 1, 0, 0, 0, 872, 873, 1, 0, 0, 0, 873, 871, 1, 0, 0, 0, 873, 874, 1, 0, 0, 0, 874, 197, 1, 0, 0, 0, 875, 876, 3, 50, 19, 0, 876, 877, 1, 0, 0, 0, 877, 878, 6, 93, 9, 0, 878, 199, 1, 0, 0, 0, 879, 880, 3, 52, 20, 0, 880, 881, 1, 0, 0, 0, 881, 882, 6, 94, 9, 0, 882, 201, 1, 0, 0, 0, 883, 884, 3, 54, 21, 0, 884, 885, 1, 0, 0, 0, 885, 886, 6, 95, 9, 0, 886, 203, 1, 0, 0, 0, 887, 888, 3, 66, 27, 0, 888, 889, 1, 0, 0, 0, 889, 890, 6, 96, 12, 0, 890, 891, 6, 96, 13, 0, 891, 205, 1, 0, 0, 0, 892, 893, 3, 108, 48, 0, 893, 894, 1, 0, 0, 0, 894, 895, 6, 97, 18, 0, 895, 207, 1, 0, 0, 0, 896, 897, 3, 104, 46, 0, 897, 898, 1, 0, 0, 0, 898, 899, 6, 98, 15, 0, 899, 209, 1, 0, 0, 0, 900, 905, 3, 70, 29, 0, 901, 905, 3, 68, 28, 0, 902, 905, 3, 84, 36, 0, 903, 905, 3, 158, 73, 0, 904, 900, 1, 0, 0, 0, 904, 901, 1, 0, 0, 0, 904, 902, 1, 0, 0, 0, 904, 903, 1, 0, 0, 0, 905, 211, 1, 0, 0, 0, 906, 909, 3, 70, 29, 0, 907, 909, 3, 158, 73, 0, 908, 906, 1, 0, 0, 0, 908, 907, 1, 0, 0, 0, 909, 913, 1, 0, 0, 0, 910, 912, 3, 210, 99, 0, 911, 910, 1, 0, 0, 0, 912, 915, 1, 0, 0, 0, 913, 911, 1, 0, 0, 0, 913, 914, 1, 0, 0, 0, 914, 926, 1, 0, 0, 0, 915, 913, 1, 0, 0, 0, 916, 919, 3, 84, 36, 0, 917, 919, 3, 78, 33, 0, 918, 916, 1, 0, 0, 0, 918, 917, 1, 0, 0, 0, 919, 921, 1, 0, 0, 0, 920, 922, 3, 210, 99, 0, 921, 920, 1, 0, 0, 0, 922, 923, 1, 0, 0, 0, 923, 921, 1, 0, 0, 0, 923, 924, 1, 0, 0, 0, 924, 926, 1, 0, 0, 0, 925, 908, 1, 0, 0, 0, 925, 918, 1, 0, 0, 0, 926, 213, 1, 0, 0, 0, 927, 930, 3, 212, 100, 0, 928, 930, 3, 170, 79, 0, 929, 927, 1, 0, 0, 0, 929, 928, 1, 0, 0, 0, 930, 931, 1, 0, 0, 0, 931, 929, 1, 0, 0, 0, 931, 932, 1, 0, 0, 0, 932, 215, 1, 0, 0, 0, 933, 934, 3, 50, 19, 0, 934, 935, 1, 0, 0, 0, 935, 936, 6, 102, 9, 0, 936, 217, 1, 0, 0, 0, 937, 938, 3, 52, 20, 0, 938, 939, 1, 0, 0, 0, 939, 940, 6, 103, 9, 0, 940, 219, 1, 0, 0, 0, 941, 942, 3, 54, 21, 0, 942, 943, 1, 0, 0, 0, 943, 944, 6, 104, 9, 0, 944, 221, 1, 0, 0, 0, 945, 946, 3, 66, 27, 0, 946, 947, 1, 0, 0, 0, 947, 948, 6, 105, 12, 0, 948, 949, 6, 105, 13, 0, 949, 223, 1, 0, 0, 0, 950, 951, 3, 100, 44, 0, 951, 952, 1, 0, 0, 0, 952, 953, 6, 106, 16, 0, 953, 225, 1, 0, 0, 0, 954, 955, 3, 104, 46, 0, 955, 956, 1, 0, 0, 0, 956, 957, 6, 107, 15, 0, 957, 227, 1, 0, 0, 0, 958, 959, 3, 108, 48, 0, 959, 960, 1, 0, 0, 0, 960, 961, 6, 108, 18, 0, 961, 229, 1, 0, 0, 0, 962, 963, 7, 12, 0, 0, 963, 964, 7, 2, 0, 0, 964, 231, 1, 0, 0, 0, 965, 966, 3, 214, 101, 0, 966, 967, 1, 0, 0, 0, 967, 968, 6, 110, 19, 0, 968, 233, 1, 0, 0, 0, 969, 970, 3, 50, 19, 0, 970, 971, 1, 0, 0, 0, 971, 972, 6, 111, 9, 0, 972, 235, 1, 0, 0, 0, 973, 974, 3, 52, 20, 0, 974, 975, 1, 0, 0, 0, 975, 976, 6, 112, 9, 0, 976, 237, 1, 0, 0, 0, 977, 978, 3, 54, 21, 0, 978, 979, 1, 0, 0, 0, 979, 980, 6, 113, 9, 0, 980, 239, 1, 0, 0, 0, 981, 982, 3, 66, 27, 0, 982, 983, 1, 0, 0, 0, 983, 984, 6, 114, 12, 0, 984, 985, 6, 114, 13, 0, 985, 241, 1, 0, 0, 0, 986, 987, 3, 164, 76, 0, 987, 988, 1, 0, 0, 0, 988, 989, 6, 115, 10, 0, 989, 990, 6, 115, 20, 0, 990, 243, 1, 0, 0, 0, 991, 992, 7, 7, 0, 0, 992, 993, 7, 9, 0, 0, 993, 994, 1, 0, 0, 0, 994, 995, 6, 116, 21, 0, 995, 245, 1, 0, 0, 0, 996, 997, 7, 19, 0, 0, 997, 998, 7, 1, 0, 0, 998, 999, 7, 5, 0, 0, 999, 1000, 7, 10, 0, 0, 1000, 1001, 1, 0, 0, 0, 1001, 1002, 6, 117, 21, 0, 1002, 247, 1, 0, 0, 0, 1003, 1004, 8, 34, 0, 0, 1004, 249, 1, 0, 0, 0, 1005, 1007, 3, 248, 118, 0, 1006, 1005, 1, 0, 0, 0, 1007, 1008, 1, 0, 0, 0, 1008, 1006, 1, 0, 0, 0, 1008, 1009, 1, 0, 0, 0, 1009, 1010, 1, 0, 0, 0, 1010, 1011, 3, 318, 153, 0, 1011, 1013, 1, 0, 0, 0, 1012, 1006, 1, 0, 0, 0, 1012, 1013, 1, 0, 0, 0, 1013, 1015, 1, 0, 0, 0, 1014, 1016, 3, 248, 118, 0, 1015, 1014, 1, 0, 0, 0, 1016, 1017, 1, 0, 0, 0, 1017, 1015, 1, 0, 0, 0, 1017, 1018, 1, 0, 0, 0, 1018, 251, 1, 0, 0, 0, 1019, 1020, 3, 172, 80, 0, 1020, 1021, 1, 0, 0, 0, 1021, 1022, 6, 120, 22, 0, 1022, 253, 1, 0, 0, 0, 1023, 1024, 3, 250, 119, 0, 1024, 1025, 1, 0, 0, 0, 1025, 1026, 6, 121, 23, 0, 1026, 255, 1, 0, 0, 0, 1027, 1028, 3, 50, 19, 0, 1028, 1029, 1, 0, 0, 0, 1029, 1030, 6, 122, 9, 0, 1030, 257, 1, 0, 0, 0, 1031, 1032, 3, 52, 20, 0, 1032, 1033, 1, 0, 0, 0, 1033, 1034, 6, 123, 9, 0, 1034, 259, 1, 0, 0, 0, 1035, 1036, 3, 54, 21, 0, 1036, 1037, 1, 0, 0, 0, 1037, 1038, 6, 124, 9, 0, 1038, 261, 1, 0, 0, 0, 1039, 1040, 3, 66, 27, 0, 1040, 1041, 1, 0, 0, 0, 1041, 1042, 6, 125, 12, 0, 1042, 1043, 6, 125, 13, 0, 1043, 1044, 6, 125, 13, 0, 1044, 263, 1, 0, 0, 0, 1045, 1046, 3, 100, 44, 0, 1046, 1047, 1, 0, 0, 0, 1047, 1048, 6, 126, 16, 0, 1048, 265, 1, 0, 0, 0, 1049, 1050, 3, 104, 46, 0, 1050, 1051, 1, 0, 0, 0, 1051, 1052, 6, 127, 15, 0, 1052, 267, 1, 0, 0, 0, 1053, 1054, 3, 108, 48, 0, 1054, 1055, 1, 0, 0, 0, 1055, 1056, 6, 128, 18, 0, 1056, 269, 1, 0, 0, 0, 1057, 1058, 3, 246, 117, 0, 1058, 1059, 1, 0, 0, 0, 1059, 1060, 6, 129, 24, 0, 1060, 271, 1, 0, 0, 0, 1061, 1062, 3, 214, 101, 0, 1062, 1063, 1, 0, 0, 0, 1063, 1064, 6, 130, 19, 0, 1064, 273, 1, 0, 0, 0, 1065, 1066, 3, 172, 80, 0, 1066, 1067, 1, 0, 0, 0, 1067, 1068, 6, 131, 22, 0, 1068, 275, 1, 0, 0, 0, 1069, 1070, 3, 50, 19, 0, 1070, 1071, 1, 0, 0, 0, 1071, 1072, 6, 132, 9, 0, 1072, 277, 1, 0, 0, 0, 1073, 1074, 3, 52, 20, 0, 1074, 1075, 1, 0, 0, 0, 1075, 1076, 6, 133, 9, 0, 1076, 279, 1, 0, 0, 0, 1077, 1078, 3, 54, 21, 0, 1078, 1079, 1, 0, 0, 0, 1079, 1080, 6, 134, 9, 0, 1080, 281, 1, 0, 0, 0, 1081, 1082, 3, 66, 27, 0, 1082, 1083, 1, 0, 0, 0, 1083, 1084, 6, 135, 12, 0, 1084, 1085, 6, 135, 13, 0, 1085, 283, 1, 0, 0, 0, 1086, 1087, 3, 108, 48, 0, 1087, 1088, 1, 0, 0, 0, 1088, 1089, 6, 136, 18, 0, 1089, 285, 1, 0, 0, 0, 1090, 1091, 3, 172, 80, 0, 1091, 1092, 1, 0, 0, 0, 1092, 1093, 6, 137, 22, 0, 1093, 287, 1, 0, 0, 0, 1094, 1095, 3, 168, 78, 0, 1095, 1096, 1, 0, 0, 0, 1096, 1097, 6, 138, 25, 0, 1097, 289, 1, 0, 0, 0, 1098, 1099, 3, 50, 19, 0, 1099, 1100, 1, 0, 0, 0, 1100, 1101, 6, 139, 9, 0, 1101, 291, 1, 0, 0, 0, 1102, 1103, 3, 52, 20, 0, 1103, 1104, 1, 0, 0, 0, 1104, 1105, 6, 140, 9, 0, 1105, 293, 1, 0, 0, 0, 1106, 1107, 3, 54, 21, 0, 1107, 1108, 1, 0, 0, 0, 1108, 1109, 6, 141, 9, 0, 1109, 295, 1, 0, 0, 0, 1110, 1111, 3, 66, 27, 0, 1111, 1112, 1, 0, 0, 0, 1112, 1113, 6, 142, 12, 0, 1113, 1114, 6, 142, 13, 0, 1114, 297, 1, 0, 0, 0, 1115, 1116, 7, 1, 0, 0, 1116, 1117, 7, 9, 0, 0, 1117, 1118, 7, 15, 0, 0, 1118, 1119, 7, 7, 0, 0, 1119, 299, 1, 0, 0, 0, 1120, 1121, 3, 50, 19, 0, 1121, 1122, 1, 0, 0, 0, 1122, 1123, 6, 144, 9, 0, 1123, 301, 1, 0, 0, 0, 1124, 1125, 3, 52, 20, 0, 1125, 1126, 1, 0, 0, 0, 1126, 1127, 6, 145, 9, 0, 1127, 303, 1, 0, 0, 0, 1128, 1129, 3, 54, 21, 0, 1129, 1130, 1, 0, 0, 0, 1130, 1131, 6, 146, 9, 0, 1131, 305, 1, 0, 0, 0, 1132, 1133, 3, 66, 27, 0, 1133, 1134, 1, 0, 0, 0, 1134, 1135, 6, 147, 12, 0, 1135, 1136, 6, 147, 13, 0, 1136, 307, 1, 0, 0, 0, 1137, 1138, 7, 15, 0, 0, 1138, 1139, 7, 31, 0, 0, 1139, 1140, 7, 9, 0, 0, 1140, 1141, 7, 4, 0, 0, 1141, 1142, 7, 5, 0, 0, 1142, 1143, 7, 1, 0, 0, 1143, 1144, 7, 7, 0, 0, 1144, 1145, 7, 9, 0, 0, 1145, 1146, 7, 2, 0, 0, 1146, 309, 1, 0, 0, 0, 1147, 1148, 3, 50, 19, 0, 1148, 1149, 1, 0, 0, 0, 1149, 1150, 6, 149, 9, 0, 1150, 311, 1, 0, 0, 0, 1151, 1152, 3, 52, 20, 0, 1152, 1153, 1, 0, 0, 0, 1153, 1154, 6, 150, 9, 0, 1154, 313, 1, 0, 0, 0, 1155, 1156, 3, 54, 21, 0, 1156, 1157, 1, 0, 0, 0, 1157, 1158, 6, 151, 9, 0, 1158, 315, 1, 0, 0, 0, 1159, 1160, 3, 166, 77, 0, 1160, 1161, 1, 0, 0, 0, 1161, 1162, 6, 152, 14, 0, 1162, 1163, 6, 152, 13, 0, 1163, 317, 1, 0, 0, 0, 1164, 1165, 5, 58, 0, 0, 1165, 319, 1, 0, 0, 0, 1166, 1172, 3, 78, 33, 0, 1167, 1172, 3, 68, 28, 0, 1168, 1172, 3, 108, 48, 0, 1169, 1172, 3, 70, 29, 0, 1170, 1172, 3, 84, 36, 0, 1171, 1166, 1, 0, 0, 0, 1171, 1167, 1, 0, 0, 0, 1171, 1168, 1, 0, 0, 0, 1171, 1169, 1, 0, 0, 0, 1171, 1170, 1, 0, 0, 0, 1172, 1173, 1, 0, 0, 0, 1173, 1171, 1, 0, 0, 0, 1173, 1174, 1, 0, 0, 0, 1174, 321, 1, 0, 0, 0, 1175, 1176, 3, 50, 19, 0, 1176, 1177, 1, 0, 0, 0, 1177, 1178, 6, 155, 9, 0, 1178, 323, 1, 0, 0, 0, 1179, 1180, 3, 52, 20, 0, 1180, 1181, 1, 0, 0, 0, 1181, 1182, 6, 156, 9, 0, 1182, 325, 1, 0, 0, 0, 1183, 1184, 3, 54, 21, 0, 1184, 1185, 1, 0, 0, 0, 1185, 1186, 6, 157, 9, 0, 1186, 327, 1, 0, 0, 0, 58, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 481, 491, 495, 498, 507, 509, 520, 561, 566, 575, 582, 587, 589, 600, 608, 611, 613, 618, 623, 629, 636, 641, 647, 650, 658, 662, 795, 800, 805, 807, 813, 868, 873, 904, 908, 913, 918, 923, 925, 929, 931, 1008, 1012, 1017, 1171, 1173, 26, 5, 2, 0, 5, 4, 0, 5, 6, 0, 5, 1, 0, 5, 3, 0, 5, 10, 0, 5, 8, 0, 5, 5, 0, 5, 9, 0, 0, 1, 0, 7, 65, 0, 5, 0, 0, 7, 26, 0, 4, 0, 0, 7, 66, 0, 7, 35, 0, 7, 33, 0, 7, 27, 0, 7, 37, 0, 7, 77, 0, 5, 11, 0, 5, 7, 0, 7, 68, 0, 7, 87, 0, 7, 86, 0, 7, 67, 0] \ No newline at end of file diff --git a/packages/kbn-esql-ast/src/antlr/esql_lexer.tokens b/packages/kbn-esql-ast/src/antlr/esql_lexer.tokens index b496aa68b61f7..d2e7a695282ec 100644 --- a/packages/kbn-esql-ast/src/antlr/esql_lexer.tokens +++ b/packages/kbn-esql-ast/src/antlr/esql_lexer.tokens @@ -69,45 +69,44 @@ QUOTED_IDENTIFIER=68 EXPR_LINE_COMMENT=69 EXPR_MULTILINE_COMMENT=70 EXPR_WS=71 -OPTIONS=72 -METADATA=73 -FROM_UNQUOTED_IDENTIFIER=74 -FROM_LINE_COMMENT=75 -FROM_MULTILINE_COMMENT=76 -FROM_WS=77 -ID_PATTERN=78 -PROJECT_LINE_COMMENT=79 -PROJECT_MULTILINE_COMMENT=80 -PROJECT_WS=81 -AS=82 -RENAME_LINE_COMMENT=83 -RENAME_MULTILINE_COMMENT=84 -RENAME_WS=85 -ON=86 -WITH=87 -ENRICH_POLICY_NAME=88 -ENRICH_LINE_COMMENT=89 -ENRICH_MULTILINE_COMMENT=90 -ENRICH_WS=91 -ENRICH_FIELD_LINE_COMMENT=92 -ENRICH_FIELD_MULTILINE_COMMENT=93 -ENRICH_FIELD_WS=94 -MVEXPAND_LINE_COMMENT=95 -MVEXPAND_MULTILINE_COMMENT=96 -MVEXPAND_WS=97 -INFO=98 -SHOW_LINE_COMMENT=99 -SHOW_MULTILINE_COMMENT=100 -SHOW_WS=101 -FUNCTIONS=102 -META_LINE_COMMENT=103 -META_MULTILINE_COMMENT=104 -META_WS=105 -COLON=106 -SETTING=107 -SETTING_LINE_COMMENT=108 -SETTTING_MULTILINE_COMMENT=109 -SETTING_WS=110 +METADATA=72 +FROM_UNQUOTED_IDENTIFIER=73 +FROM_LINE_COMMENT=74 +FROM_MULTILINE_COMMENT=75 +FROM_WS=76 +ID_PATTERN=77 +PROJECT_LINE_COMMENT=78 +PROJECT_MULTILINE_COMMENT=79 +PROJECT_WS=80 +AS=81 +RENAME_LINE_COMMENT=82 +RENAME_MULTILINE_COMMENT=83 +RENAME_WS=84 +ON=85 +WITH=86 +ENRICH_POLICY_NAME=87 +ENRICH_LINE_COMMENT=88 +ENRICH_MULTILINE_COMMENT=89 +ENRICH_WS=90 +ENRICH_FIELD_LINE_COMMENT=91 +ENRICH_FIELD_MULTILINE_COMMENT=92 +ENRICH_FIELD_WS=93 +MVEXPAND_LINE_COMMENT=94 +MVEXPAND_MULTILINE_COMMENT=95 +MVEXPAND_WS=96 +INFO=97 +SHOW_LINE_COMMENT=98 +SHOW_MULTILINE_COMMENT=99 +SHOW_WS=100 +FUNCTIONS=101 +META_LINE_COMMENT=102 +META_MULTILINE_COMMENT=103 +META_WS=104 +COLON=105 +SETTING=106 +SETTING_LINE_COMMENT=107 +SETTTING_MULTILINE_COMMENT=108 +SETTING_WS=109 'dissect'=1 'drop'=2 'enrich'=3 @@ -163,11 +162,10 @@ SETTING_WS=110 '/'=63 '%'=64 ']'=66 -'options'=72 -'metadata'=73 -'as'=82 -'on'=86 -'with'=87 -'info'=98 -'functions'=102 -':'=106 +'metadata'=72 +'as'=81 +'on'=85 +'with'=86 +'info'=97 +'functions'=101 +':'=105 diff --git a/packages/kbn-esql-ast/src/antlr/esql_lexer.ts b/packages/kbn-esql-ast/src/antlr/esql_lexer.ts index d10efdb06e4bb..33ff8b4a75db3 100644 --- a/packages/kbn-esql-ast/src/antlr/esql_lexer.ts +++ b/packages/kbn-esql-ast/src/antlr/esql_lexer.ts @@ -84,45 +84,44 @@ export default class esql_lexer extends Lexer { public static readonly EXPR_LINE_COMMENT = 69; public static readonly EXPR_MULTILINE_COMMENT = 70; public static readonly EXPR_WS = 71; - public static readonly OPTIONS = 72; - public static readonly METADATA = 73; - public static readonly FROM_UNQUOTED_IDENTIFIER = 74; - public static readonly FROM_LINE_COMMENT = 75; - public static readonly FROM_MULTILINE_COMMENT = 76; - public static readonly FROM_WS = 77; - public static readonly ID_PATTERN = 78; - public static readonly PROJECT_LINE_COMMENT = 79; - public static readonly PROJECT_MULTILINE_COMMENT = 80; - public static readonly PROJECT_WS = 81; - public static readonly AS = 82; - public static readonly RENAME_LINE_COMMENT = 83; - public static readonly RENAME_MULTILINE_COMMENT = 84; - public static readonly RENAME_WS = 85; - public static readonly ON = 86; - public static readonly WITH = 87; - public static readonly ENRICH_POLICY_NAME = 88; - public static readonly ENRICH_LINE_COMMENT = 89; - public static readonly ENRICH_MULTILINE_COMMENT = 90; - public static readonly ENRICH_WS = 91; - public static readonly ENRICH_FIELD_LINE_COMMENT = 92; - public static readonly ENRICH_FIELD_MULTILINE_COMMENT = 93; - public static readonly ENRICH_FIELD_WS = 94; - public static readonly MVEXPAND_LINE_COMMENT = 95; - public static readonly MVEXPAND_MULTILINE_COMMENT = 96; - public static readonly MVEXPAND_WS = 97; - public static readonly INFO = 98; - public static readonly SHOW_LINE_COMMENT = 99; - public static readonly SHOW_MULTILINE_COMMENT = 100; - public static readonly SHOW_WS = 101; - public static readonly FUNCTIONS = 102; - public static readonly META_LINE_COMMENT = 103; - public static readonly META_MULTILINE_COMMENT = 104; - public static readonly META_WS = 105; - public static readonly COLON = 106; - public static readonly SETTING = 107; - public static readonly SETTING_LINE_COMMENT = 108; - public static readonly SETTTING_MULTILINE_COMMENT = 109; - public static readonly SETTING_WS = 110; + public static readonly METADATA = 72; + public static readonly FROM_UNQUOTED_IDENTIFIER = 73; + public static readonly FROM_LINE_COMMENT = 74; + public static readonly FROM_MULTILINE_COMMENT = 75; + public static readonly FROM_WS = 76; + public static readonly ID_PATTERN = 77; + public static readonly PROJECT_LINE_COMMENT = 78; + public static readonly PROJECT_MULTILINE_COMMENT = 79; + public static readonly PROJECT_WS = 80; + public static readonly AS = 81; + public static readonly RENAME_LINE_COMMENT = 82; + public static readonly RENAME_MULTILINE_COMMENT = 83; + public static readonly RENAME_WS = 84; + public static readonly ON = 85; + public static readonly WITH = 86; + public static readonly ENRICH_POLICY_NAME = 87; + public static readonly ENRICH_LINE_COMMENT = 88; + public static readonly ENRICH_MULTILINE_COMMENT = 89; + public static readonly ENRICH_WS = 90; + public static readonly ENRICH_FIELD_LINE_COMMENT = 91; + public static readonly ENRICH_FIELD_MULTILINE_COMMENT = 92; + public static readonly ENRICH_FIELD_WS = 93; + public static readonly MVEXPAND_LINE_COMMENT = 94; + public static readonly MVEXPAND_MULTILINE_COMMENT = 95; + public static readonly MVEXPAND_WS = 96; + public static readonly INFO = 97; + public static readonly SHOW_LINE_COMMENT = 98; + public static readonly SHOW_MULTILINE_COMMENT = 99; + public static readonly SHOW_WS = 100; + public static readonly FUNCTIONS = 101; + public static readonly META_LINE_COMMENT = 102; + public static readonly META_MULTILINE_COMMENT = 103; + public static readonly META_WS = 104; + public static readonly COLON = 105; + public static readonly SETTING = 106; + public static readonly SETTING_LINE_COMMENT = 107; + public static readonly SETTTING_MULTILINE_COMMENT = 108; + public static readonly SETTING_WS = 109; public static readonly EOF = Token.EOF; public static readonly EXPLAIN_MODE = 1; public static readonly EXPRESSION_MODE = 2; @@ -174,7 +173,6 @@ export default class esql_lexer extends Lexer { "']'", null, null, null, null, null, - "'options'", "'metadata'", null, null, null, null, @@ -237,7 +235,6 @@ export default class esql_lexer extends Lexer { "EXPR_LINE_COMMENT", "EXPR_MULTILINE_COMMENT", "EXPR_WS", - "OPTIONS", "METADATA", "FROM_UNQUOTED_IDENTIFIER", "FROM_LINE_COMMENT", @@ -294,22 +291,21 @@ export default class esql_lexer extends Lexer { "CLOSING_BRACKET", "UNQUOTED_IDENTIFIER", "QUOTED_ID", "QUOTED_IDENTIFIER", "EXPR_LINE_COMMENT", "EXPR_MULTILINE_COMMENT", "EXPR_WS", "FROM_PIPE", "FROM_OPENING_BRACKET", "FROM_CLOSING_BRACKET", "FROM_COMMA", "FROM_ASSIGN", - "FROM_QUOTED_STRING", "OPTIONS", "METADATA", "FROM_UNQUOTED_IDENTIFIER_PART", - "FROM_UNQUOTED_IDENTIFIER", "FROM_LINE_COMMENT", "FROM_MULTILINE_COMMENT", - "FROM_WS", "PROJECT_PIPE", "PROJECT_DOT", "PROJECT_COMMA", "UNQUOTED_ID_BODY_WITH_PATTERN", - "UNQUOTED_ID_PATTERN", "ID_PATTERN", "PROJECT_LINE_COMMENT", "PROJECT_MULTILINE_COMMENT", - "PROJECT_WS", "RENAME_PIPE", "RENAME_ASSIGN", "RENAME_COMMA", "RENAME_DOT", - "AS", "RENAME_ID_PATTERN", "RENAME_LINE_COMMENT", "RENAME_MULTILINE_COMMENT", - "RENAME_WS", "ENRICH_PIPE", "ENRICH_OPENING_BRACKET", "ON", "WITH", "ENRICH_POLICY_NAME_BODY", - "ENRICH_POLICY_NAME", "ENRICH_QUOTED_IDENTIFIER", "ENRICH_MODE_UNQUOTED_VALUE", - "ENRICH_LINE_COMMENT", "ENRICH_MULTILINE_COMMENT", "ENRICH_WS", "ENRICH_FIELD_PIPE", - "ENRICH_FIELD_ASSIGN", "ENRICH_FIELD_COMMA", "ENRICH_FIELD_DOT", "ENRICH_FIELD_WITH", - "ENRICH_FIELD_ID_PATTERN", "ENRICH_FIELD_QUOTED_IDENTIFIER", "ENRICH_FIELD_LINE_COMMENT", - "ENRICH_FIELD_MULTILINE_COMMENT", "ENRICH_FIELD_WS", "MVEXPAND_PIPE", - "MVEXPAND_DOT", "MVEXPAND_QUOTED_IDENTIFIER", "MVEXPAND_UNQUOTED_IDENTIFIER", - "MVEXPAND_LINE_COMMENT", "MVEXPAND_MULTILINE_COMMENT", "MVEXPAND_WS", - "SHOW_PIPE", "INFO", "SHOW_LINE_COMMENT", "SHOW_MULTILINE_COMMENT", "SHOW_WS", - "META_PIPE", "FUNCTIONS", "META_LINE_COMMENT", "META_MULTILINE_COMMENT", + "FROM_QUOTED_STRING", "METADATA", "FROM_UNQUOTED_IDENTIFIER_PART", "FROM_UNQUOTED_IDENTIFIER", + "FROM_LINE_COMMENT", "FROM_MULTILINE_COMMENT", "FROM_WS", "PROJECT_PIPE", + "PROJECT_DOT", "PROJECT_COMMA", "UNQUOTED_ID_BODY_WITH_PATTERN", "UNQUOTED_ID_PATTERN", + "ID_PATTERN", "PROJECT_LINE_COMMENT", "PROJECT_MULTILINE_COMMENT", "PROJECT_WS", + "RENAME_PIPE", "RENAME_ASSIGN", "RENAME_COMMA", "RENAME_DOT", "AS", "RENAME_ID_PATTERN", + "RENAME_LINE_COMMENT", "RENAME_MULTILINE_COMMENT", "RENAME_WS", "ENRICH_PIPE", + "ENRICH_OPENING_BRACKET", "ON", "WITH", "ENRICH_POLICY_NAME_BODY", "ENRICH_POLICY_NAME", + "ENRICH_QUOTED_IDENTIFIER", "ENRICH_MODE_UNQUOTED_VALUE", "ENRICH_LINE_COMMENT", + "ENRICH_MULTILINE_COMMENT", "ENRICH_WS", "ENRICH_FIELD_PIPE", "ENRICH_FIELD_ASSIGN", + "ENRICH_FIELD_COMMA", "ENRICH_FIELD_DOT", "ENRICH_FIELD_WITH", "ENRICH_FIELD_ID_PATTERN", + "ENRICH_FIELD_QUOTED_IDENTIFIER", "ENRICH_FIELD_LINE_COMMENT", "ENRICH_FIELD_MULTILINE_COMMENT", + "ENRICH_FIELD_WS", "MVEXPAND_PIPE", "MVEXPAND_DOT", "MVEXPAND_QUOTED_IDENTIFIER", + "MVEXPAND_UNQUOTED_IDENTIFIER", "MVEXPAND_LINE_COMMENT", "MVEXPAND_MULTILINE_COMMENT", + "MVEXPAND_WS", "SHOW_PIPE", "INFO", "SHOW_LINE_COMMENT", "SHOW_MULTILINE_COMMENT", + "SHOW_WS", "META_PIPE", "FUNCTIONS", "META_LINE_COMMENT", "META_MULTILINE_COMMENT", "META_WS", "SETTING_CLOSING_BRACKET", "COLON", "SETTING", "SETTING_LINE_COMMENT", "SETTTING_MULTILINE_COMMENT", "SETTING_WS", ]; @@ -332,7 +328,7 @@ export default class esql_lexer extends Lexer { public get modeNames(): string[] { return esql_lexer.modeNames; } - public static readonly _serializedATN: number[] = [4,0,110,1197,6,-1,6, + public static readonly _serializedATN: number[] = [4,0,109,1187,6,-1,6, -1,6,-1,6,-1,6,-1,6,-1,6,-1,6,-1,6,-1,6,-1,6,-1,6,-1,2,0,7,0,2,1,7,1,2, 2,7,2,2,3,7,3,2,4,7,4,2,5,7,5,2,6,7,6,2,7,7,7,2,8,7,8,2,9,7,9,2,10,7,10, 2,11,7,11,2,12,7,12,2,13,7,13,2,14,7,14,2,15,7,15,2,16,7,16,2,17,7,17,2, @@ -356,386 +352,383 @@ export default class esql_lexer extends Lexer { 7,134,2,135,7,135,2,136,7,136,2,137,7,137,2,138,7,138,2,139,7,139,2,140, 7,140,2,141,7,141,2,142,7,142,2,143,7,143,2,144,7,144,2,145,7,145,2,146, 7,146,2,147,7,147,2,148,7,148,2,149,7,149,2,150,7,150,2,151,7,151,2,152, - 7,152,2,153,7,153,2,154,7,154,2,155,7,155,2,156,7,156,2,157,7,157,2,158, - 7,158,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,3,1,3,1,3,1,3,1,3,1,3,1,3,1,4,1, - 4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,4,1,5,1,5,1,5,1,5,1,5,1,5,1,5,1,6,1,6,1, - 6,1,6,1,6,1,6,1,6,1,7,1,7,1,7,1,7,1,7,1,7,1,7,1,7,1,7,1,7,1,7,1,7,1,7,1, - 7,1,8,1,8,1,8,1,8,1,8,1,8,1,8,1,9,1,9,1,9,1,9,1,9,1,9,1,9,1,9,1,10,1,10, - 1,10,1,10,1,10,1,10,1,10,1,11,1,11,1,11,1,11,1,11,1,11,1,11,1,11,1,11,1, - 11,1,11,1,11,1,12,1,12,1,12,1,12,1,12,1,12,1,12,1,12,1,12,1,13,1,13,1,13, - 1,13,1,13,1,13,1,14,1,14,1,14,1,14,1,14,1,14,1,14,1,15,1,15,1,15,1,15,1, - 15,1,15,1,15,1,16,1,16,1,16,1,16,1,16,1,16,1,16,1,16,1,17,1,17,1,17,1,17, - 1,17,1,17,1,17,1,17,1,18,4,18,482,8,18,11,18,12,18,483,1,18,1,18,1,19,1, - 19,1,19,1,19,5,19,492,8,19,10,19,12,19,495,9,19,1,19,3,19,498,8,19,1,19, - 3,19,501,8,19,1,19,1,19,1,20,1,20,1,20,1,20,1,20,5,20,510,8,20,10,20,12, - 20,513,9,20,1,20,1,20,1,20,1,20,1,20,1,21,4,21,521,8,21,11,21,12,21,522, - 1,21,1,21,1,22,1,22,1,22,1,22,1,22,1,23,1,23,1,23,1,23,1,23,1,24,1,24,1, - 24,1,24,1,25,1,25,1,25,1,25,1,26,1,26,1,26,1,26,1,27,1,27,1,27,1,27,1,28, - 1,28,1,29,1,29,1,30,1,30,1,30,1,31,1,31,1,32,1,32,3,32,564,8,32,1,32,4, - 32,567,8,32,11,32,12,32,568,1,33,1,33,1,34,1,34,1,35,1,35,1,35,3,35,578, - 8,35,1,36,1,36,1,37,1,37,1,37,3,37,585,8,37,1,38,1,38,1,38,5,38,590,8,38, - 10,38,12,38,593,9,38,1,38,1,38,1,38,1,38,1,38,1,38,5,38,601,8,38,10,38, - 12,38,604,9,38,1,38,1,38,1,38,1,38,1,38,3,38,611,8,38,1,38,3,38,614,8,38, - 3,38,616,8,38,1,39,4,39,619,8,39,11,39,12,39,620,1,40,4,40,624,8,40,11, - 40,12,40,625,1,40,1,40,5,40,630,8,40,10,40,12,40,633,9,40,1,40,1,40,4,40, - 637,8,40,11,40,12,40,638,1,40,4,40,642,8,40,11,40,12,40,643,1,40,1,40,5, - 40,648,8,40,10,40,12,40,651,9,40,3,40,653,8,40,1,40,1,40,1,40,1,40,4,40, - 659,8,40,11,40,12,40,660,1,40,1,40,3,40,665,8,40,1,41,1,41,1,41,1,42,1, - 42,1,42,1,42,1,43,1,43,1,43,1,43,1,44,1,44,1,45,1,45,1,45,1,46,1,46,1,47, - 1,47,1,47,1,47,1,47,1,48,1,48,1,49,1,49,1,49,1,49,1,49,1,49,1,50,1,50,1, - 50,1,50,1,50,1,50,1,51,1,51,1,51,1,51,1,51,1,52,1,52,1,53,1,53,1,53,1,54, - 1,54,1,54,1,55,1,55,1,55,1,55,1,55,1,56,1,56,1,56,1,56,1,57,1,57,1,57,1, - 57,1,57,1,58,1,58,1,58,1,58,1,58,1,58,1,59,1,59,1,59,1,60,1,60,1,61,1,61, - 1,61,1,61,1,61,1,61,1,62,1,62,1,63,1,63,1,63,1,63,1,63,1,64,1,64,1,64,1, - 65,1,65,1,65,1,66,1,66,1,66,1,67,1,67,1,68,1,68,1,68,1,69,1,69,1,70,1,70, - 1,70,1,71,1,71,1,72,1,72,1,73,1,73,1,74,1,74,1,75,1,75,1,76,1,76,1,76,1, - 76,1,76,1,77,1,77,1,77,1,77,1,77,1,78,1,78,5,78,796,8,78,10,78,12,78,799, - 9,78,1,78,1,78,3,78,803,8,78,1,78,4,78,806,8,78,11,78,12,78,807,3,78,810, - 8,78,1,79,1,79,4,79,814,8,79,11,79,12,79,815,1,79,1,79,1,80,1,80,1,81,1, - 81,1,81,1,81,1,82,1,82,1,82,1,82,1,83,1,83,1,83,1,83,1,84,1,84,1,84,1,84, - 1,84,1,85,1,85,1,85,1,85,1,86,1,86,1,86,1,86,1,87,1,87,1,87,1,87,1,88,1, - 88,1,88,1,88,1,89,1,89,1,89,1,89,1,90,1,90,1,90,1,90,1,90,1,90,1,90,1,90, - 1,91,1,91,1,91,1,91,1,91,1,91,1,91,1,91,1,91,1,92,1,92,1,92,3,92,879,8, - 92,1,93,4,93,882,8,93,11,93,12,93,883,1,94,1,94,1,94,1,94,1,95,1,95,1,95, - 1,95,1,96,1,96,1,96,1,96,1,97,1,97,1,97,1,97,1,97,1,98,1,98,1,98,1,98,1, - 99,1,99,1,99,1,99,1,100,1,100,1,100,1,100,3,100,915,8,100,1,101,1,101,3, - 101,919,8,101,1,101,5,101,922,8,101,10,101,12,101,925,9,101,1,101,1,101, - 3,101,929,8,101,1,101,4,101,932,8,101,11,101,12,101,933,3,101,936,8,101, - 1,102,1,102,4,102,940,8,102,11,102,12,102,941,1,103,1,103,1,103,1,103,1, - 104,1,104,1,104,1,104,1,105,1,105,1,105,1,105,1,106,1,106,1,106,1,106,1, - 106,1,107,1,107,1,107,1,107,1,108,1,108,1,108,1,108,1,109,1,109,1,109,1, - 109,1,110,1,110,1,110,1,111,1,111,1,111,1,111,1,112,1,112,1,112,1,112,1, - 113,1,113,1,113,1,113,1,114,1,114,1,114,1,114,1,115,1,115,1,115,1,115,1, - 115,1,116,1,116,1,116,1,116,1,116,1,117,1,117,1,117,1,117,1,117,1,118,1, - 118,1,118,1,118,1,118,1,118,1,118,1,119,1,119,1,120,4,120,1017,8,120,11, - 120,12,120,1018,1,120,1,120,3,120,1023,8,120,1,120,4,120,1026,8,120,11, - 120,12,120,1027,1,121,1,121,1,121,1,121,1,122,1,122,1,122,1,122,1,123,1, - 123,1,123,1,123,1,124,1,124,1,124,1,124,1,125,1,125,1,125,1,125,1,126,1, - 126,1,126,1,126,1,126,1,126,1,127,1,127,1,127,1,127,1,128,1,128,1,128,1, - 128,1,129,1,129,1,129,1,129,1,130,1,130,1,130,1,130,1,131,1,131,1,131,1, - 131,1,132,1,132,1,132,1,132,1,133,1,133,1,133,1,133,1,134,1,134,1,134,1, - 134,1,135,1,135,1,135,1,135,1,136,1,136,1,136,1,136,1,136,1,137,1,137,1, - 137,1,137,1,138,1,138,1,138,1,138,1,139,1,139,1,139,1,139,1,140,1,140,1, - 140,1,140,1,141,1,141,1,141,1,141,1,142,1,142,1,142,1,142,1,143,1,143,1, - 143,1,143,1,143,1,144,1,144,1,144,1,144,1,144,1,145,1,145,1,145,1,145,1, - 146,1,146,1,146,1,146,1,147,1,147,1,147,1,147,1,148,1,148,1,148,1,148,1, - 148,1,149,1,149,1,149,1,149,1,149,1,149,1,149,1,149,1,149,1,149,1,150,1, - 150,1,150,1,150,1,151,1,151,1,151,1,151,1,152,1,152,1,152,1,152,1,153,1, - 153,1,153,1,153,1,153,1,154,1,154,1,155,1,155,1,155,1,155,1,155,4,155,1182, - 8,155,11,155,12,155,1183,1,156,1,156,1,156,1,156,1,157,1,157,1,157,1,157, - 1,158,1,158,1,158,1,158,2,511,602,0,159,12,1,14,2,16,3,18,4,20,5,22,6,24, - 7,26,8,28,9,30,10,32,11,34,12,36,13,38,14,40,15,42,16,44,17,46,18,48,19, - 50,20,52,21,54,22,56,0,58,0,60,23,62,24,64,25,66,26,68,0,70,0,72,0,74,0, - 76,0,78,0,80,0,82,0,84,0,86,0,88,27,90,28,92,29,94,30,96,31,98,32,100,33, - 102,34,104,35,106,36,108,37,110,38,112,39,114,40,116,41,118,42,120,43,122, - 44,124,45,126,46,128,47,130,48,132,49,134,50,136,51,138,52,140,53,142,54, - 144,55,146,56,148,57,150,58,152,59,154,60,156,61,158,62,160,63,162,64,164, - 65,166,66,168,67,170,0,172,68,174,69,176,70,178,71,180,0,182,0,184,0,186, - 0,188,0,190,0,192,72,194,73,196,0,198,74,200,75,202,76,204,77,206,0,208, - 0,210,0,212,0,214,0,216,78,218,79,220,80,222,81,224,0,226,0,228,0,230,0, - 232,82,234,0,236,83,238,84,240,85,242,0,244,0,246,86,248,87,250,0,252,88, - 254,0,256,0,258,89,260,90,262,91,264,0,266,0,268,0,270,0,272,0,274,0,276, - 0,278,92,280,93,282,94,284,0,286,0,288,0,290,0,292,95,294,96,296,97,298, - 0,300,98,302,99,304,100,306,101,308,0,310,102,312,103,314,104,316,105,318, - 0,320,106,322,107,324,108,326,109,328,110,12,0,1,2,3,4,5,6,7,8,9,10,11, - 35,2,0,68,68,100,100,2,0,73,73,105,105,2,0,83,83,115,115,2,0,69,69,101, - 101,2,0,67,67,99,99,2,0,84,84,116,116,2,0,82,82,114,114,2,0,79,79,111,111, - 2,0,80,80,112,112,2,0,78,78,110,110,2,0,72,72,104,104,2,0,86,86,118,118, - 2,0,65,65,97,97,2,0,76,76,108,108,2,0,88,88,120,120,2,0,70,70,102,102,2, - 0,77,77,109,109,2,0,71,71,103,103,2,0,75,75,107,107,2,0,87,87,119,119,6, - 0,9,10,13,13,32,32,47,47,91,91,93,93,2,0,10,10,13,13,3,0,9,10,13,13,32, - 32,1,0,48,57,2,0,65,90,97,122,8,0,34,34,78,78,82,82,84,84,92,92,110,110, - 114,114,116,116,4,0,10,10,13,13,34,34,92,92,2,0,43,43,45,45,1,0,96,96,2, - 0,66,66,98,98,2,0,89,89,121,121,2,0,85,85,117,117,10,0,9,10,13,13,32,32, - 44,44,47,47,61,61,91,91,93,93,96,96,124,124,2,0,42,42,47,47,11,0,9,10,13, - 13,32,32,34,35,44,44,47,47,58,58,60,60,62,63,92,92,124,124,1224,0,12,1, - 0,0,0,0,14,1,0,0,0,0,16,1,0,0,0,0,18,1,0,0,0,0,20,1,0,0,0,0,22,1,0,0,0, - 0,24,1,0,0,0,0,26,1,0,0,0,0,28,1,0,0,0,0,30,1,0,0,0,0,32,1,0,0,0,0,34,1, - 0,0,0,0,36,1,0,0,0,0,38,1,0,0,0,0,40,1,0,0,0,0,42,1,0,0,0,0,44,1,0,0,0, - 0,46,1,0,0,0,0,48,1,0,0,0,0,50,1,0,0,0,0,52,1,0,0,0,0,54,1,0,0,0,1,56,1, - 0,0,0,1,58,1,0,0,0,1,60,1,0,0,0,1,62,1,0,0,0,1,64,1,0,0,0,2,66,1,0,0,0, - 2,88,1,0,0,0,2,90,1,0,0,0,2,92,1,0,0,0,2,94,1,0,0,0,2,96,1,0,0,0,2,98,1, - 0,0,0,2,100,1,0,0,0,2,102,1,0,0,0,2,104,1,0,0,0,2,106,1,0,0,0,2,108,1,0, - 0,0,2,110,1,0,0,0,2,112,1,0,0,0,2,114,1,0,0,0,2,116,1,0,0,0,2,118,1,0,0, - 0,2,120,1,0,0,0,2,122,1,0,0,0,2,124,1,0,0,0,2,126,1,0,0,0,2,128,1,0,0,0, - 2,130,1,0,0,0,2,132,1,0,0,0,2,134,1,0,0,0,2,136,1,0,0,0,2,138,1,0,0,0,2, - 140,1,0,0,0,2,142,1,0,0,0,2,144,1,0,0,0,2,146,1,0,0,0,2,148,1,0,0,0,2,150, - 1,0,0,0,2,152,1,0,0,0,2,154,1,0,0,0,2,156,1,0,0,0,2,158,1,0,0,0,2,160,1, - 0,0,0,2,162,1,0,0,0,2,164,1,0,0,0,2,166,1,0,0,0,2,168,1,0,0,0,2,172,1,0, - 0,0,2,174,1,0,0,0,2,176,1,0,0,0,2,178,1,0,0,0,3,180,1,0,0,0,3,182,1,0,0, - 0,3,184,1,0,0,0,3,186,1,0,0,0,3,188,1,0,0,0,3,190,1,0,0,0,3,192,1,0,0,0, - 3,194,1,0,0,0,3,198,1,0,0,0,3,200,1,0,0,0,3,202,1,0,0,0,3,204,1,0,0,0,4, - 206,1,0,0,0,4,208,1,0,0,0,4,210,1,0,0,0,4,216,1,0,0,0,4,218,1,0,0,0,4,220, - 1,0,0,0,4,222,1,0,0,0,5,224,1,0,0,0,5,226,1,0,0,0,5,228,1,0,0,0,5,230,1, - 0,0,0,5,232,1,0,0,0,5,234,1,0,0,0,5,236,1,0,0,0,5,238,1,0,0,0,5,240,1,0, - 0,0,6,242,1,0,0,0,6,244,1,0,0,0,6,246,1,0,0,0,6,248,1,0,0,0,6,252,1,0,0, - 0,6,254,1,0,0,0,6,256,1,0,0,0,6,258,1,0,0,0,6,260,1,0,0,0,6,262,1,0,0,0, - 7,264,1,0,0,0,7,266,1,0,0,0,7,268,1,0,0,0,7,270,1,0,0,0,7,272,1,0,0,0,7, - 274,1,0,0,0,7,276,1,0,0,0,7,278,1,0,0,0,7,280,1,0,0,0,7,282,1,0,0,0,8,284, - 1,0,0,0,8,286,1,0,0,0,8,288,1,0,0,0,8,290,1,0,0,0,8,292,1,0,0,0,8,294,1, - 0,0,0,8,296,1,0,0,0,9,298,1,0,0,0,9,300,1,0,0,0,9,302,1,0,0,0,9,304,1,0, - 0,0,9,306,1,0,0,0,10,308,1,0,0,0,10,310,1,0,0,0,10,312,1,0,0,0,10,314,1, - 0,0,0,10,316,1,0,0,0,11,318,1,0,0,0,11,320,1,0,0,0,11,322,1,0,0,0,11,324, - 1,0,0,0,11,326,1,0,0,0,11,328,1,0,0,0,12,330,1,0,0,0,14,340,1,0,0,0,16, - 347,1,0,0,0,18,356,1,0,0,0,20,363,1,0,0,0,22,373,1,0,0,0,24,380,1,0,0,0, - 26,387,1,0,0,0,28,401,1,0,0,0,30,408,1,0,0,0,32,416,1,0,0,0,34,423,1,0, - 0,0,36,435,1,0,0,0,38,444,1,0,0,0,40,450,1,0,0,0,42,457,1,0,0,0,44,464, - 1,0,0,0,46,472,1,0,0,0,48,481,1,0,0,0,50,487,1,0,0,0,52,504,1,0,0,0,54, - 520,1,0,0,0,56,526,1,0,0,0,58,531,1,0,0,0,60,536,1,0,0,0,62,540,1,0,0,0, - 64,544,1,0,0,0,66,548,1,0,0,0,68,552,1,0,0,0,70,554,1,0,0,0,72,556,1,0, - 0,0,74,559,1,0,0,0,76,561,1,0,0,0,78,570,1,0,0,0,80,572,1,0,0,0,82,577, - 1,0,0,0,84,579,1,0,0,0,86,584,1,0,0,0,88,615,1,0,0,0,90,618,1,0,0,0,92, - 664,1,0,0,0,94,666,1,0,0,0,96,669,1,0,0,0,98,673,1,0,0,0,100,677,1,0,0, - 0,102,679,1,0,0,0,104,682,1,0,0,0,106,684,1,0,0,0,108,689,1,0,0,0,110,691, - 1,0,0,0,112,697,1,0,0,0,114,703,1,0,0,0,116,708,1,0,0,0,118,710,1,0,0,0, - 120,713,1,0,0,0,122,716,1,0,0,0,124,721,1,0,0,0,126,725,1,0,0,0,128,730, - 1,0,0,0,130,736,1,0,0,0,132,739,1,0,0,0,134,741,1,0,0,0,136,747,1,0,0,0, - 138,749,1,0,0,0,140,754,1,0,0,0,142,757,1,0,0,0,144,760,1,0,0,0,146,763, - 1,0,0,0,148,765,1,0,0,0,150,768,1,0,0,0,152,770,1,0,0,0,154,773,1,0,0,0, - 156,775,1,0,0,0,158,777,1,0,0,0,160,779,1,0,0,0,162,781,1,0,0,0,164,783, - 1,0,0,0,166,788,1,0,0,0,168,809,1,0,0,0,170,811,1,0,0,0,172,819,1,0,0,0, - 174,821,1,0,0,0,176,825,1,0,0,0,178,829,1,0,0,0,180,833,1,0,0,0,182,838, - 1,0,0,0,184,842,1,0,0,0,186,846,1,0,0,0,188,850,1,0,0,0,190,854,1,0,0,0, - 192,858,1,0,0,0,194,866,1,0,0,0,196,878,1,0,0,0,198,881,1,0,0,0,200,885, - 1,0,0,0,202,889,1,0,0,0,204,893,1,0,0,0,206,897,1,0,0,0,208,902,1,0,0,0, - 210,906,1,0,0,0,212,914,1,0,0,0,214,935,1,0,0,0,216,939,1,0,0,0,218,943, - 1,0,0,0,220,947,1,0,0,0,222,951,1,0,0,0,224,955,1,0,0,0,226,960,1,0,0,0, - 228,964,1,0,0,0,230,968,1,0,0,0,232,972,1,0,0,0,234,975,1,0,0,0,236,979, - 1,0,0,0,238,983,1,0,0,0,240,987,1,0,0,0,242,991,1,0,0,0,244,996,1,0,0,0, - 246,1001,1,0,0,0,248,1006,1,0,0,0,250,1013,1,0,0,0,252,1022,1,0,0,0,254, - 1029,1,0,0,0,256,1033,1,0,0,0,258,1037,1,0,0,0,260,1041,1,0,0,0,262,1045, - 1,0,0,0,264,1049,1,0,0,0,266,1055,1,0,0,0,268,1059,1,0,0,0,270,1063,1,0, - 0,0,272,1067,1,0,0,0,274,1071,1,0,0,0,276,1075,1,0,0,0,278,1079,1,0,0,0, - 280,1083,1,0,0,0,282,1087,1,0,0,0,284,1091,1,0,0,0,286,1096,1,0,0,0,288, - 1100,1,0,0,0,290,1104,1,0,0,0,292,1108,1,0,0,0,294,1112,1,0,0,0,296,1116, - 1,0,0,0,298,1120,1,0,0,0,300,1125,1,0,0,0,302,1130,1,0,0,0,304,1134,1,0, - 0,0,306,1138,1,0,0,0,308,1142,1,0,0,0,310,1147,1,0,0,0,312,1157,1,0,0,0, - 314,1161,1,0,0,0,316,1165,1,0,0,0,318,1169,1,0,0,0,320,1174,1,0,0,0,322, - 1181,1,0,0,0,324,1185,1,0,0,0,326,1189,1,0,0,0,328,1193,1,0,0,0,330,331, - 7,0,0,0,331,332,7,1,0,0,332,333,7,2,0,0,333,334,7,2,0,0,334,335,7,3,0,0, - 335,336,7,4,0,0,336,337,7,5,0,0,337,338,1,0,0,0,338,339,6,0,0,0,339,13, - 1,0,0,0,340,341,7,0,0,0,341,342,7,6,0,0,342,343,7,7,0,0,343,344,7,8,0,0, - 344,345,1,0,0,0,345,346,6,1,1,0,346,15,1,0,0,0,347,348,7,3,0,0,348,349, - 7,9,0,0,349,350,7,6,0,0,350,351,7,1,0,0,351,352,7,4,0,0,352,353,7,10,0, - 0,353,354,1,0,0,0,354,355,6,2,2,0,355,17,1,0,0,0,356,357,7,3,0,0,357,358, - 7,11,0,0,358,359,7,12,0,0,359,360,7,13,0,0,360,361,1,0,0,0,361,362,6,3, - 0,0,362,19,1,0,0,0,363,364,7,3,0,0,364,365,7,14,0,0,365,366,7,8,0,0,366, - 367,7,13,0,0,367,368,7,12,0,0,368,369,7,1,0,0,369,370,7,9,0,0,370,371,1, - 0,0,0,371,372,6,4,3,0,372,21,1,0,0,0,373,374,7,15,0,0,374,375,7,6,0,0,375, - 376,7,7,0,0,376,377,7,16,0,0,377,378,1,0,0,0,378,379,6,5,4,0,379,23,1,0, - 0,0,380,381,7,17,0,0,381,382,7,6,0,0,382,383,7,7,0,0,383,384,7,18,0,0,384, - 385,1,0,0,0,385,386,6,6,0,0,386,25,1,0,0,0,387,388,7,1,0,0,388,389,7,9, - 0,0,389,390,7,13,0,0,390,391,7,1,0,0,391,392,7,9,0,0,392,393,7,3,0,0,393, - 394,7,2,0,0,394,395,7,5,0,0,395,396,7,12,0,0,396,397,7,5,0,0,397,398,7, - 2,0,0,398,399,1,0,0,0,399,400,6,7,0,0,400,27,1,0,0,0,401,402,7,18,0,0,402, - 403,7,3,0,0,403,404,7,3,0,0,404,405,7,8,0,0,405,406,1,0,0,0,406,407,6,8, - 1,0,407,29,1,0,0,0,408,409,7,13,0,0,409,410,7,1,0,0,410,411,7,16,0,0,411, - 412,7,1,0,0,412,413,7,5,0,0,413,414,1,0,0,0,414,415,6,9,0,0,415,31,1,0, - 0,0,416,417,7,16,0,0,417,418,7,3,0,0,418,419,7,5,0,0,419,420,7,12,0,0,420, - 421,1,0,0,0,421,422,6,10,5,0,422,33,1,0,0,0,423,424,7,16,0,0,424,425,7, - 11,0,0,425,426,5,95,0,0,426,427,7,3,0,0,427,428,7,14,0,0,428,429,7,8,0, - 0,429,430,7,12,0,0,430,431,7,9,0,0,431,432,7,0,0,0,432,433,1,0,0,0,433, - 434,6,11,6,0,434,35,1,0,0,0,435,436,7,6,0,0,436,437,7,3,0,0,437,438,7,9, - 0,0,438,439,7,12,0,0,439,440,7,16,0,0,440,441,7,3,0,0,441,442,1,0,0,0,442, - 443,6,12,7,0,443,37,1,0,0,0,444,445,7,6,0,0,445,446,7,7,0,0,446,447,7,19, - 0,0,447,448,1,0,0,0,448,449,6,13,0,0,449,39,1,0,0,0,450,451,7,2,0,0,451, - 452,7,10,0,0,452,453,7,7,0,0,453,454,7,19,0,0,454,455,1,0,0,0,455,456,6, - 14,8,0,456,41,1,0,0,0,457,458,7,2,0,0,458,459,7,7,0,0,459,460,7,6,0,0,460, - 461,7,5,0,0,461,462,1,0,0,0,462,463,6,15,0,0,463,43,1,0,0,0,464,465,7,2, - 0,0,465,466,7,5,0,0,466,467,7,12,0,0,467,468,7,5,0,0,468,469,7,2,0,0,469, - 470,1,0,0,0,470,471,6,16,0,0,471,45,1,0,0,0,472,473,7,19,0,0,473,474,7, - 10,0,0,474,475,7,3,0,0,475,476,7,6,0,0,476,477,7,3,0,0,477,478,1,0,0,0, - 478,479,6,17,0,0,479,47,1,0,0,0,480,482,8,20,0,0,481,480,1,0,0,0,482,483, - 1,0,0,0,483,481,1,0,0,0,483,484,1,0,0,0,484,485,1,0,0,0,485,486,6,18,0, - 0,486,49,1,0,0,0,487,488,5,47,0,0,488,489,5,47,0,0,489,493,1,0,0,0,490, - 492,8,21,0,0,491,490,1,0,0,0,492,495,1,0,0,0,493,491,1,0,0,0,493,494,1, - 0,0,0,494,497,1,0,0,0,495,493,1,0,0,0,496,498,5,13,0,0,497,496,1,0,0,0, - 497,498,1,0,0,0,498,500,1,0,0,0,499,501,5,10,0,0,500,499,1,0,0,0,500,501, - 1,0,0,0,501,502,1,0,0,0,502,503,6,19,9,0,503,51,1,0,0,0,504,505,5,47,0, - 0,505,506,5,42,0,0,506,511,1,0,0,0,507,510,3,52,20,0,508,510,9,0,0,0,509, - 507,1,0,0,0,509,508,1,0,0,0,510,513,1,0,0,0,511,512,1,0,0,0,511,509,1,0, - 0,0,512,514,1,0,0,0,513,511,1,0,0,0,514,515,5,42,0,0,515,516,5,47,0,0,516, - 517,1,0,0,0,517,518,6,20,9,0,518,53,1,0,0,0,519,521,7,22,0,0,520,519,1, - 0,0,0,521,522,1,0,0,0,522,520,1,0,0,0,522,523,1,0,0,0,523,524,1,0,0,0,524, - 525,6,21,9,0,525,55,1,0,0,0,526,527,3,164,76,0,527,528,1,0,0,0,528,529, - 6,22,10,0,529,530,6,22,11,0,530,57,1,0,0,0,531,532,3,66,27,0,532,533,1, - 0,0,0,533,534,6,23,12,0,534,535,6,23,13,0,535,59,1,0,0,0,536,537,3,54,21, - 0,537,538,1,0,0,0,538,539,6,24,9,0,539,61,1,0,0,0,540,541,3,50,19,0,541, - 542,1,0,0,0,542,543,6,25,9,0,543,63,1,0,0,0,544,545,3,52,20,0,545,546,1, - 0,0,0,546,547,6,26,9,0,547,65,1,0,0,0,548,549,5,124,0,0,549,550,1,0,0,0, - 550,551,6,27,13,0,551,67,1,0,0,0,552,553,7,23,0,0,553,69,1,0,0,0,554,555, - 7,24,0,0,555,71,1,0,0,0,556,557,5,92,0,0,557,558,7,25,0,0,558,73,1,0,0, - 0,559,560,8,26,0,0,560,75,1,0,0,0,561,563,7,3,0,0,562,564,7,27,0,0,563, - 562,1,0,0,0,563,564,1,0,0,0,564,566,1,0,0,0,565,567,3,68,28,0,566,565,1, - 0,0,0,567,568,1,0,0,0,568,566,1,0,0,0,568,569,1,0,0,0,569,77,1,0,0,0,570, - 571,5,64,0,0,571,79,1,0,0,0,572,573,5,96,0,0,573,81,1,0,0,0,574,578,8,28, - 0,0,575,576,5,96,0,0,576,578,5,96,0,0,577,574,1,0,0,0,577,575,1,0,0,0,578, - 83,1,0,0,0,579,580,5,95,0,0,580,85,1,0,0,0,581,585,3,70,29,0,582,585,3, - 68,28,0,583,585,3,84,36,0,584,581,1,0,0,0,584,582,1,0,0,0,584,583,1,0,0, - 0,585,87,1,0,0,0,586,591,5,34,0,0,587,590,3,72,30,0,588,590,3,74,31,0,589, - 587,1,0,0,0,589,588,1,0,0,0,590,593,1,0,0,0,591,589,1,0,0,0,591,592,1,0, - 0,0,592,594,1,0,0,0,593,591,1,0,0,0,594,616,5,34,0,0,595,596,5,34,0,0,596, - 597,5,34,0,0,597,598,5,34,0,0,598,602,1,0,0,0,599,601,8,21,0,0,600,599, - 1,0,0,0,601,604,1,0,0,0,602,603,1,0,0,0,602,600,1,0,0,0,603,605,1,0,0,0, - 604,602,1,0,0,0,605,606,5,34,0,0,606,607,5,34,0,0,607,608,5,34,0,0,608, - 610,1,0,0,0,609,611,5,34,0,0,610,609,1,0,0,0,610,611,1,0,0,0,611,613,1, - 0,0,0,612,614,5,34,0,0,613,612,1,0,0,0,613,614,1,0,0,0,614,616,1,0,0,0, - 615,586,1,0,0,0,615,595,1,0,0,0,616,89,1,0,0,0,617,619,3,68,28,0,618,617, - 1,0,0,0,619,620,1,0,0,0,620,618,1,0,0,0,620,621,1,0,0,0,621,91,1,0,0,0, - 622,624,3,68,28,0,623,622,1,0,0,0,624,625,1,0,0,0,625,623,1,0,0,0,625,626, - 1,0,0,0,626,627,1,0,0,0,627,631,3,108,48,0,628,630,3,68,28,0,629,628,1, - 0,0,0,630,633,1,0,0,0,631,629,1,0,0,0,631,632,1,0,0,0,632,665,1,0,0,0,633, - 631,1,0,0,0,634,636,3,108,48,0,635,637,3,68,28,0,636,635,1,0,0,0,637,638, - 1,0,0,0,638,636,1,0,0,0,638,639,1,0,0,0,639,665,1,0,0,0,640,642,3,68,28, - 0,641,640,1,0,0,0,642,643,1,0,0,0,643,641,1,0,0,0,643,644,1,0,0,0,644,652, - 1,0,0,0,645,649,3,108,48,0,646,648,3,68,28,0,647,646,1,0,0,0,648,651,1, - 0,0,0,649,647,1,0,0,0,649,650,1,0,0,0,650,653,1,0,0,0,651,649,1,0,0,0,652, - 645,1,0,0,0,652,653,1,0,0,0,653,654,1,0,0,0,654,655,3,76,32,0,655,665,1, - 0,0,0,656,658,3,108,48,0,657,659,3,68,28,0,658,657,1,0,0,0,659,660,1,0, - 0,0,660,658,1,0,0,0,660,661,1,0,0,0,661,662,1,0,0,0,662,663,3,76,32,0,663, - 665,1,0,0,0,664,623,1,0,0,0,664,634,1,0,0,0,664,641,1,0,0,0,664,656,1,0, - 0,0,665,93,1,0,0,0,666,667,7,29,0,0,667,668,7,30,0,0,668,95,1,0,0,0,669, - 670,7,12,0,0,670,671,7,9,0,0,671,672,7,0,0,0,672,97,1,0,0,0,673,674,7,12, - 0,0,674,675,7,2,0,0,675,676,7,4,0,0,676,99,1,0,0,0,677,678,5,61,0,0,678, - 101,1,0,0,0,679,680,5,58,0,0,680,681,5,58,0,0,681,103,1,0,0,0,682,683,5, - 44,0,0,683,105,1,0,0,0,684,685,7,0,0,0,685,686,7,3,0,0,686,687,7,2,0,0, - 687,688,7,4,0,0,688,107,1,0,0,0,689,690,5,46,0,0,690,109,1,0,0,0,691,692, - 7,15,0,0,692,693,7,12,0,0,693,694,7,13,0,0,694,695,7,2,0,0,695,696,7,3, - 0,0,696,111,1,0,0,0,697,698,7,15,0,0,698,699,7,1,0,0,699,700,7,6,0,0,700, - 701,7,2,0,0,701,702,7,5,0,0,702,113,1,0,0,0,703,704,7,13,0,0,704,705,7, - 12,0,0,705,706,7,2,0,0,706,707,7,5,0,0,707,115,1,0,0,0,708,709,5,40,0,0, - 709,117,1,0,0,0,710,711,7,1,0,0,711,712,7,9,0,0,712,119,1,0,0,0,713,714, - 7,1,0,0,714,715,7,2,0,0,715,121,1,0,0,0,716,717,7,13,0,0,717,718,7,1,0, - 0,718,719,7,18,0,0,719,720,7,3,0,0,720,123,1,0,0,0,721,722,7,9,0,0,722, - 723,7,7,0,0,723,724,7,5,0,0,724,125,1,0,0,0,725,726,7,9,0,0,726,727,7,31, - 0,0,727,728,7,13,0,0,728,729,7,13,0,0,729,127,1,0,0,0,730,731,7,9,0,0,731, - 732,7,31,0,0,732,733,7,13,0,0,733,734,7,13,0,0,734,735,7,2,0,0,735,129, - 1,0,0,0,736,737,7,7,0,0,737,738,7,6,0,0,738,131,1,0,0,0,739,740,5,63,0, - 0,740,133,1,0,0,0,741,742,7,6,0,0,742,743,7,13,0,0,743,744,7,1,0,0,744, - 745,7,18,0,0,745,746,7,3,0,0,746,135,1,0,0,0,747,748,5,41,0,0,748,137,1, - 0,0,0,749,750,7,5,0,0,750,751,7,6,0,0,751,752,7,31,0,0,752,753,7,3,0,0, - 753,139,1,0,0,0,754,755,5,61,0,0,755,756,5,61,0,0,756,141,1,0,0,0,757,758, - 5,61,0,0,758,759,5,126,0,0,759,143,1,0,0,0,760,761,5,33,0,0,761,762,5,61, - 0,0,762,145,1,0,0,0,763,764,5,60,0,0,764,147,1,0,0,0,765,766,5,60,0,0,766, - 767,5,61,0,0,767,149,1,0,0,0,768,769,5,62,0,0,769,151,1,0,0,0,770,771,5, - 62,0,0,771,772,5,61,0,0,772,153,1,0,0,0,773,774,5,43,0,0,774,155,1,0,0, - 0,775,776,5,45,0,0,776,157,1,0,0,0,777,778,5,42,0,0,778,159,1,0,0,0,779, - 780,5,47,0,0,780,161,1,0,0,0,781,782,5,37,0,0,782,163,1,0,0,0,783,784,5, - 91,0,0,784,785,1,0,0,0,785,786,6,76,0,0,786,787,6,76,0,0,787,165,1,0,0, - 0,788,789,5,93,0,0,789,790,1,0,0,0,790,791,6,77,13,0,791,792,6,77,13,0, - 792,167,1,0,0,0,793,797,3,70,29,0,794,796,3,86,37,0,795,794,1,0,0,0,796, - 799,1,0,0,0,797,795,1,0,0,0,797,798,1,0,0,0,798,810,1,0,0,0,799,797,1,0, - 0,0,800,803,3,84,36,0,801,803,3,78,33,0,802,800,1,0,0,0,802,801,1,0,0,0, - 803,805,1,0,0,0,804,806,3,86,37,0,805,804,1,0,0,0,806,807,1,0,0,0,807,805, - 1,0,0,0,807,808,1,0,0,0,808,810,1,0,0,0,809,793,1,0,0,0,809,802,1,0,0,0, - 810,169,1,0,0,0,811,813,3,80,34,0,812,814,3,82,35,0,813,812,1,0,0,0,814, - 815,1,0,0,0,815,813,1,0,0,0,815,816,1,0,0,0,816,817,1,0,0,0,817,818,3,80, - 34,0,818,171,1,0,0,0,819,820,3,170,79,0,820,173,1,0,0,0,821,822,3,50,19, - 0,822,823,1,0,0,0,823,824,6,81,9,0,824,175,1,0,0,0,825,826,3,52,20,0,826, - 827,1,0,0,0,827,828,6,82,9,0,828,177,1,0,0,0,829,830,3,54,21,0,830,831, - 1,0,0,0,831,832,6,83,9,0,832,179,1,0,0,0,833,834,3,66,27,0,834,835,1,0, - 0,0,835,836,6,84,12,0,836,837,6,84,13,0,837,181,1,0,0,0,838,839,3,164,76, - 0,839,840,1,0,0,0,840,841,6,85,10,0,841,183,1,0,0,0,842,843,3,166,77,0, - 843,844,1,0,0,0,844,845,6,86,14,0,845,185,1,0,0,0,846,847,3,104,46,0,847, - 848,1,0,0,0,848,849,6,87,15,0,849,187,1,0,0,0,850,851,3,100,44,0,851,852, - 1,0,0,0,852,853,6,88,16,0,853,189,1,0,0,0,854,855,3,88,38,0,855,856,1,0, - 0,0,856,857,6,89,17,0,857,191,1,0,0,0,858,859,7,7,0,0,859,860,7,8,0,0,860, - 861,7,5,0,0,861,862,7,1,0,0,862,863,7,7,0,0,863,864,7,9,0,0,864,865,7,2, - 0,0,865,193,1,0,0,0,866,867,7,16,0,0,867,868,7,3,0,0,868,869,7,5,0,0,869, - 870,7,12,0,0,870,871,7,0,0,0,871,872,7,12,0,0,872,873,7,5,0,0,873,874,7, - 12,0,0,874,195,1,0,0,0,875,879,8,32,0,0,876,877,5,47,0,0,877,879,8,33,0, - 0,878,875,1,0,0,0,878,876,1,0,0,0,879,197,1,0,0,0,880,882,3,196,92,0,881, - 880,1,0,0,0,882,883,1,0,0,0,883,881,1,0,0,0,883,884,1,0,0,0,884,199,1,0, - 0,0,885,886,3,50,19,0,886,887,1,0,0,0,887,888,6,94,9,0,888,201,1,0,0,0, - 889,890,3,52,20,0,890,891,1,0,0,0,891,892,6,95,9,0,892,203,1,0,0,0,893, - 894,3,54,21,0,894,895,1,0,0,0,895,896,6,96,9,0,896,205,1,0,0,0,897,898, - 3,66,27,0,898,899,1,0,0,0,899,900,6,97,12,0,900,901,6,97,13,0,901,207,1, - 0,0,0,902,903,3,108,48,0,903,904,1,0,0,0,904,905,6,98,18,0,905,209,1,0, - 0,0,906,907,3,104,46,0,907,908,1,0,0,0,908,909,6,99,15,0,909,211,1,0,0, - 0,910,915,3,70,29,0,911,915,3,68,28,0,912,915,3,84,36,0,913,915,3,158,73, - 0,914,910,1,0,0,0,914,911,1,0,0,0,914,912,1,0,0,0,914,913,1,0,0,0,915,213, - 1,0,0,0,916,919,3,70,29,0,917,919,3,158,73,0,918,916,1,0,0,0,918,917,1, - 0,0,0,919,923,1,0,0,0,920,922,3,212,100,0,921,920,1,0,0,0,922,925,1,0,0, - 0,923,921,1,0,0,0,923,924,1,0,0,0,924,936,1,0,0,0,925,923,1,0,0,0,926,929, - 3,84,36,0,927,929,3,78,33,0,928,926,1,0,0,0,928,927,1,0,0,0,929,931,1,0, - 0,0,930,932,3,212,100,0,931,930,1,0,0,0,932,933,1,0,0,0,933,931,1,0,0,0, - 933,934,1,0,0,0,934,936,1,0,0,0,935,918,1,0,0,0,935,928,1,0,0,0,936,215, - 1,0,0,0,937,940,3,214,101,0,938,940,3,170,79,0,939,937,1,0,0,0,939,938, - 1,0,0,0,940,941,1,0,0,0,941,939,1,0,0,0,941,942,1,0,0,0,942,217,1,0,0,0, - 943,944,3,50,19,0,944,945,1,0,0,0,945,946,6,103,9,0,946,219,1,0,0,0,947, - 948,3,52,20,0,948,949,1,0,0,0,949,950,6,104,9,0,950,221,1,0,0,0,951,952, - 3,54,21,0,952,953,1,0,0,0,953,954,6,105,9,0,954,223,1,0,0,0,955,956,3,66, - 27,0,956,957,1,0,0,0,957,958,6,106,12,0,958,959,6,106,13,0,959,225,1,0, - 0,0,960,961,3,100,44,0,961,962,1,0,0,0,962,963,6,107,16,0,963,227,1,0,0, - 0,964,965,3,104,46,0,965,966,1,0,0,0,966,967,6,108,15,0,967,229,1,0,0,0, - 968,969,3,108,48,0,969,970,1,0,0,0,970,971,6,109,18,0,971,231,1,0,0,0,972, - 973,7,12,0,0,973,974,7,2,0,0,974,233,1,0,0,0,975,976,3,216,102,0,976,977, - 1,0,0,0,977,978,6,111,19,0,978,235,1,0,0,0,979,980,3,50,19,0,980,981,1, - 0,0,0,981,982,6,112,9,0,982,237,1,0,0,0,983,984,3,52,20,0,984,985,1,0,0, - 0,985,986,6,113,9,0,986,239,1,0,0,0,987,988,3,54,21,0,988,989,1,0,0,0,989, - 990,6,114,9,0,990,241,1,0,0,0,991,992,3,66,27,0,992,993,1,0,0,0,993,994, - 6,115,12,0,994,995,6,115,13,0,995,243,1,0,0,0,996,997,3,164,76,0,997,998, - 1,0,0,0,998,999,6,116,10,0,999,1000,6,116,20,0,1000,245,1,0,0,0,1001,1002, - 7,7,0,0,1002,1003,7,9,0,0,1003,1004,1,0,0,0,1004,1005,6,117,21,0,1005,247, - 1,0,0,0,1006,1007,7,19,0,0,1007,1008,7,1,0,0,1008,1009,7,5,0,0,1009,1010, - 7,10,0,0,1010,1011,1,0,0,0,1011,1012,6,118,21,0,1012,249,1,0,0,0,1013,1014, - 8,34,0,0,1014,251,1,0,0,0,1015,1017,3,250,119,0,1016,1015,1,0,0,0,1017, - 1018,1,0,0,0,1018,1016,1,0,0,0,1018,1019,1,0,0,0,1019,1020,1,0,0,0,1020, - 1021,3,320,154,0,1021,1023,1,0,0,0,1022,1016,1,0,0,0,1022,1023,1,0,0,0, - 1023,1025,1,0,0,0,1024,1026,3,250,119,0,1025,1024,1,0,0,0,1026,1027,1,0, - 0,0,1027,1025,1,0,0,0,1027,1028,1,0,0,0,1028,253,1,0,0,0,1029,1030,3,172, - 80,0,1030,1031,1,0,0,0,1031,1032,6,121,22,0,1032,255,1,0,0,0,1033,1034, - 3,252,120,0,1034,1035,1,0,0,0,1035,1036,6,122,23,0,1036,257,1,0,0,0,1037, - 1038,3,50,19,0,1038,1039,1,0,0,0,1039,1040,6,123,9,0,1040,259,1,0,0,0,1041, - 1042,3,52,20,0,1042,1043,1,0,0,0,1043,1044,6,124,9,0,1044,261,1,0,0,0,1045, - 1046,3,54,21,0,1046,1047,1,0,0,0,1047,1048,6,125,9,0,1048,263,1,0,0,0,1049, - 1050,3,66,27,0,1050,1051,1,0,0,0,1051,1052,6,126,12,0,1052,1053,6,126,13, - 0,1053,1054,6,126,13,0,1054,265,1,0,0,0,1055,1056,3,100,44,0,1056,1057, - 1,0,0,0,1057,1058,6,127,16,0,1058,267,1,0,0,0,1059,1060,3,104,46,0,1060, - 1061,1,0,0,0,1061,1062,6,128,15,0,1062,269,1,0,0,0,1063,1064,3,108,48,0, - 1064,1065,1,0,0,0,1065,1066,6,129,18,0,1066,271,1,0,0,0,1067,1068,3,248, - 118,0,1068,1069,1,0,0,0,1069,1070,6,130,24,0,1070,273,1,0,0,0,1071,1072, - 3,216,102,0,1072,1073,1,0,0,0,1073,1074,6,131,19,0,1074,275,1,0,0,0,1075, - 1076,3,172,80,0,1076,1077,1,0,0,0,1077,1078,6,132,22,0,1078,277,1,0,0,0, - 1079,1080,3,50,19,0,1080,1081,1,0,0,0,1081,1082,6,133,9,0,1082,279,1,0, - 0,0,1083,1084,3,52,20,0,1084,1085,1,0,0,0,1085,1086,6,134,9,0,1086,281, - 1,0,0,0,1087,1088,3,54,21,0,1088,1089,1,0,0,0,1089,1090,6,135,9,0,1090, - 283,1,0,0,0,1091,1092,3,66,27,0,1092,1093,1,0,0,0,1093,1094,6,136,12,0, - 1094,1095,6,136,13,0,1095,285,1,0,0,0,1096,1097,3,108,48,0,1097,1098,1, - 0,0,0,1098,1099,6,137,18,0,1099,287,1,0,0,0,1100,1101,3,172,80,0,1101,1102, - 1,0,0,0,1102,1103,6,138,22,0,1103,289,1,0,0,0,1104,1105,3,168,78,0,1105, - 1106,1,0,0,0,1106,1107,6,139,25,0,1107,291,1,0,0,0,1108,1109,3,50,19,0, - 1109,1110,1,0,0,0,1110,1111,6,140,9,0,1111,293,1,0,0,0,1112,1113,3,52,20, - 0,1113,1114,1,0,0,0,1114,1115,6,141,9,0,1115,295,1,0,0,0,1116,1117,3,54, - 21,0,1117,1118,1,0,0,0,1118,1119,6,142,9,0,1119,297,1,0,0,0,1120,1121,3, - 66,27,0,1121,1122,1,0,0,0,1122,1123,6,143,12,0,1123,1124,6,143,13,0,1124, - 299,1,0,0,0,1125,1126,7,1,0,0,1126,1127,7,9,0,0,1127,1128,7,15,0,0,1128, - 1129,7,7,0,0,1129,301,1,0,0,0,1130,1131,3,50,19,0,1131,1132,1,0,0,0,1132, - 1133,6,145,9,0,1133,303,1,0,0,0,1134,1135,3,52,20,0,1135,1136,1,0,0,0,1136, - 1137,6,146,9,0,1137,305,1,0,0,0,1138,1139,3,54,21,0,1139,1140,1,0,0,0,1140, - 1141,6,147,9,0,1141,307,1,0,0,0,1142,1143,3,66,27,0,1143,1144,1,0,0,0,1144, - 1145,6,148,12,0,1145,1146,6,148,13,0,1146,309,1,0,0,0,1147,1148,7,15,0, - 0,1148,1149,7,31,0,0,1149,1150,7,9,0,0,1150,1151,7,4,0,0,1151,1152,7,5, - 0,0,1152,1153,7,1,0,0,1153,1154,7,7,0,0,1154,1155,7,9,0,0,1155,1156,7,2, - 0,0,1156,311,1,0,0,0,1157,1158,3,50,19,0,1158,1159,1,0,0,0,1159,1160,6, - 150,9,0,1160,313,1,0,0,0,1161,1162,3,52,20,0,1162,1163,1,0,0,0,1163,1164, - 6,151,9,0,1164,315,1,0,0,0,1165,1166,3,54,21,0,1166,1167,1,0,0,0,1167,1168, - 6,152,9,0,1168,317,1,0,0,0,1169,1170,3,166,77,0,1170,1171,1,0,0,0,1171, - 1172,6,153,14,0,1172,1173,6,153,13,0,1173,319,1,0,0,0,1174,1175,5,58,0, - 0,1175,321,1,0,0,0,1176,1182,3,78,33,0,1177,1182,3,68,28,0,1178,1182,3, - 108,48,0,1179,1182,3,70,29,0,1180,1182,3,84,36,0,1181,1176,1,0,0,0,1181, - 1177,1,0,0,0,1181,1178,1,0,0,0,1181,1179,1,0,0,0,1181,1180,1,0,0,0,1182, - 1183,1,0,0,0,1183,1181,1,0,0,0,1183,1184,1,0,0,0,1184,323,1,0,0,0,1185, - 1186,3,50,19,0,1186,1187,1,0,0,0,1187,1188,6,156,9,0,1188,325,1,0,0,0,1189, - 1190,3,52,20,0,1190,1191,1,0,0,0,1191,1192,6,157,9,0,1192,327,1,0,0,0,1193, - 1194,3,54,21,0,1194,1195,1,0,0,0,1195,1196,6,158,9,0,1196,329,1,0,0,0,58, - 0,1,2,3,4,5,6,7,8,9,10,11,483,493,497,500,509,511,522,563,568,577,584,589, - 591,602,610,613,615,620,625,631,638,643,649,652,660,664,797,802,807,809, - 815,878,883,914,918,923,928,933,935,939,941,1018,1022,1027,1181,1183,26, - 5,2,0,5,4,0,5,6,0,5,1,0,5,3,0,5,10,0,5,8,0,5,5,0,5,9,0,0,1,0,7,65,0,5,0, - 0,7,26,0,4,0,0,7,66,0,7,35,0,7,33,0,7,27,0,7,37,0,7,78,0,5,11,0,5,7,0,7, - 68,0,7,88,0,7,87,0,7,67,0]; + 7,152,2,153,7,153,2,154,7,154,2,155,7,155,2,156,7,156,2,157,7,157,1,0,1, + 0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,2,1, + 2,1,2,1,2,1,2,1,2,1,2,1,2,1,3,1,3,1,3,1,3,1,3,1,3,1,3,1,4,1,4,1,4,1,4,1, + 4,1,4,1,4,1,4,1,4,1,4,1,5,1,5,1,5,1,5,1,5,1,5,1,5,1,6,1,6,1,6,1,6,1,6,1, + 6,1,6,1,7,1,7,1,7,1,7,1,7,1,7,1,7,1,7,1,7,1,7,1,7,1,7,1,7,1,7,1,8,1,8,1, + 8,1,8,1,8,1,8,1,8,1,9,1,9,1,9,1,9,1,9,1,9,1,9,1,9,1,10,1,10,1,10,1,10,1, + 10,1,10,1,10,1,11,1,11,1,11,1,11,1,11,1,11,1,11,1,11,1,11,1,11,1,11,1,11, + 1,12,1,12,1,12,1,12,1,12,1,12,1,12,1,12,1,12,1,13,1,13,1,13,1,13,1,13,1, + 13,1,14,1,14,1,14,1,14,1,14,1,14,1,14,1,15,1,15,1,15,1,15,1,15,1,15,1,15, + 1,16,1,16,1,16,1,16,1,16,1,16,1,16,1,16,1,17,1,17,1,17,1,17,1,17,1,17,1, + 17,1,17,1,18,4,18,480,8,18,11,18,12,18,481,1,18,1,18,1,19,1,19,1,19,1,19, + 5,19,490,8,19,10,19,12,19,493,9,19,1,19,3,19,496,8,19,1,19,3,19,499,8,19, + 1,19,1,19,1,20,1,20,1,20,1,20,1,20,5,20,508,8,20,10,20,12,20,511,9,20,1, + 20,1,20,1,20,1,20,1,20,1,21,4,21,519,8,21,11,21,12,21,520,1,21,1,21,1,22, + 1,22,1,22,1,22,1,22,1,23,1,23,1,23,1,23,1,23,1,24,1,24,1,24,1,24,1,25,1, + 25,1,25,1,25,1,26,1,26,1,26,1,26,1,27,1,27,1,27,1,27,1,28,1,28,1,29,1,29, + 1,30,1,30,1,30,1,31,1,31,1,32,1,32,3,32,562,8,32,1,32,4,32,565,8,32,11, + 32,12,32,566,1,33,1,33,1,34,1,34,1,35,1,35,1,35,3,35,576,8,35,1,36,1,36, + 1,37,1,37,1,37,3,37,583,8,37,1,38,1,38,1,38,5,38,588,8,38,10,38,12,38,591, + 9,38,1,38,1,38,1,38,1,38,1,38,1,38,5,38,599,8,38,10,38,12,38,602,9,38,1, + 38,1,38,1,38,1,38,1,38,3,38,609,8,38,1,38,3,38,612,8,38,3,38,614,8,38,1, + 39,4,39,617,8,39,11,39,12,39,618,1,40,4,40,622,8,40,11,40,12,40,623,1,40, + 1,40,5,40,628,8,40,10,40,12,40,631,9,40,1,40,1,40,4,40,635,8,40,11,40,12, + 40,636,1,40,4,40,640,8,40,11,40,12,40,641,1,40,1,40,5,40,646,8,40,10,40, + 12,40,649,9,40,3,40,651,8,40,1,40,1,40,1,40,1,40,4,40,657,8,40,11,40,12, + 40,658,1,40,1,40,3,40,663,8,40,1,41,1,41,1,41,1,42,1,42,1,42,1,42,1,43, + 1,43,1,43,1,43,1,44,1,44,1,45,1,45,1,45,1,46,1,46,1,47,1,47,1,47,1,47,1, + 47,1,48,1,48,1,49,1,49,1,49,1,49,1,49,1,49,1,50,1,50,1,50,1,50,1,50,1,50, + 1,51,1,51,1,51,1,51,1,51,1,52,1,52,1,53,1,53,1,53,1,54,1,54,1,54,1,55,1, + 55,1,55,1,55,1,55,1,56,1,56,1,56,1,56,1,57,1,57,1,57,1,57,1,57,1,58,1,58, + 1,58,1,58,1,58,1,58,1,59,1,59,1,59,1,60,1,60,1,61,1,61,1,61,1,61,1,61,1, + 61,1,62,1,62,1,63,1,63,1,63,1,63,1,63,1,64,1,64,1,64,1,65,1,65,1,65,1,66, + 1,66,1,66,1,67,1,67,1,68,1,68,1,68,1,69,1,69,1,70,1,70,1,70,1,71,1,71,1, + 72,1,72,1,73,1,73,1,74,1,74,1,75,1,75,1,76,1,76,1,76,1,76,1,76,1,77,1,77, + 1,77,1,77,1,77,1,78,1,78,5,78,794,8,78,10,78,12,78,797,9,78,1,78,1,78,3, + 78,801,8,78,1,78,4,78,804,8,78,11,78,12,78,805,3,78,808,8,78,1,79,1,79, + 4,79,812,8,79,11,79,12,79,813,1,79,1,79,1,80,1,80,1,81,1,81,1,81,1,81,1, + 82,1,82,1,82,1,82,1,83,1,83,1,83,1,83,1,84,1,84,1,84,1,84,1,84,1,85,1,85, + 1,85,1,85,1,86,1,86,1,86,1,86,1,87,1,87,1,87,1,87,1,88,1,88,1,88,1,88,1, + 89,1,89,1,89,1,89,1,90,1,90,1,90,1,90,1,90,1,90,1,90,1,90,1,90,1,91,1,91, + 1,91,3,91,869,8,91,1,92,4,92,872,8,92,11,92,12,92,873,1,93,1,93,1,93,1, + 93,1,94,1,94,1,94,1,94,1,95,1,95,1,95,1,95,1,96,1,96,1,96,1,96,1,96,1,97, + 1,97,1,97,1,97,1,98,1,98,1,98,1,98,1,99,1,99,1,99,1,99,3,99,905,8,99,1, + 100,1,100,3,100,909,8,100,1,100,5,100,912,8,100,10,100,12,100,915,9,100, + 1,100,1,100,3,100,919,8,100,1,100,4,100,922,8,100,11,100,12,100,923,3,100, + 926,8,100,1,101,1,101,4,101,930,8,101,11,101,12,101,931,1,102,1,102,1,102, + 1,102,1,103,1,103,1,103,1,103,1,104,1,104,1,104,1,104,1,105,1,105,1,105, + 1,105,1,105,1,106,1,106,1,106,1,106,1,107,1,107,1,107,1,107,1,108,1,108, + 1,108,1,108,1,109,1,109,1,109,1,110,1,110,1,110,1,110,1,111,1,111,1,111, + 1,111,1,112,1,112,1,112,1,112,1,113,1,113,1,113,1,113,1,114,1,114,1,114, + 1,114,1,114,1,115,1,115,1,115,1,115,1,115,1,116,1,116,1,116,1,116,1,116, + 1,117,1,117,1,117,1,117,1,117,1,117,1,117,1,118,1,118,1,119,4,119,1007, + 8,119,11,119,12,119,1008,1,119,1,119,3,119,1013,8,119,1,119,4,119,1016, + 8,119,11,119,12,119,1017,1,120,1,120,1,120,1,120,1,121,1,121,1,121,1,121, + 1,122,1,122,1,122,1,122,1,123,1,123,1,123,1,123,1,124,1,124,1,124,1,124, + 1,125,1,125,1,125,1,125,1,125,1,125,1,126,1,126,1,126,1,126,1,127,1,127, + 1,127,1,127,1,128,1,128,1,128,1,128,1,129,1,129,1,129,1,129,1,130,1,130, + 1,130,1,130,1,131,1,131,1,131,1,131,1,132,1,132,1,132,1,132,1,133,1,133, + 1,133,1,133,1,134,1,134,1,134,1,134,1,135,1,135,1,135,1,135,1,135,1,136, + 1,136,1,136,1,136,1,137,1,137,1,137,1,137,1,138,1,138,1,138,1,138,1,139, + 1,139,1,139,1,139,1,140,1,140,1,140,1,140,1,141,1,141,1,141,1,141,1,142, + 1,142,1,142,1,142,1,142,1,143,1,143,1,143,1,143,1,143,1,144,1,144,1,144, + 1,144,1,145,1,145,1,145,1,145,1,146,1,146,1,146,1,146,1,147,1,147,1,147, + 1,147,1,147,1,148,1,148,1,148,1,148,1,148,1,148,1,148,1,148,1,148,1,148, + 1,149,1,149,1,149,1,149,1,150,1,150,1,150,1,150,1,151,1,151,1,151,1,151, + 1,152,1,152,1,152,1,152,1,152,1,153,1,153,1,154,1,154,1,154,1,154,1,154, + 4,154,1172,8,154,11,154,12,154,1173,1,155,1,155,1,155,1,155,1,156,1,156, + 1,156,1,156,1,157,1,157,1,157,1,157,2,509,600,0,158,12,1,14,2,16,3,18,4, + 20,5,22,6,24,7,26,8,28,9,30,10,32,11,34,12,36,13,38,14,40,15,42,16,44,17, + 46,18,48,19,50,20,52,21,54,22,56,0,58,0,60,23,62,24,64,25,66,26,68,0,70, + 0,72,0,74,0,76,0,78,0,80,0,82,0,84,0,86,0,88,27,90,28,92,29,94,30,96,31, + 98,32,100,33,102,34,104,35,106,36,108,37,110,38,112,39,114,40,116,41,118, + 42,120,43,122,44,124,45,126,46,128,47,130,48,132,49,134,50,136,51,138,52, + 140,53,142,54,144,55,146,56,148,57,150,58,152,59,154,60,156,61,158,62,160, + 63,162,64,164,65,166,66,168,67,170,0,172,68,174,69,176,70,178,71,180,0, + 182,0,184,0,186,0,188,0,190,0,192,72,194,0,196,73,198,74,200,75,202,76, + 204,0,206,0,208,0,210,0,212,0,214,77,216,78,218,79,220,80,222,0,224,0,226, + 0,228,0,230,81,232,0,234,82,236,83,238,84,240,0,242,0,244,85,246,86,248, + 0,250,87,252,0,254,0,256,88,258,89,260,90,262,0,264,0,266,0,268,0,270,0, + 272,0,274,0,276,91,278,92,280,93,282,0,284,0,286,0,288,0,290,94,292,95, + 294,96,296,0,298,97,300,98,302,99,304,100,306,0,308,101,310,102,312,103, + 314,104,316,0,318,105,320,106,322,107,324,108,326,109,12,0,1,2,3,4,5,6, + 7,8,9,10,11,35,2,0,68,68,100,100,2,0,73,73,105,105,2,0,83,83,115,115,2, + 0,69,69,101,101,2,0,67,67,99,99,2,0,84,84,116,116,2,0,82,82,114,114,2,0, + 79,79,111,111,2,0,80,80,112,112,2,0,78,78,110,110,2,0,72,72,104,104,2,0, + 86,86,118,118,2,0,65,65,97,97,2,0,76,76,108,108,2,0,88,88,120,120,2,0,70, + 70,102,102,2,0,77,77,109,109,2,0,71,71,103,103,2,0,75,75,107,107,2,0,87, + 87,119,119,6,0,9,10,13,13,32,32,47,47,91,91,93,93,2,0,10,10,13,13,3,0,9, + 10,13,13,32,32,1,0,48,57,2,0,65,90,97,122,8,0,34,34,78,78,82,82,84,84,92, + 92,110,110,114,114,116,116,4,0,10,10,13,13,34,34,92,92,2,0,43,43,45,45, + 1,0,96,96,2,0,66,66,98,98,2,0,89,89,121,121,2,0,85,85,117,117,10,0,9,10, + 13,13,32,32,44,44,47,47,61,61,91,91,93,93,96,96,124,124,2,0,42,42,47,47, + 11,0,9,10,13,13,32,32,34,35,44,44,47,47,58,58,60,60,62,63,92,92,124,124, + 1214,0,12,1,0,0,0,0,14,1,0,0,0,0,16,1,0,0,0,0,18,1,0,0,0,0,20,1,0,0,0,0, + 22,1,0,0,0,0,24,1,0,0,0,0,26,1,0,0,0,0,28,1,0,0,0,0,30,1,0,0,0,0,32,1,0, + 0,0,0,34,1,0,0,0,0,36,1,0,0,0,0,38,1,0,0,0,0,40,1,0,0,0,0,42,1,0,0,0,0, + 44,1,0,0,0,0,46,1,0,0,0,0,48,1,0,0,0,0,50,1,0,0,0,0,52,1,0,0,0,0,54,1,0, + 0,0,1,56,1,0,0,0,1,58,1,0,0,0,1,60,1,0,0,0,1,62,1,0,0,0,1,64,1,0,0,0,2, + 66,1,0,0,0,2,88,1,0,0,0,2,90,1,0,0,0,2,92,1,0,0,0,2,94,1,0,0,0,2,96,1,0, + 0,0,2,98,1,0,0,0,2,100,1,0,0,0,2,102,1,0,0,0,2,104,1,0,0,0,2,106,1,0,0, + 0,2,108,1,0,0,0,2,110,1,0,0,0,2,112,1,0,0,0,2,114,1,0,0,0,2,116,1,0,0,0, + 2,118,1,0,0,0,2,120,1,0,0,0,2,122,1,0,0,0,2,124,1,0,0,0,2,126,1,0,0,0,2, + 128,1,0,0,0,2,130,1,0,0,0,2,132,1,0,0,0,2,134,1,0,0,0,2,136,1,0,0,0,2,138, + 1,0,0,0,2,140,1,0,0,0,2,142,1,0,0,0,2,144,1,0,0,0,2,146,1,0,0,0,2,148,1, + 0,0,0,2,150,1,0,0,0,2,152,1,0,0,0,2,154,1,0,0,0,2,156,1,0,0,0,2,158,1,0, + 0,0,2,160,1,0,0,0,2,162,1,0,0,0,2,164,1,0,0,0,2,166,1,0,0,0,2,168,1,0,0, + 0,2,172,1,0,0,0,2,174,1,0,0,0,2,176,1,0,0,0,2,178,1,0,0,0,3,180,1,0,0,0, + 3,182,1,0,0,0,3,184,1,0,0,0,3,186,1,0,0,0,3,188,1,0,0,0,3,190,1,0,0,0,3, + 192,1,0,0,0,3,196,1,0,0,0,3,198,1,0,0,0,3,200,1,0,0,0,3,202,1,0,0,0,4,204, + 1,0,0,0,4,206,1,0,0,0,4,208,1,0,0,0,4,214,1,0,0,0,4,216,1,0,0,0,4,218,1, + 0,0,0,4,220,1,0,0,0,5,222,1,0,0,0,5,224,1,0,0,0,5,226,1,0,0,0,5,228,1,0, + 0,0,5,230,1,0,0,0,5,232,1,0,0,0,5,234,1,0,0,0,5,236,1,0,0,0,5,238,1,0,0, + 0,6,240,1,0,0,0,6,242,1,0,0,0,6,244,1,0,0,0,6,246,1,0,0,0,6,250,1,0,0,0, + 6,252,1,0,0,0,6,254,1,0,0,0,6,256,1,0,0,0,6,258,1,0,0,0,6,260,1,0,0,0,7, + 262,1,0,0,0,7,264,1,0,0,0,7,266,1,0,0,0,7,268,1,0,0,0,7,270,1,0,0,0,7,272, + 1,0,0,0,7,274,1,0,0,0,7,276,1,0,0,0,7,278,1,0,0,0,7,280,1,0,0,0,8,282,1, + 0,0,0,8,284,1,0,0,0,8,286,1,0,0,0,8,288,1,0,0,0,8,290,1,0,0,0,8,292,1,0, + 0,0,8,294,1,0,0,0,9,296,1,0,0,0,9,298,1,0,0,0,9,300,1,0,0,0,9,302,1,0,0, + 0,9,304,1,0,0,0,10,306,1,0,0,0,10,308,1,0,0,0,10,310,1,0,0,0,10,312,1,0, + 0,0,10,314,1,0,0,0,11,316,1,0,0,0,11,318,1,0,0,0,11,320,1,0,0,0,11,322, + 1,0,0,0,11,324,1,0,0,0,11,326,1,0,0,0,12,328,1,0,0,0,14,338,1,0,0,0,16, + 345,1,0,0,0,18,354,1,0,0,0,20,361,1,0,0,0,22,371,1,0,0,0,24,378,1,0,0,0, + 26,385,1,0,0,0,28,399,1,0,0,0,30,406,1,0,0,0,32,414,1,0,0,0,34,421,1,0, + 0,0,36,433,1,0,0,0,38,442,1,0,0,0,40,448,1,0,0,0,42,455,1,0,0,0,44,462, + 1,0,0,0,46,470,1,0,0,0,48,479,1,0,0,0,50,485,1,0,0,0,52,502,1,0,0,0,54, + 518,1,0,0,0,56,524,1,0,0,0,58,529,1,0,0,0,60,534,1,0,0,0,62,538,1,0,0,0, + 64,542,1,0,0,0,66,546,1,0,0,0,68,550,1,0,0,0,70,552,1,0,0,0,72,554,1,0, + 0,0,74,557,1,0,0,0,76,559,1,0,0,0,78,568,1,0,0,0,80,570,1,0,0,0,82,575, + 1,0,0,0,84,577,1,0,0,0,86,582,1,0,0,0,88,613,1,0,0,0,90,616,1,0,0,0,92, + 662,1,0,0,0,94,664,1,0,0,0,96,667,1,0,0,0,98,671,1,0,0,0,100,675,1,0,0, + 0,102,677,1,0,0,0,104,680,1,0,0,0,106,682,1,0,0,0,108,687,1,0,0,0,110,689, + 1,0,0,0,112,695,1,0,0,0,114,701,1,0,0,0,116,706,1,0,0,0,118,708,1,0,0,0, + 120,711,1,0,0,0,122,714,1,0,0,0,124,719,1,0,0,0,126,723,1,0,0,0,128,728, + 1,0,0,0,130,734,1,0,0,0,132,737,1,0,0,0,134,739,1,0,0,0,136,745,1,0,0,0, + 138,747,1,0,0,0,140,752,1,0,0,0,142,755,1,0,0,0,144,758,1,0,0,0,146,761, + 1,0,0,0,148,763,1,0,0,0,150,766,1,0,0,0,152,768,1,0,0,0,154,771,1,0,0,0, + 156,773,1,0,0,0,158,775,1,0,0,0,160,777,1,0,0,0,162,779,1,0,0,0,164,781, + 1,0,0,0,166,786,1,0,0,0,168,807,1,0,0,0,170,809,1,0,0,0,172,817,1,0,0,0, + 174,819,1,0,0,0,176,823,1,0,0,0,178,827,1,0,0,0,180,831,1,0,0,0,182,836, + 1,0,0,0,184,840,1,0,0,0,186,844,1,0,0,0,188,848,1,0,0,0,190,852,1,0,0,0, + 192,856,1,0,0,0,194,868,1,0,0,0,196,871,1,0,0,0,198,875,1,0,0,0,200,879, + 1,0,0,0,202,883,1,0,0,0,204,887,1,0,0,0,206,892,1,0,0,0,208,896,1,0,0,0, + 210,904,1,0,0,0,212,925,1,0,0,0,214,929,1,0,0,0,216,933,1,0,0,0,218,937, + 1,0,0,0,220,941,1,0,0,0,222,945,1,0,0,0,224,950,1,0,0,0,226,954,1,0,0,0, + 228,958,1,0,0,0,230,962,1,0,0,0,232,965,1,0,0,0,234,969,1,0,0,0,236,973, + 1,0,0,0,238,977,1,0,0,0,240,981,1,0,0,0,242,986,1,0,0,0,244,991,1,0,0,0, + 246,996,1,0,0,0,248,1003,1,0,0,0,250,1012,1,0,0,0,252,1019,1,0,0,0,254, + 1023,1,0,0,0,256,1027,1,0,0,0,258,1031,1,0,0,0,260,1035,1,0,0,0,262,1039, + 1,0,0,0,264,1045,1,0,0,0,266,1049,1,0,0,0,268,1053,1,0,0,0,270,1057,1,0, + 0,0,272,1061,1,0,0,0,274,1065,1,0,0,0,276,1069,1,0,0,0,278,1073,1,0,0,0, + 280,1077,1,0,0,0,282,1081,1,0,0,0,284,1086,1,0,0,0,286,1090,1,0,0,0,288, + 1094,1,0,0,0,290,1098,1,0,0,0,292,1102,1,0,0,0,294,1106,1,0,0,0,296,1110, + 1,0,0,0,298,1115,1,0,0,0,300,1120,1,0,0,0,302,1124,1,0,0,0,304,1128,1,0, + 0,0,306,1132,1,0,0,0,308,1137,1,0,0,0,310,1147,1,0,0,0,312,1151,1,0,0,0, + 314,1155,1,0,0,0,316,1159,1,0,0,0,318,1164,1,0,0,0,320,1171,1,0,0,0,322, + 1175,1,0,0,0,324,1179,1,0,0,0,326,1183,1,0,0,0,328,329,7,0,0,0,329,330, + 7,1,0,0,330,331,7,2,0,0,331,332,7,2,0,0,332,333,7,3,0,0,333,334,7,4,0,0, + 334,335,7,5,0,0,335,336,1,0,0,0,336,337,6,0,0,0,337,13,1,0,0,0,338,339, + 7,0,0,0,339,340,7,6,0,0,340,341,7,7,0,0,341,342,7,8,0,0,342,343,1,0,0,0, + 343,344,6,1,1,0,344,15,1,0,0,0,345,346,7,3,0,0,346,347,7,9,0,0,347,348, + 7,6,0,0,348,349,7,1,0,0,349,350,7,4,0,0,350,351,7,10,0,0,351,352,1,0,0, + 0,352,353,6,2,2,0,353,17,1,0,0,0,354,355,7,3,0,0,355,356,7,11,0,0,356,357, + 7,12,0,0,357,358,7,13,0,0,358,359,1,0,0,0,359,360,6,3,0,0,360,19,1,0,0, + 0,361,362,7,3,0,0,362,363,7,14,0,0,363,364,7,8,0,0,364,365,7,13,0,0,365, + 366,7,12,0,0,366,367,7,1,0,0,367,368,7,9,0,0,368,369,1,0,0,0,369,370,6, + 4,3,0,370,21,1,0,0,0,371,372,7,15,0,0,372,373,7,6,0,0,373,374,7,7,0,0,374, + 375,7,16,0,0,375,376,1,0,0,0,376,377,6,5,4,0,377,23,1,0,0,0,378,379,7,17, + 0,0,379,380,7,6,0,0,380,381,7,7,0,0,381,382,7,18,0,0,382,383,1,0,0,0,383, + 384,6,6,0,0,384,25,1,0,0,0,385,386,7,1,0,0,386,387,7,9,0,0,387,388,7,13, + 0,0,388,389,7,1,0,0,389,390,7,9,0,0,390,391,7,3,0,0,391,392,7,2,0,0,392, + 393,7,5,0,0,393,394,7,12,0,0,394,395,7,5,0,0,395,396,7,2,0,0,396,397,1, + 0,0,0,397,398,6,7,0,0,398,27,1,0,0,0,399,400,7,18,0,0,400,401,7,3,0,0,401, + 402,7,3,0,0,402,403,7,8,0,0,403,404,1,0,0,0,404,405,6,8,1,0,405,29,1,0, + 0,0,406,407,7,13,0,0,407,408,7,1,0,0,408,409,7,16,0,0,409,410,7,1,0,0,410, + 411,7,5,0,0,411,412,1,0,0,0,412,413,6,9,0,0,413,31,1,0,0,0,414,415,7,16, + 0,0,415,416,7,3,0,0,416,417,7,5,0,0,417,418,7,12,0,0,418,419,1,0,0,0,419, + 420,6,10,5,0,420,33,1,0,0,0,421,422,7,16,0,0,422,423,7,11,0,0,423,424,5, + 95,0,0,424,425,7,3,0,0,425,426,7,14,0,0,426,427,7,8,0,0,427,428,7,12,0, + 0,428,429,7,9,0,0,429,430,7,0,0,0,430,431,1,0,0,0,431,432,6,11,6,0,432, + 35,1,0,0,0,433,434,7,6,0,0,434,435,7,3,0,0,435,436,7,9,0,0,436,437,7,12, + 0,0,437,438,7,16,0,0,438,439,7,3,0,0,439,440,1,0,0,0,440,441,6,12,7,0,441, + 37,1,0,0,0,442,443,7,6,0,0,443,444,7,7,0,0,444,445,7,19,0,0,445,446,1,0, + 0,0,446,447,6,13,0,0,447,39,1,0,0,0,448,449,7,2,0,0,449,450,7,10,0,0,450, + 451,7,7,0,0,451,452,7,19,0,0,452,453,1,0,0,0,453,454,6,14,8,0,454,41,1, + 0,0,0,455,456,7,2,0,0,456,457,7,7,0,0,457,458,7,6,0,0,458,459,7,5,0,0,459, + 460,1,0,0,0,460,461,6,15,0,0,461,43,1,0,0,0,462,463,7,2,0,0,463,464,7,5, + 0,0,464,465,7,12,0,0,465,466,7,5,0,0,466,467,7,2,0,0,467,468,1,0,0,0,468, + 469,6,16,0,0,469,45,1,0,0,0,470,471,7,19,0,0,471,472,7,10,0,0,472,473,7, + 3,0,0,473,474,7,6,0,0,474,475,7,3,0,0,475,476,1,0,0,0,476,477,6,17,0,0, + 477,47,1,0,0,0,478,480,8,20,0,0,479,478,1,0,0,0,480,481,1,0,0,0,481,479, + 1,0,0,0,481,482,1,0,0,0,482,483,1,0,0,0,483,484,6,18,0,0,484,49,1,0,0,0, + 485,486,5,47,0,0,486,487,5,47,0,0,487,491,1,0,0,0,488,490,8,21,0,0,489, + 488,1,0,0,0,490,493,1,0,0,0,491,489,1,0,0,0,491,492,1,0,0,0,492,495,1,0, + 0,0,493,491,1,0,0,0,494,496,5,13,0,0,495,494,1,0,0,0,495,496,1,0,0,0,496, + 498,1,0,0,0,497,499,5,10,0,0,498,497,1,0,0,0,498,499,1,0,0,0,499,500,1, + 0,0,0,500,501,6,19,9,0,501,51,1,0,0,0,502,503,5,47,0,0,503,504,5,42,0,0, + 504,509,1,0,0,0,505,508,3,52,20,0,506,508,9,0,0,0,507,505,1,0,0,0,507,506, + 1,0,0,0,508,511,1,0,0,0,509,510,1,0,0,0,509,507,1,0,0,0,510,512,1,0,0,0, + 511,509,1,0,0,0,512,513,5,42,0,0,513,514,5,47,0,0,514,515,1,0,0,0,515,516, + 6,20,9,0,516,53,1,0,0,0,517,519,7,22,0,0,518,517,1,0,0,0,519,520,1,0,0, + 0,520,518,1,0,0,0,520,521,1,0,0,0,521,522,1,0,0,0,522,523,6,21,9,0,523, + 55,1,0,0,0,524,525,3,164,76,0,525,526,1,0,0,0,526,527,6,22,10,0,527,528, + 6,22,11,0,528,57,1,0,0,0,529,530,3,66,27,0,530,531,1,0,0,0,531,532,6,23, + 12,0,532,533,6,23,13,0,533,59,1,0,0,0,534,535,3,54,21,0,535,536,1,0,0,0, + 536,537,6,24,9,0,537,61,1,0,0,0,538,539,3,50,19,0,539,540,1,0,0,0,540,541, + 6,25,9,0,541,63,1,0,0,0,542,543,3,52,20,0,543,544,1,0,0,0,544,545,6,26, + 9,0,545,65,1,0,0,0,546,547,5,124,0,0,547,548,1,0,0,0,548,549,6,27,13,0, + 549,67,1,0,0,0,550,551,7,23,0,0,551,69,1,0,0,0,552,553,7,24,0,0,553,71, + 1,0,0,0,554,555,5,92,0,0,555,556,7,25,0,0,556,73,1,0,0,0,557,558,8,26,0, + 0,558,75,1,0,0,0,559,561,7,3,0,0,560,562,7,27,0,0,561,560,1,0,0,0,561,562, + 1,0,0,0,562,564,1,0,0,0,563,565,3,68,28,0,564,563,1,0,0,0,565,566,1,0,0, + 0,566,564,1,0,0,0,566,567,1,0,0,0,567,77,1,0,0,0,568,569,5,64,0,0,569,79, + 1,0,0,0,570,571,5,96,0,0,571,81,1,0,0,0,572,576,8,28,0,0,573,574,5,96,0, + 0,574,576,5,96,0,0,575,572,1,0,0,0,575,573,1,0,0,0,576,83,1,0,0,0,577,578, + 5,95,0,0,578,85,1,0,0,0,579,583,3,70,29,0,580,583,3,68,28,0,581,583,3,84, + 36,0,582,579,1,0,0,0,582,580,1,0,0,0,582,581,1,0,0,0,583,87,1,0,0,0,584, + 589,5,34,0,0,585,588,3,72,30,0,586,588,3,74,31,0,587,585,1,0,0,0,587,586, + 1,0,0,0,588,591,1,0,0,0,589,587,1,0,0,0,589,590,1,0,0,0,590,592,1,0,0,0, + 591,589,1,0,0,0,592,614,5,34,0,0,593,594,5,34,0,0,594,595,5,34,0,0,595, + 596,5,34,0,0,596,600,1,0,0,0,597,599,8,21,0,0,598,597,1,0,0,0,599,602,1, + 0,0,0,600,601,1,0,0,0,600,598,1,0,0,0,601,603,1,0,0,0,602,600,1,0,0,0,603, + 604,5,34,0,0,604,605,5,34,0,0,605,606,5,34,0,0,606,608,1,0,0,0,607,609, + 5,34,0,0,608,607,1,0,0,0,608,609,1,0,0,0,609,611,1,0,0,0,610,612,5,34,0, + 0,611,610,1,0,0,0,611,612,1,0,0,0,612,614,1,0,0,0,613,584,1,0,0,0,613,593, + 1,0,0,0,614,89,1,0,0,0,615,617,3,68,28,0,616,615,1,0,0,0,617,618,1,0,0, + 0,618,616,1,0,0,0,618,619,1,0,0,0,619,91,1,0,0,0,620,622,3,68,28,0,621, + 620,1,0,0,0,622,623,1,0,0,0,623,621,1,0,0,0,623,624,1,0,0,0,624,625,1,0, + 0,0,625,629,3,108,48,0,626,628,3,68,28,0,627,626,1,0,0,0,628,631,1,0,0, + 0,629,627,1,0,0,0,629,630,1,0,0,0,630,663,1,0,0,0,631,629,1,0,0,0,632,634, + 3,108,48,0,633,635,3,68,28,0,634,633,1,0,0,0,635,636,1,0,0,0,636,634,1, + 0,0,0,636,637,1,0,0,0,637,663,1,0,0,0,638,640,3,68,28,0,639,638,1,0,0,0, + 640,641,1,0,0,0,641,639,1,0,0,0,641,642,1,0,0,0,642,650,1,0,0,0,643,647, + 3,108,48,0,644,646,3,68,28,0,645,644,1,0,0,0,646,649,1,0,0,0,647,645,1, + 0,0,0,647,648,1,0,0,0,648,651,1,0,0,0,649,647,1,0,0,0,650,643,1,0,0,0,650, + 651,1,0,0,0,651,652,1,0,0,0,652,653,3,76,32,0,653,663,1,0,0,0,654,656,3, + 108,48,0,655,657,3,68,28,0,656,655,1,0,0,0,657,658,1,0,0,0,658,656,1,0, + 0,0,658,659,1,0,0,0,659,660,1,0,0,0,660,661,3,76,32,0,661,663,1,0,0,0,662, + 621,1,0,0,0,662,632,1,0,0,0,662,639,1,0,0,0,662,654,1,0,0,0,663,93,1,0, + 0,0,664,665,7,29,0,0,665,666,7,30,0,0,666,95,1,0,0,0,667,668,7,12,0,0,668, + 669,7,9,0,0,669,670,7,0,0,0,670,97,1,0,0,0,671,672,7,12,0,0,672,673,7,2, + 0,0,673,674,7,4,0,0,674,99,1,0,0,0,675,676,5,61,0,0,676,101,1,0,0,0,677, + 678,5,58,0,0,678,679,5,58,0,0,679,103,1,0,0,0,680,681,5,44,0,0,681,105, + 1,0,0,0,682,683,7,0,0,0,683,684,7,3,0,0,684,685,7,2,0,0,685,686,7,4,0,0, + 686,107,1,0,0,0,687,688,5,46,0,0,688,109,1,0,0,0,689,690,7,15,0,0,690,691, + 7,12,0,0,691,692,7,13,0,0,692,693,7,2,0,0,693,694,7,3,0,0,694,111,1,0,0, + 0,695,696,7,15,0,0,696,697,7,1,0,0,697,698,7,6,0,0,698,699,7,2,0,0,699, + 700,7,5,0,0,700,113,1,0,0,0,701,702,7,13,0,0,702,703,7,12,0,0,703,704,7, + 2,0,0,704,705,7,5,0,0,705,115,1,0,0,0,706,707,5,40,0,0,707,117,1,0,0,0, + 708,709,7,1,0,0,709,710,7,9,0,0,710,119,1,0,0,0,711,712,7,1,0,0,712,713, + 7,2,0,0,713,121,1,0,0,0,714,715,7,13,0,0,715,716,7,1,0,0,716,717,7,18,0, + 0,717,718,7,3,0,0,718,123,1,0,0,0,719,720,7,9,0,0,720,721,7,7,0,0,721,722, + 7,5,0,0,722,125,1,0,0,0,723,724,7,9,0,0,724,725,7,31,0,0,725,726,7,13,0, + 0,726,727,7,13,0,0,727,127,1,0,0,0,728,729,7,9,0,0,729,730,7,31,0,0,730, + 731,7,13,0,0,731,732,7,13,0,0,732,733,7,2,0,0,733,129,1,0,0,0,734,735,7, + 7,0,0,735,736,7,6,0,0,736,131,1,0,0,0,737,738,5,63,0,0,738,133,1,0,0,0, + 739,740,7,6,0,0,740,741,7,13,0,0,741,742,7,1,0,0,742,743,7,18,0,0,743,744, + 7,3,0,0,744,135,1,0,0,0,745,746,5,41,0,0,746,137,1,0,0,0,747,748,7,5,0, + 0,748,749,7,6,0,0,749,750,7,31,0,0,750,751,7,3,0,0,751,139,1,0,0,0,752, + 753,5,61,0,0,753,754,5,61,0,0,754,141,1,0,0,0,755,756,5,61,0,0,756,757, + 5,126,0,0,757,143,1,0,0,0,758,759,5,33,0,0,759,760,5,61,0,0,760,145,1,0, + 0,0,761,762,5,60,0,0,762,147,1,0,0,0,763,764,5,60,0,0,764,765,5,61,0,0, + 765,149,1,0,0,0,766,767,5,62,0,0,767,151,1,0,0,0,768,769,5,62,0,0,769,770, + 5,61,0,0,770,153,1,0,0,0,771,772,5,43,0,0,772,155,1,0,0,0,773,774,5,45, + 0,0,774,157,1,0,0,0,775,776,5,42,0,0,776,159,1,0,0,0,777,778,5,47,0,0,778, + 161,1,0,0,0,779,780,5,37,0,0,780,163,1,0,0,0,781,782,5,91,0,0,782,783,1, + 0,0,0,783,784,6,76,0,0,784,785,6,76,0,0,785,165,1,0,0,0,786,787,5,93,0, + 0,787,788,1,0,0,0,788,789,6,77,13,0,789,790,6,77,13,0,790,167,1,0,0,0,791, + 795,3,70,29,0,792,794,3,86,37,0,793,792,1,0,0,0,794,797,1,0,0,0,795,793, + 1,0,0,0,795,796,1,0,0,0,796,808,1,0,0,0,797,795,1,0,0,0,798,801,3,84,36, + 0,799,801,3,78,33,0,800,798,1,0,0,0,800,799,1,0,0,0,801,803,1,0,0,0,802, + 804,3,86,37,0,803,802,1,0,0,0,804,805,1,0,0,0,805,803,1,0,0,0,805,806,1, + 0,0,0,806,808,1,0,0,0,807,791,1,0,0,0,807,800,1,0,0,0,808,169,1,0,0,0,809, + 811,3,80,34,0,810,812,3,82,35,0,811,810,1,0,0,0,812,813,1,0,0,0,813,811, + 1,0,0,0,813,814,1,0,0,0,814,815,1,0,0,0,815,816,3,80,34,0,816,171,1,0,0, + 0,817,818,3,170,79,0,818,173,1,0,0,0,819,820,3,50,19,0,820,821,1,0,0,0, + 821,822,6,81,9,0,822,175,1,0,0,0,823,824,3,52,20,0,824,825,1,0,0,0,825, + 826,6,82,9,0,826,177,1,0,0,0,827,828,3,54,21,0,828,829,1,0,0,0,829,830, + 6,83,9,0,830,179,1,0,0,0,831,832,3,66,27,0,832,833,1,0,0,0,833,834,6,84, + 12,0,834,835,6,84,13,0,835,181,1,0,0,0,836,837,3,164,76,0,837,838,1,0,0, + 0,838,839,6,85,10,0,839,183,1,0,0,0,840,841,3,166,77,0,841,842,1,0,0,0, + 842,843,6,86,14,0,843,185,1,0,0,0,844,845,3,104,46,0,845,846,1,0,0,0,846, + 847,6,87,15,0,847,187,1,0,0,0,848,849,3,100,44,0,849,850,1,0,0,0,850,851, + 6,88,16,0,851,189,1,0,0,0,852,853,3,88,38,0,853,854,1,0,0,0,854,855,6,89, + 17,0,855,191,1,0,0,0,856,857,7,16,0,0,857,858,7,3,0,0,858,859,7,5,0,0,859, + 860,7,12,0,0,860,861,7,0,0,0,861,862,7,12,0,0,862,863,7,5,0,0,863,864,7, + 12,0,0,864,193,1,0,0,0,865,869,8,32,0,0,866,867,5,47,0,0,867,869,8,33,0, + 0,868,865,1,0,0,0,868,866,1,0,0,0,869,195,1,0,0,0,870,872,3,194,91,0,871, + 870,1,0,0,0,872,873,1,0,0,0,873,871,1,0,0,0,873,874,1,0,0,0,874,197,1,0, + 0,0,875,876,3,50,19,0,876,877,1,0,0,0,877,878,6,93,9,0,878,199,1,0,0,0, + 879,880,3,52,20,0,880,881,1,0,0,0,881,882,6,94,9,0,882,201,1,0,0,0,883, + 884,3,54,21,0,884,885,1,0,0,0,885,886,6,95,9,0,886,203,1,0,0,0,887,888, + 3,66,27,0,888,889,1,0,0,0,889,890,6,96,12,0,890,891,6,96,13,0,891,205,1, + 0,0,0,892,893,3,108,48,0,893,894,1,0,0,0,894,895,6,97,18,0,895,207,1,0, + 0,0,896,897,3,104,46,0,897,898,1,0,0,0,898,899,6,98,15,0,899,209,1,0,0, + 0,900,905,3,70,29,0,901,905,3,68,28,0,902,905,3,84,36,0,903,905,3,158,73, + 0,904,900,1,0,0,0,904,901,1,0,0,0,904,902,1,0,0,0,904,903,1,0,0,0,905,211, + 1,0,0,0,906,909,3,70,29,0,907,909,3,158,73,0,908,906,1,0,0,0,908,907,1, + 0,0,0,909,913,1,0,0,0,910,912,3,210,99,0,911,910,1,0,0,0,912,915,1,0,0, + 0,913,911,1,0,0,0,913,914,1,0,0,0,914,926,1,0,0,0,915,913,1,0,0,0,916,919, + 3,84,36,0,917,919,3,78,33,0,918,916,1,0,0,0,918,917,1,0,0,0,919,921,1,0, + 0,0,920,922,3,210,99,0,921,920,1,0,0,0,922,923,1,0,0,0,923,921,1,0,0,0, + 923,924,1,0,0,0,924,926,1,0,0,0,925,908,1,0,0,0,925,918,1,0,0,0,926,213, + 1,0,0,0,927,930,3,212,100,0,928,930,3,170,79,0,929,927,1,0,0,0,929,928, + 1,0,0,0,930,931,1,0,0,0,931,929,1,0,0,0,931,932,1,0,0,0,932,215,1,0,0,0, + 933,934,3,50,19,0,934,935,1,0,0,0,935,936,6,102,9,0,936,217,1,0,0,0,937, + 938,3,52,20,0,938,939,1,0,0,0,939,940,6,103,9,0,940,219,1,0,0,0,941,942, + 3,54,21,0,942,943,1,0,0,0,943,944,6,104,9,0,944,221,1,0,0,0,945,946,3,66, + 27,0,946,947,1,0,0,0,947,948,6,105,12,0,948,949,6,105,13,0,949,223,1,0, + 0,0,950,951,3,100,44,0,951,952,1,0,0,0,952,953,6,106,16,0,953,225,1,0,0, + 0,954,955,3,104,46,0,955,956,1,0,0,0,956,957,6,107,15,0,957,227,1,0,0,0, + 958,959,3,108,48,0,959,960,1,0,0,0,960,961,6,108,18,0,961,229,1,0,0,0,962, + 963,7,12,0,0,963,964,7,2,0,0,964,231,1,0,0,0,965,966,3,214,101,0,966,967, + 1,0,0,0,967,968,6,110,19,0,968,233,1,0,0,0,969,970,3,50,19,0,970,971,1, + 0,0,0,971,972,6,111,9,0,972,235,1,0,0,0,973,974,3,52,20,0,974,975,1,0,0, + 0,975,976,6,112,9,0,976,237,1,0,0,0,977,978,3,54,21,0,978,979,1,0,0,0,979, + 980,6,113,9,0,980,239,1,0,0,0,981,982,3,66,27,0,982,983,1,0,0,0,983,984, + 6,114,12,0,984,985,6,114,13,0,985,241,1,0,0,0,986,987,3,164,76,0,987,988, + 1,0,0,0,988,989,6,115,10,0,989,990,6,115,20,0,990,243,1,0,0,0,991,992,7, + 7,0,0,992,993,7,9,0,0,993,994,1,0,0,0,994,995,6,116,21,0,995,245,1,0,0, + 0,996,997,7,19,0,0,997,998,7,1,0,0,998,999,7,5,0,0,999,1000,7,10,0,0,1000, + 1001,1,0,0,0,1001,1002,6,117,21,0,1002,247,1,0,0,0,1003,1004,8,34,0,0,1004, + 249,1,0,0,0,1005,1007,3,248,118,0,1006,1005,1,0,0,0,1007,1008,1,0,0,0,1008, + 1006,1,0,0,0,1008,1009,1,0,0,0,1009,1010,1,0,0,0,1010,1011,3,318,153,0, + 1011,1013,1,0,0,0,1012,1006,1,0,0,0,1012,1013,1,0,0,0,1013,1015,1,0,0,0, + 1014,1016,3,248,118,0,1015,1014,1,0,0,0,1016,1017,1,0,0,0,1017,1015,1,0, + 0,0,1017,1018,1,0,0,0,1018,251,1,0,0,0,1019,1020,3,172,80,0,1020,1021,1, + 0,0,0,1021,1022,6,120,22,0,1022,253,1,0,0,0,1023,1024,3,250,119,0,1024, + 1025,1,0,0,0,1025,1026,6,121,23,0,1026,255,1,0,0,0,1027,1028,3,50,19,0, + 1028,1029,1,0,0,0,1029,1030,6,122,9,0,1030,257,1,0,0,0,1031,1032,3,52,20, + 0,1032,1033,1,0,0,0,1033,1034,6,123,9,0,1034,259,1,0,0,0,1035,1036,3,54, + 21,0,1036,1037,1,0,0,0,1037,1038,6,124,9,0,1038,261,1,0,0,0,1039,1040,3, + 66,27,0,1040,1041,1,0,0,0,1041,1042,6,125,12,0,1042,1043,6,125,13,0,1043, + 1044,6,125,13,0,1044,263,1,0,0,0,1045,1046,3,100,44,0,1046,1047,1,0,0,0, + 1047,1048,6,126,16,0,1048,265,1,0,0,0,1049,1050,3,104,46,0,1050,1051,1, + 0,0,0,1051,1052,6,127,15,0,1052,267,1,0,0,0,1053,1054,3,108,48,0,1054,1055, + 1,0,0,0,1055,1056,6,128,18,0,1056,269,1,0,0,0,1057,1058,3,246,117,0,1058, + 1059,1,0,0,0,1059,1060,6,129,24,0,1060,271,1,0,0,0,1061,1062,3,214,101, + 0,1062,1063,1,0,0,0,1063,1064,6,130,19,0,1064,273,1,0,0,0,1065,1066,3,172, + 80,0,1066,1067,1,0,0,0,1067,1068,6,131,22,0,1068,275,1,0,0,0,1069,1070, + 3,50,19,0,1070,1071,1,0,0,0,1071,1072,6,132,9,0,1072,277,1,0,0,0,1073,1074, + 3,52,20,0,1074,1075,1,0,0,0,1075,1076,6,133,9,0,1076,279,1,0,0,0,1077,1078, + 3,54,21,0,1078,1079,1,0,0,0,1079,1080,6,134,9,0,1080,281,1,0,0,0,1081,1082, + 3,66,27,0,1082,1083,1,0,0,0,1083,1084,6,135,12,0,1084,1085,6,135,13,0,1085, + 283,1,0,0,0,1086,1087,3,108,48,0,1087,1088,1,0,0,0,1088,1089,6,136,18,0, + 1089,285,1,0,0,0,1090,1091,3,172,80,0,1091,1092,1,0,0,0,1092,1093,6,137, + 22,0,1093,287,1,0,0,0,1094,1095,3,168,78,0,1095,1096,1,0,0,0,1096,1097, + 6,138,25,0,1097,289,1,0,0,0,1098,1099,3,50,19,0,1099,1100,1,0,0,0,1100, + 1101,6,139,9,0,1101,291,1,0,0,0,1102,1103,3,52,20,0,1103,1104,1,0,0,0,1104, + 1105,6,140,9,0,1105,293,1,0,0,0,1106,1107,3,54,21,0,1107,1108,1,0,0,0,1108, + 1109,6,141,9,0,1109,295,1,0,0,0,1110,1111,3,66,27,0,1111,1112,1,0,0,0,1112, + 1113,6,142,12,0,1113,1114,6,142,13,0,1114,297,1,0,0,0,1115,1116,7,1,0,0, + 1116,1117,7,9,0,0,1117,1118,7,15,0,0,1118,1119,7,7,0,0,1119,299,1,0,0,0, + 1120,1121,3,50,19,0,1121,1122,1,0,0,0,1122,1123,6,144,9,0,1123,301,1,0, + 0,0,1124,1125,3,52,20,0,1125,1126,1,0,0,0,1126,1127,6,145,9,0,1127,303, + 1,0,0,0,1128,1129,3,54,21,0,1129,1130,1,0,0,0,1130,1131,6,146,9,0,1131, + 305,1,0,0,0,1132,1133,3,66,27,0,1133,1134,1,0,0,0,1134,1135,6,147,12,0, + 1135,1136,6,147,13,0,1136,307,1,0,0,0,1137,1138,7,15,0,0,1138,1139,7,31, + 0,0,1139,1140,7,9,0,0,1140,1141,7,4,0,0,1141,1142,7,5,0,0,1142,1143,7,1, + 0,0,1143,1144,7,7,0,0,1144,1145,7,9,0,0,1145,1146,7,2,0,0,1146,309,1,0, + 0,0,1147,1148,3,50,19,0,1148,1149,1,0,0,0,1149,1150,6,149,9,0,1150,311, + 1,0,0,0,1151,1152,3,52,20,0,1152,1153,1,0,0,0,1153,1154,6,150,9,0,1154, + 313,1,0,0,0,1155,1156,3,54,21,0,1156,1157,1,0,0,0,1157,1158,6,151,9,0,1158, + 315,1,0,0,0,1159,1160,3,166,77,0,1160,1161,1,0,0,0,1161,1162,6,152,14,0, + 1162,1163,6,152,13,0,1163,317,1,0,0,0,1164,1165,5,58,0,0,1165,319,1,0,0, + 0,1166,1172,3,78,33,0,1167,1172,3,68,28,0,1168,1172,3,108,48,0,1169,1172, + 3,70,29,0,1170,1172,3,84,36,0,1171,1166,1,0,0,0,1171,1167,1,0,0,0,1171, + 1168,1,0,0,0,1171,1169,1,0,0,0,1171,1170,1,0,0,0,1172,1173,1,0,0,0,1173, + 1171,1,0,0,0,1173,1174,1,0,0,0,1174,321,1,0,0,0,1175,1176,3,50,19,0,1176, + 1177,1,0,0,0,1177,1178,6,155,9,0,1178,323,1,0,0,0,1179,1180,3,52,20,0,1180, + 1181,1,0,0,0,1181,1182,6,156,9,0,1182,325,1,0,0,0,1183,1184,3,54,21,0,1184, + 1185,1,0,0,0,1185,1186,6,157,9,0,1186,327,1,0,0,0,58,0,1,2,3,4,5,6,7,8, + 9,10,11,481,491,495,498,507,509,520,561,566,575,582,587,589,600,608,611, + 613,618,623,629,636,641,647,650,658,662,795,800,805,807,813,868,873,904, + 908,913,918,923,925,929,931,1008,1012,1017,1171,1173,26,5,2,0,5,4,0,5,6, + 0,5,1,0,5,3,0,5,10,0,5,8,0,5,5,0,5,9,0,0,1,0,7,65,0,5,0,0,7,26,0,4,0,0, + 7,66,0,7,35,0,7,33,0,7,27,0,7,37,0,7,77,0,5,11,0,5,7,0,7,68,0,7,87,0,7, + 86,0,7,67,0]; private static __ATN: ATN; public static get _ATN(): ATN { diff --git a/packages/kbn-esql-ast/src/antlr/esql_parser.g4 b/packages/kbn-esql-ast/src/antlr/esql_parser.g4 index 6f445b0df1730..b3496a20e3b8f 100644 --- a/packages/kbn-esql-ast/src/antlr/esql_parser.g4 +++ b/packages/kbn-esql-ast/src/antlr/esql_parser.g4 @@ -7,14 +7,6 @@ // DO NOT MODIFY THIS FILE BY HAND. IT IS MANAGED BY A CI JOB. - -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - parser grammar esql_parser; options {tokenVocab=esql_lexer;} @@ -113,21 +105,13 @@ field ; fromCommand - : FROM fromIdentifier (COMMA fromIdentifier)* metadata? fromOptions? + : FROM fromIdentifier (COMMA fromIdentifier)* metadata? ; fromIdentifier : FROM_UNQUOTED_IDENTIFIER ; -fromOptions - : OPTIONS configOption (COMMA configOption)* - ; - -configOption - : string ASSIGN string - ; - metadata : metadataOption | deprecated_metadata diff --git a/packages/kbn-esql-ast/src/antlr/esql_parser.interp b/packages/kbn-esql-ast/src/antlr/esql_parser.interp index 2b887065985d3..04dbf1b4a43dd 100644 --- a/packages/kbn-esql-ast/src/antlr/esql_parser.interp +++ b/packages/kbn-esql-ast/src/antlr/esql_parser.interp @@ -71,7 +71,6 @@ null null null null -'options' 'metadata' null null @@ -184,7 +183,6 @@ QUOTED_IDENTIFIER EXPR_LINE_COMMENT EXPR_MULTILINE_COMMENT EXPR_WS -OPTIONS METADATA FROM_UNQUOTED_IDENTIFIER FROM_LINE_COMMENT @@ -242,8 +240,6 @@ fields field fromCommand fromIdentifier -fromOptions -configOption metadata metadataOption deprecated_metadata @@ -282,4 +278,4 @@ enrichWithClause atn: -[4, 1, 110, 543, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15, 2, 16, 7, 16, 2, 17, 7, 17, 2, 18, 7, 18, 2, 19, 7, 19, 2, 20, 7, 20, 2, 21, 7, 21, 2, 22, 7, 22, 2, 23, 7, 23, 2, 24, 7, 24, 2, 25, 7, 25, 2, 26, 7, 26, 2, 27, 7, 27, 2, 28, 7, 28, 2, 29, 7, 29, 2, 30, 7, 30, 2, 31, 7, 31, 2, 32, 7, 32, 2, 33, 7, 33, 2, 34, 7, 34, 2, 35, 7, 35, 2, 36, 7, 36, 2, 37, 7, 37, 2, 38, 7, 38, 2, 39, 7, 39, 2, 40, 7, 40, 2, 41, 7, 41, 2, 42, 7, 42, 2, 43, 7, 43, 2, 44, 7, 44, 2, 45, 7, 45, 2, 46, 7, 46, 2, 47, 7, 47, 2, 48, 7, 48, 2, 49, 7, 49, 2, 50, 7, 50, 2, 51, 7, 51, 2, 52, 7, 52, 2, 53, 7, 53, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 1, 118, 8, 1, 10, 1, 12, 1, 121, 9, 1, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 3, 2, 128, 8, 2, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 3, 3, 143, 8, 3, 1, 4, 1, 4, 1, 4, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 3, 5, 155, 8, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 5, 5, 162, 8, 5, 10, 5, 12, 5, 165, 9, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 3, 5, 172, 8, 5, 1, 5, 1, 5, 3, 5, 176, 8, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 5, 5, 184, 8, 5, 10, 5, 12, 5, 187, 9, 5, 1, 6, 1, 6, 3, 6, 191, 8, 6, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 3, 6, 198, 8, 6, 1, 6, 1, 6, 1, 6, 3, 6, 203, 8, 6, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 3, 7, 210, 8, 7, 1, 8, 1, 8, 1, 8, 1, 8, 3, 8, 216, 8, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 5, 8, 224, 8, 8, 10, 8, 12, 8, 227, 9, 8, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 3, 9, 237, 8, 9, 1, 9, 1, 9, 1, 9, 5, 9, 242, 8, 9, 10, 9, 12, 9, 245, 9, 9, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 5, 10, 253, 8, 10, 10, 10, 12, 10, 256, 9, 10, 3, 10, 258, 8, 10, 1, 10, 1, 10, 1, 11, 1, 11, 1, 12, 1, 12, 1, 12, 1, 13, 1, 13, 1, 13, 5, 13, 270, 8, 13, 10, 13, 12, 13, 273, 9, 13, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 3, 14, 280, 8, 14, 1, 15, 1, 15, 1, 15, 1, 15, 5, 15, 286, 8, 15, 10, 15, 12, 15, 289, 9, 15, 1, 15, 3, 15, 292, 8, 15, 1, 15, 3, 15, 295, 8, 15, 1, 16, 1, 16, 1, 17, 1, 17, 1, 17, 1, 17, 5, 17, 303, 8, 17, 10, 17, 12, 17, 306, 9, 17, 1, 18, 1, 18, 1, 18, 1, 18, 1, 19, 1, 19, 3, 19, 314, 8, 19, 1, 20, 1, 20, 1, 20, 1, 20, 5, 20, 320, 8, 20, 10, 20, 12, 20, 323, 9, 20, 1, 21, 1, 21, 1, 21, 1, 21, 1, 22, 1, 22, 1, 22, 1, 23, 1, 23, 3, 23, 334, 8, 23, 1, 23, 1, 23, 3, 23, 338, 8, 23, 1, 24, 1, 24, 1, 24, 1, 24, 3, 24, 344, 8, 24, 1, 25, 1, 25, 1, 25, 5, 25, 349, 8, 25, 10, 25, 12, 25, 352, 9, 25, 1, 26, 1, 26, 1, 26, 5, 26, 357, 8, 26, 10, 26, 12, 26, 360, 9, 26, 1, 27, 1, 27, 1, 28, 1, 28, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 5, 29, 379, 8, 29, 10, 29, 12, 29, 382, 9, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 5, 29, 390, 8, 29, 10, 29, 12, 29, 393, 9, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 5, 29, 401, 8, 29, 10, 29, 12, 29, 404, 9, 29, 1, 29, 1, 29, 3, 29, 408, 8, 29, 1, 30, 1, 30, 1, 30, 1, 31, 1, 31, 1, 31, 1, 31, 5, 31, 417, 8, 31, 10, 31, 12, 31, 420, 9, 31, 1, 32, 1, 32, 3, 32, 424, 8, 32, 1, 32, 1, 32, 3, 32, 428, 8, 32, 1, 33, 1, 33, 1, 33, 1, 33, 5, 33, 434, 8, 33, 10, 33, 12, 33, 437, 9, 33, 1, 34, 1, 34, 1, 34, 1, 34, 5, 34, 443, 8, 34, 10, 34, 12, 34, 446, 9, 34, 1, 35, 1, 35, 1, 35, 1, 35, 5, 35, 452, 8, 35, 10, 35, 12, 35, 455, 9, 35, 1, 36, 1, 36, 1, 36, 1, 36, 1, 37, 1, 37, 1, 37, 1, 37, 3, 37, 465, 8, 37, 1, 38, 1, 38, 1, 38, 1, 38, 1, 39, 1, 39, 1, 39, 1, 40, 1, 40, 1, 40, 5, 40, 477, 8, 40, 10, 40, 12, 40, 480, 9, 40, 1, 41, 1, 41, 1, 41, 1, 41, 1, 42, 1, 42, 1, 43, 1, 43, 3, 43, 490, 8, 43, 1, 44, 3, 44, 493, 8, 44, 1, 44, 1, 44, 1, 45, 3, 45, 498, 8, 45, 1, 45, 1, 45, 1, 46, 1, 46, 1, 47, 1, 47, 1, 48, 1, 48, 1, 48, 1, 49, 1, 49, 1, 49, 1, 49, 1, 50, 1, 50, 1, 50, 1, 51, 1, 51, 1, 51, 1, 52, 1, 52, 1, 52, 1, 52, 3, 52, 523, 8, 52, 1, 52, 1, 52, 1, 52, 1, 52, 5, 52, 529, 8, 52, 10, 52, 12, 52, 532, 9, 52, 3, 52, 534, 8, 52, 1, 53, 1, 53, 1, 53, 3, 53, 539, 8, 53, 1, 53, 1, 53, 1, 53, 0, 4, 2, 10, 16, 18, 54, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98, 100, 102, 104, 106, 0, 7, 1, 0, 60, 61, 1, 0, 62, 64, 1, 0, 67, 68, 2, 0, 32, 32, 36, 36, 1, 0, 39, 40, 2, 0, 38, 38, 52, 52, 2, 0, 53, 53, 55, 59, 568, 0, 108, 1, 0, 0, 0, 2, 111, 1, 0, 0, 0, 4, 127, 1, 0, 0, 0, 6, 142, 1, 0, 0, 0, 8, 144, 1, 0, 0, 0, 10, 175, 1, 0, 0, 0, 12, 202, 1, 0, 0, 0, 14, 209, 1, 0, 0, 0, 16, 215, 1, 0, 0, 0, 18, 236, 1, 0, 0, 0, 20, 246, 1, 0, 0, 0, 22, 261, 1, 0, 0, 0, 24, 263, 1, 0, 0, 0, 26, 266, 1, 0, 0, 0, 28, 279, 1, 0, 0, 0, 30, 281, 1, 0, 0, 0, 32, 296, 1, 0, 0, 0, 34, 298, 1, 0, 0, 0, 36, 307, 1, 0, 0, 0, 38, 313, 1, 0, 0, 0, 40, 315, 1, 0, 0, 0, 42, 324, 1, 0, 0, 0, 44, 328, 1, 0, 0, 0, 46, 331, 1, 0, 0, 0, 48, 339, 1, 0, 0, 0, 50, 345, 1, 0, 0, 0, 52, 353, 1, 0, 0, 0, 54, 361, 1, 0, 0, 0, 56, 363, 1, 0, 0, 0, 58, 407, 1, 0, 0, 0, 60, 409, 1, 0, 0, 0, 62, 412, 1, 0, 0, 0, 64, 421, 1, 0, 0, 0, 66, 429, 1, 0, 0, 0, 68, 438, 1, 0, 0, 0, 70, 447, 1, 0, 0, 0, 72, 456, 1, 0, 0, 0, 74, 460, 1, 0, 0, 0, 76, 466, 1, 0, 0, 0, 78, 470, 1, 0, 0, 0, 80, 473, 1, 0, 0, 0, 82, 481, 1, 0, 0, 0, 84, 485, 1, 0, 0, 0, 86, 489, 1, 0, 0, 0, 88, 492, 1, 0, 0, 0, 90, 497, 1, 0, 0, 0, 92, 501, 1, 0, 0, 0, 94, 503, 1, 0, 0, 0, 96, 505, 1, 0, 0, 0, 98, 508, 1, 0, 0, 0, 100, 512, 1, 0, 0, 0, 102, 515, 1, 0, 0, 0, 104, 518, 1, 0, 0, 0, 106, 538, 1, 0, 0, 0, 108, 109, 3, 2, 1, 0, 109, 110, 5, 0, 0, 1, 110, 1, 1, 0, 0, 0, 111, 112, 6, 1, -1, 0, 112, 113, 3, 4, 2, 0, 113, 119, 1, 0, 0, 0, 114, 115, 10, 1, 0, 0, 115, 116, 5, 26, 0, 0, 116, 118, 3, 6, 3, 0, 117, 114, 1, 0, 0, 0, 118, 121, 1, 0, 0, 0, 119, 117, 1, 0, 0, 0, 119, 120, 1, 0, 0, 0, 120, 3, 1, 0, 0, 0, 121, 119, 1, 0, 0, 0, 122, 128, 3, 96, 48, 0, 123, 128, 3, 30, 15, 0, 124, 128, 3, 24, 12, 0, 125, 128, 3, 100, 50, 0, 126, 128, 3, 102, 51, 0, 127, 122, 1, 0, 0, 0, 127, 123, 1, 0, 0, 0, 127, 124, 1, 0, 0, 0, 127, 125, 1, 0, 0, 0, 127, 126, 1, 0, 0, 0, 128, 5, 1, 0, 0, 0, 129, 143, 3, 44, 22, 0, 130, 143, 3, 48, 24, 0, 131, 143, 3, 60, 30, 0, 132, 143, 3, 66, 33, 0, 133, 143, 3, 62, 31, 0, 134, 143, 3, 46, 23, 0, 135, 143, 3, 8, 4, 0, 136, 143, 3, 68, 34, 0, 137, 143, 3, 70, 35, 0, 138, 143, 3, 74, 37, 0, 139, 143, 3, 76, 38, 0, 140, 143, 3, 104, 52, 0, 141, 143, 3, 78, 39, 0, 142, 129, 1, 0, 0, 0, 142, 130, 1, 0, 0, 0, 142, 131, 1, 0, 0, 0, 142, 132, 1, 0, 0, 0, 142, 133, 1, 0, 0, 0, 142, 134, 1, 0, 0, 0, 142, 135, 1, 0, 0, 0, 142, 136, 1, 0, 0, 0, 142, 137, 1, 0, 0, 0, 142, 138, 1, 0, 0, 0, 142, 139, 1, 0, 0, 0, 142, 140, 1, 0, 0, 0, 142, 141, 1, 0, 0, 0, 143, 7, 1, 0, 0, 0, 144, 145, 5, 18, 0, 0, 145, 146, 3, 10, 5, 0, 146, 9, 1, 0, 0, 0, 147, 148, 6, 5, -1, 0, 148, 149, 5, 45, 0, 0, 149, 176, 3, 10, 5, 7, 150, 176, 3, 14, 7, 0, 151, 176, 3, 12, 6, 0, 152, 154, 3, 14, 7, 0, 153, 155, 5, 45, 0, 0, 154, 153, 1, 0, 0, 0, 154, 155, 1, 0, 0, 0, 155, 156, 1, 0, 0, 0, 156, 157, 5, 42, 0, 0, 157, 158, 5, 41, 0, 0, 158, 163, 3, 14, 7, 0, 159, 160, 5, 35, 0, 0, 160, 162, 3, 14, 7, 0, 161, 159, 1, 0, 0, 0, 162, 165, 1, 0, 0, 0, 163, 161, 1, 0, 0, 0, 163, 164, 1, 0, 0, 0, 164, 166, 1, 0, 0, 0, 165, 163, 1, 0, 0, 0, 166, 167, 5, 51, 0, 0, 167, 176, 1, 0, 0, 0, 168, 169, 3, 14, 7, 0, 169, 171, 5, 43, 0, 0, 170, 172, 5, 45, 0, 0, 171, 170, 1, 0, 0, 0, 171, 172, 1, 0, 0, 0, 172, 173, 1, 0, 0, 0, 173, 174, 5, 46, 0, 0, 174, 176, 1, 0, 0, 0, 175, 147, 1, 0, 0, 0, 175, 150, 1, 0, 0, 0, 175, 151, 1, 0, 0, 0, 175, 152, 1, 0, 0, 0, 175, 168, 1, 0, 0, 0, 176, 185, 1, 0, 0, 0, 177, 178, 10, 4, 0, 0, 178, 179, 5, 31, 0, 0, 179, 184, 3, 10, 5, 5, 180, 181, 10, 3, 0, 0, 181, 182, 5, 48, 0, 0, 182, 184, 3, 10, 5, 4, 183, 177, 1, 0, 0, 0, 183, 180, 1, 0, 0, 0, 184, 187, 1, 0, 0, 0, 185, 183, 1, 0, 0, 0, 185, 186, 1, 0, 0, 0, 186, 11, 1, 0, 0, 0, 187, 185, 1, 0, 0, 0, 188, 190, 3, 14, 7, 0, 189, 191, 5, 45, 0, 0, 190, 189, 1, 0, 0, 0, 190, 191, 1, 0, 0, 0, 191, 192, 1, 0, 0, 0, 192, 193, 5, 44, 0, 0, 193, 194, 3, 92, 46, 0, 194, 203, 1, 0, 0, 0, 195, 197, 3, 14, 7, 0, 196, 198, 5, 45, 0, 0, 197, 196, 1, 0, 0, 0, 197, 198, 1, 0, 0, 0, 198, 199, 1, 0, 0, 0, 199, 200, 5, 50, 0, 0, 200, 201, 3, 92, 46, 0, 201, 203, 1, 0, 0, 0, 202, 188, 1, 0, 0, 0, 202, 195, 1, 0, 0, 0, 203, 13, 1, 0, 0, 0, 204, 210, 3, 16, 8, 0, 205, 206, 3, 16, 8, 0, 206, 207, 3, 94, 47, 0, 207, 208, 3, 16, 8, 0, 208, 210, 1, 0, 0, 0, 209, 204, 1, 0, 0, 0, 209, 205, 1, 0, 0, 0, 210, 15, 1, 0, 0, 0, 211, 212, 6, 8, -1, 0, 212, 216, 3, 18, 9, 0, 213, 214, 7, 0, 0, 0, 214, 216, 3, 16, 8, 3, 215, 211, 1, 0, 0, 0, 215, 213, 1, 0, 0, 0, 216, 225, 1, 0, 0, 0, 217, 218, 10, 2, 0, 0, 218, 219, 7, 1, 0, 0, 219, 224, 3, 16, 8, 3, 220, 221, 10, 1, 0, 0, 221, 222, 7, 0, 0, 0, 222, 224, 3, 16, 8, 2, 223, 217, 1, 0, 0, 0, 223, 220, 1, 0, 0, 0, 224, 227, 1, 0, 0, 0, 225, 223, 1, 0, 0, 0, 225, 226, 1, 0, 0, 0, 226, 17, 1, 0, 0, 0, 227, 225, 1, 0, 0, 0, 228, 229, 6, 9, -1, 0, 229, 237, 3, 58, 29, 0, 230, 237, 3, 50, 25, 0, 231, 237, 3, 20, 10, 0, 232, 233, 5, 41, 0, 0, 233, 234, 3, 10, 5, 0, 234, 235, 5, 51, 0, 0, 235, 237, 1, 0, 0, 0, 236, 228, 1, 0, 0, 0, 236, 230, 1, 0, 0, 0, 236, 231, 1, 0, 0, 0, 236, 232, 1, 0, 0, 0, 237, 243, 1, 0, 0, 0, 238, 239, 10, 1, 0, 0, 239, 240, 5, 34, 0, 0, 240, 242, 3, 22, 11, 0, 241, 238, 1, 0, 0, 0, 242, 245, 1, 0, 0, 0, 243, 241, 1, 0, 0, 0, 243, 244, 1, 0, 0, 0, 244, 19, 1, 0, 0, 0, 245, 243, 1, 0, 0, 0, 246, 247, 3, 54, 27, 0, 247, 257, 5, 41, 0, 0, 248, 258, 5, 62, 0, 0, 249, 254, 3, 10, 5, 0, 250, 251, 5, 35, 0, 0, 251, 253, 3, 10, 5, 0, 252, 250, 1, 0, 0, 0, 253, 256, 1, 0, 0, 0, 254, 252, 1, 0, 0, 0, 254, 255, 1, 0, 0, 0, 255, 258, 1, 0, 0, 0, 256, 254, 1, 0, 0, 0, 257, 248, 1, 0, 0, 0, 257, 249, 1, 0, 0, 0, 257, 258, 1, 0, 0, 0, 258, 259, 1, 0, 0, 0, 259, 260, 5, 51, 0, 0, 260, 21, 1, 0, 0, 0, 261, 262, 3, 54, 27, 0, 262, 23, 1, 0, 0, 0, 263, 264, 5, 14, 0, 0, 264, 265, 3, 26, 13, 0, 265, 25, 1, 0, 0, 0, 266, 271, 3, 28, 14, 0, 267, 268, 5, 35, 0, 0, 268, 270, 3, 28, 14, 0, 269, 267, 1, 0, 0, 0, 270, 273, 1, 0, 0, 0, 271, 269, 1, 0, 0, 0, 271, 272, 1, 0, 0, 0, 272, 27, 1, 0, 0, 0, 273, 271, 1, 0, 0, 0, 274, 280, 3, 10, 5, 0, 275, 276, 3, 50, 25, 0, 276, 277, 5, 33, 0, 0, 277, 278, 3, 10, 5, 0, 278, 280, 1, 0, 0, 0, 279, 274, 1, 0, 0, 0, 279, 275, 1, 0, 0, 0, 280, 29, 1, 0, 0, 0, 281, 282, 5, 6, 0, 0, 282, 287, 3, 32, 16, 0, 283, 284, 5, 35, 0, 0, 284, 286, 3, 32, 16, 0, 285, 283, 1, 0, 0, 0, 286, 289, 1, 0, 0, 0, 287, 285, 1, 0, 0, 0, 287, 288, 1, 0, 0, 0, 288, 291, 1, 0, 0, 0, 289, 287, 1, 0, 0, 0, 290, 292, 3, 38, 19, 0, 291, 290, 1, 0, 0, 0, 291, 292, 1, 0, 0, 0, 292, 294, 1, 0, 0, 0, 293, 295, 3, 34, 17, 0, 294, 293, 1, 0, 0, 0, 294, 295, 1, 0, 0, 0, 295, 31, 1, 0, 0, 0, 296, 297, 5, 74, 0, 0, 297, 33, 1, 0, 0, 0, 298, 299, 5, 72, 0, 0, 299, 304, 3, 36, 18, 0, 300, 301, 5, 35, 0, 0, 301, 303, 3, 36, 18, 0, 302, 300, 1, 0, 0, 0, 303, 306, 1, 0, 0, 0, 304, 302, 1, 0, 0, 0, 304, 305, 1, 0, 0, 0, 305, 35, 1, 0, 0, 0, 306, 304, 1, 0, 0, 0, 307, 308, 3, 92, 46, 0, 308, 309, 5, 33, 0, 0, 309, 310, 3, 92, 46, 0, 310, 37, 1, 0, 0, 0, 311, 314, 3, 40, 20, 0, 312, 314, 3, 42, 21, 0, 313, 311, 1, 0, 0, 0, 313, 312, 1, 0, 0, 0, 314, 39, 1, 0, 0, 0, 315, 316, 5, 73, 0, 0, 316, 321, 3, 32, 16, 0, 317, 318, 5, 35, 0, 0, 318, 320, 3, 32, 16, 0, 319, 317, 1, 0, 0, 0, 320, 323, 1, 0, 0, 0, 321, 319, 1, 0, 0, 0, 321, 322, 1, 0, 0, 0, 322, 41, 1, 0, 0, 0, 323, 321, 1, 0, 0, 0, 324, 325, 5, 65, 0, 0, 325, 326, 3, 40, 20, 0, 326, 327, 5, 66, 0, 0, 327, 43, 1, 0, 0, 0, 328, 329, 5, 4, 0, 0, 329, 330, 3, 26, 13, 0, 330, 45, 1, 0, 0, 0, 331, 333, 5, 17, 0, 0, 332, 334, 3, 26, 13, 0, 333, 332, 1, 0, 0, 0, 333, 334, 1, 0, 0, 0, 334, 337, 1, 0, 0, 0, 335, 336, 5, 30, 0, 0, 336, 338, 3, 26, 13, 0, 337, 335, 1, 0, 0, 0, 337, 338, 1, 0, 0, 0, 338, 47, 1, 0, 0, 0, 339, 340, 5, 8, 0, 0, 340, 343, 3, 26, 13, 0, 341, 342, 5, 30, 0, 0, 342, 344, 3, 26, 13, 0, 343, 341, 1, 0, 0, 0, 343, 344, 1, 0, 0, 0, 344, 49, 1, 0, 0, 0, 345, 350, 3, 54, 27, 0, 346, 347, 5, 37, 0, 0, 347, 349, 3, 54, 27, 0, 348, 346, 1, 0, 0, 0, 349, 352, 1, 0, 0, 0, 350, 348, 1, 0, 0, 0, 350, 351, 1, 0, 0, 0, 351, 51, 1, 0, 0, 0, 352, 350, 1, 0, 0, 0, 353, 358, 3, 56, 28, 0, 354, 355, 5, 37, 0, 0, 355, 357, 3, 56, 28, 0, 356, 354, 1, 0, 0, 0, 357, 360, 1, 0, 0, 0, 358, 356, 1, 0, 0, 0, 358, 359, 1, 0, 0, 0, 359, 53, 1, 0, 0, 0, 360, 358, 1, 0, 0, 0, 361, 362, 7, 2, 0, 0, 362, 55, 1, 0, 0, 0, 363, 364, 5, 78, 0, 0, 364, 57, 1, 0, 0, 0, 365, 408, 5, 46, 0, 0, 366, 367, 3, 90, 45, 0, 367, 368, 5, 67, 0, 0, 368, 408, 1, 0, 0, 0, 369, 408, 3, 88, 44, 0, 370, 408, 3, 90, 45, 0, 371, 408, 3, 84, 42, 0, 372, 408, 5, 49, 0, 0, 373, 408, 3, 92, 46, 0, 374, 375, 5, 65, 0, 0, 375, 380, 3, 86, 43, 0, 376, 377, 5, 35, 0, 0, 377, 379, 3, 86, 43, 0, 378, 376, 1, 0, 0, 0, 379, 382, 1, 0, 0, 0, 380, 378, 1, 0, 0, 0, 380, 381, 1, 0, 0, 0, 381, 383, 1, 0, 0, 0, 382, 380, 1, 0, 0, 0, 383, 384, 5, 66, 0, 0, 384, 408, 1, 0, 0, 0, 385, 386, 5, 65, 0, 0, 386, 391, 3, 84, 42, 0, 387, 388, 5, 35, 0, 0, 388, 390, 3, 84, 42, 0, 389, 387, 1, 0, 0, 0, 390, 393, 1, 0, 0, 0, 391, 389, 1, 0, 0, 0, 391, 392, 1, 0, 0, 0, 392, 394, 1, 0, 0, 0, 393, 391, 1, 0, 0, 0, 394, 395, 5, 66, 0, 0, 395, 408, 1, 0, 0, 0, 396, 397, 5, 65, 0, 0, 397, 402, 3, 92, 46, 0, 398, 399, 5, 35, 0, 0, 399, 401, 3, 92, 46, 0, 400, 398, 1, 0, 0, 0, 401, 404, 1, 0, 0, 0, 402, 400, 1, 0, 0, 0, 402, 403, 1, 0, 0, 0, 403, 405, 1, 0, 0, 0, 404, 402, 1, 0, 0, 0, 405, 406, 5, 66, 0, 0, 406, 408, 1, 0, 0, 0, 407, 365, 1, 0, 0, 0, 407, 366, 1, 0, 0, 0, 407, 369, 1, 0, 0, 0, 407, 370, 1, 0, 0, 0, 407, 371, 1, 0, 0, 0, 407, 372, 1, 0, 0, 0, 407, 373, 1, 0, 0, 0, 407, 374, 1, 0, 0, 0, 407, 385, 1, 0, 0, 0, 407, 396, 1, 0, 0, 0, 408, 59, 1, 0, 0, 0, 409, 410, 5, 10, 0, 0, 410, 411, 5, 28, 0, 0, 411, 61, 1, 0, 0, 0, 412, 413, 5, 16, 0, 0, 413, 418, 3, 64, 32, 0, 414, 415, 5, 35, 0, 0, 415, 417, 3, 64, 32, 0, 416, 414, 1, 0, 0, 0, 417, 420, 1, 0, 0, 0, 418, 416, 1, 0, 0, 0, 418, 419, 1, 0, 0, 0, 419, 63, 1, 0, 0, 0, 420, 418, 1, 0, 0, 0, 421, 423, 3, 10, 5, 0, 422, 424, 7, 3, 0, 0, 423, 422, 1, 0, 0, 0, 423, 424, 1, 0, 0, 0, 424, 427, 1, 0, 0, 0, 425, 426, 5, 47, 0, 0, 426, 428, 7, 4, 0, 0, 427, 425, 1, 0, 0, 0, 427, 428, 1, 0, 0, 0, 428, 65, 1, 0, 0, 0, 429, 430, 5, 9, 0, 0, 430, 435, 3, 52, 26, 0, 431, 432, 5, 35, 0, 0, 432, 434, 3, 52, 26, 0, 433, 431, 1, 0, 0, 0, 434, 437, 1, 0, 0, 0, 435, 433, 1, 0, 0, 0, 435, 436, 1, 0, 0, 0, 436, 67, 1, 0, 0, 0, 437, 435, 1, 0, 0, 0, 438, 439, 5, 2, 0, 0, 439, 444, 3, 52, 26, 0, 440, 441, 5, 35, 0, 0, 441, 443, 3, 52, 26, 0, 442, 440, 1, 0, 0, 0, 443, 446, 1, 0, 0, 0, 444, 442, 1, 0, 0, 0, 444, 445, 1, 0, 0, 0, 445, 69, 1, 0, 0, 0, 446, 444, 1, 0, 0, 0, 447, 448, 5, 13, 0, 0, 448, 453, 3, 72, 36, 0, 449, 450, 5, 35, 0, 0, 450, 452, 3, 72, 36, 0, 451, 449, 1, 0, 0, 0, 452, 455, 1, 0, 0, 0, 453, 451, 1, 0, 0, 0, 453, 454, 1, 0, 0, 0, 454, 71, 1, 0, 0, 0, 455, 453, 1, 0, 0, 0, 456, 457, 3, 52, 26, 0, 457, 458, 5, 82, 0, 0, 458, 459, 3, 52, 26, 0, 459, 73, 1, 0, 0, 0, 460, 461, 5, 1, 0, 0, 461, 462, 3, 18, 9, 0, 462, 464, 3, 92, 46, 0, 463, 465, 3, 80, 40, 0, 464, 463, 1, 0, 0, 0, 464, 465, 1, 0, 0, 0, 465, 75, 1, 0, 0, 0, 466, 467, 5, 7, 0, 0, 467, 468, 3, 18, 9, 0, 468, 469, 3, 92, 46, 0, 469, 77, 1, 0, 0, 0, 470, 471, 5, 12, 0, 0, 471, 472, 3, 50, 25, 0, 472, 79, 1, 0, 0, 0, 473, 478, 3, 82, 41, 0, 474, 475, 5, 35, 0, 0, 475, 477, 3, 82, 41, 0, 476, 474, 1, 0, 0, 0, 477, 480, 1, 0, 0, 0, 478, 476, 1, 0, 0, 0, 478, 479, 1, 0, 0, 0, 479, 81, 1, 0, 0, 0, 480, 478, 1, 0, 0, 0, 481, 482, 3, 54, 27, 0, 482, 483, 5, 33, 0, 0, 483, 484, 3, 58, 29, 0, 484, 83, 1, 0, 0, 0, 485, 486, 7, 5, 0, 0, 486, 85, 1, 0, 0, 0, 487, 490, 3, 88, 44, 0, 488, 490, 3, 90, 45, 0, 489, 487, 1, 0, 0, 0, 489, 488, 1, 0, 0, 0, 490, 87, 1, 0, 0, 0, 491, 493, 7, 0, 0, 0, 492, 491, 1, 0, 0, 0, 492, 493, 1, 0, 0, 0, 493, 494, 1, 0, 0, 0, 494, 495, 5, 29, 0, 0, 495, 89, 1, 0, 0, 0, 496, 498, 7, 0, 0, 0, 497, 496, 1, 0, 0, 0, 497, 498, 1, 0, 0, 0, 498, 499, 1, 0, 0, 0, 499, 500, 5, 28, 0, 0, 500, 91, 1, 0, 0, 0, 501, 502, 5, 27, 0, 0, 502, 93, 1, 0, 0, 0, 503, 504, 7, 6, 0, 0, 504, 95, 1, 0, 0, 0, 505, 506, 5, 5, 0, 0, 506, 507, 3, 98, 49, 0, 507, 97, 1, 0, 0, 0, 508, 509, 5, 65, 0, 0, 509, 510, 3, 2, 1, 0, 510, 511, 5, 66, 0, 0, 511, 99, 1, 0, 0, 0, 512, 513, 5, 15, 0, 0, 513, 514, 5, 98, 0, 0, 514, 101, 1, 0, 0, 0, 515, 516, 5, 11, 0, 0, 516, 517, 5, 102, 0, 0, 517, 103, 1, 0, 0, 0, 518, 519, 5, 3, 0, 0, 519, 522, 5, 88, 0, 0, 520, 521, 5, 86, 0, 0, 521, 523, 3, 52, 26, 0, 522, 520, 1, 0, 0, 0, 522, 523, 1, 0, 0, 0, 523, 533, 1, 0, 0, 0, 524, 525, 5, 87, 0, 0, 525, 530, 3, 106, 53, 0, 526, 527, 5, 35, 0, 0, 527, 529, 3, 106, 53, 0, 528, 526, 1, 0, 0, 0, 529, 532, 1, 0, 0, 0, 530, 528, 1, 0, 0, 0, 530, 531, 1, 0, 0, 0, 531, 534, 1, 0, 0, 0, 532, 530, 1, 0, 0, 0, 533, 524, 1, 0, 0, 0, 533, 534, 1, 0, 0, 0, 534, 105, 1, 0, 0, 0, 535, 536, 3, 52, 26, 0, 536, 537, 5, 33, 0, 0, 537, 539, 1, 0, 0, 0, 538, 535, 1, 0, 0, 0, 538, 539, 1, 0, 0, 0, 539, 540, 1, 0, 0, 0, 540, 541, 3, 52, 26, 0, 541, 107, 1, 0, 0, 0, 52, 119, 127, 142, 154, 163, 171, 175, 183, 185, 190, 197, 202, 209, 215, 223, 225, 236, 243, 254, 257, 271, 279, 287, 291, 294, 304, 313, 321, 333, 337, 343, 350, 358, 380, 391, 402, 407, 418, 423, 427, 435, 444, 453, 464, 478, 489, 492, 497, 522, 530, 533, 538] \ No newline at end of file +[4, 1, 109, 523, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15, 2, 16, 7, 16, 2, 17, 7, 17, 2, 18, 7, 18, 2, 19, 7, 19, 2, 20, 7, 20, 2, 21, 7, 21, 2, 22, 7, 22, 2, 23, 7, 23, 2, 24, 7, 24, 2, 25, 7, 25, 2, 26, 7, 26, 2, 27, 7, 27, 2, 28, 7, 28, 2, 29, 7, 29, 2, 30, 7, 30, 2, 31, 7, 31, 2, 32, 7, 32, 2, 33, 7, 33, 2, 34, 7, 34, 2, 35, 7, 35, 2, 36, 7, 36, 2, 37, 7, 37, 2, 38, 7, 38, 2, 39, 7, 39, 2, 40, 7, 40, 2, 41, 7, 41, 2, 42, 7, 42, 2, 43, 7, 43, 2, 44, 7, 44, 2, 45, 7, 45, 2, 46, 7, 46, 2, 47, 7, 47, 2, 48, 7, 48, 2, 49, 7, 49, 2, 50, 7, 50, 2, 51, 7, 51, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 1, 114, 8, 1, 10, 1, 12, 1, 117, 9, 1, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 3, 2, 124, 8, 2, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 3, 3, 139, 8, 3, 1, 4, 1, 4, 1, 4, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 3, 5, 151, 8, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 5, 5, 158, 8, 5, 10, 5, 12, 5, 161, 9, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 3, 5, 168, 8, 5, 1, 5, 1, 5, 3, 5, 172, 8, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 1, 5, 5, 5, 180, 8, 5, 10, 5, 12, 5, 183, 9, 5, 1, 6, 1, 6, 3, 6, 187, 8, 6, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 3, 6, 194, 8, 6, 1, 6, 1, 6, 1, 6, 3, 6, 199, 8, 6, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 3, 7, 206, 8, 7, 1, 8, 1, 8, 1, 8, 1, 8, 3, 8, 212, 8, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 5, 8, 220, 8, 8, 10, 8, 12, 8, 223, 9, 8, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 3, 9, 233, 8, 9, 1, 9, 1, 9, 1, 9, 5, 9, 238, 8, 9, 10, 9, 12, 9, 241, 9, 9, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 5, 10, 249, 8, 10, 10, 10, 12, 10, 252, 9, 10, 3, 10, 254, 8, 10, 1, 10, 1, 10, 1, 11, 1, 11, 1, 12, 1, 12, 1, 12, 1, 13, 1, 13, 1, 13, 5, 13, 266, 8, 13, 10, 13, 12, 13, 269, 9, 13, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 3, 14, 276, 8, 14, 1, 15, 1, 15, 1, 15, 1, 15, 5, 15, 282, 8, 15, 10, 15, 12, 15, 285, 9, 15, 1, 15, 3, 15, 288, 8, 15, 1, 16, 1, 16, 1, 17, 1, 17, 3, 17, 294, 8, 17, 1, 18, 1, 18, 1, 18, 1, 18, 5, 18, 300, 8, 18, 10, 18, 12, 18, 303, 9, 18, 1, 19, 1, 19, 1, 19, 1, 19, 1, 20, 1, 20, 1, 20, 1, 21, 1, 21, 3, 21, 314, 8, 21, 1, 21, 1, 21, 3, 21, 318, 8, 21, 1, 22, 1, 22, 1, 22, 1, 22, 3, 22, 324, 8, 22, 1, 23, 1, 23, 1, 23, 5, 23, 329, 8, 23, 10, 23, 12, 23, 332, 9, 23, 1, 24, 1, 24, 1, 24, 5, 24, 337, 8, 24, 10, 24, 12, 24, 340, 9, 24, 1, 25, 1, 25, 1, 26, 1, 26, 1, 27, 1, 27, 1, 27, 1, 27, 1, 27, 1, 27, 1, 27, 1, 27, 1, 27, 1, 27, 1, 27, 1, 27, 1, 27, 5, 27, 359, 8, 27, 10, 27, 12, 27, 362, 9, 27, 1, 27, 1, 27, 1, 27, 1, 27, 1, 27, 1, 27, 5, 27, 370, 8, 27, 10, 27, 12, 27, 373, 9, 27, 1, 27, 1, 27, 1, 27, 1, 27, 1, 27, 1, 27, 5, 27, 381, 8, 27, 10, 27, 12, 27, 384, 9, 27, 1, 27, 1, 27, 3, 27, 388, 8, 27, 1, 28, 1, 28, 1, 28, 1, 29, 1, 29, 1, 29, 1, 29, 5, 29, 397, 8, 29, 10, 29, 12, 29, 400, 9, 29, 1, 30, 1, 30, 3, 30, 404, 8, 30, 1, 30, 1, 30, 3, 30, 408, 8, 30, 1, 31, 1, 31, 1, 31, 1, 31, 5, 31, 414, 8, 31, 10, 31, 12, 31, 417, 9, 31, 1, 32, 1, 32, 1, 32, 1, 32, 5, 32, 423, 8, 32, 10, 32, 12, 32, 426, 9, 32, 1, 33, 1, 33, 1, 33, 1, 33, 5, 33, 432, 8, 33, 10, 33, 12, 33, 435, 9, 33, 1, 34, 1, 34, 1, 34, 1, 34, 1, 35, 1, 35, 1, 35, 1, 35, 3, 35, 445, 8, 35, 1, 36, 1, 36, 1, 36, 1, 36, 1, 37, 1, 37, 1, 37, 1, 38, 1, 38, 1, 38, 5, 38, 457, 8, 38, 10, 38, 12, 38, 460, 9, 38, 1, 39, 1, 39, 1, 39, 1, 39, 1, 40, 1, 40, 1, 41, 1, 41, 3, 41, 470, 8, 41, 1, 42, 3, 42, 473, 8, 42, 1, 42, 1, 42, 1, 43, 3, 43, 478, 8, 43, 1, 43, 1, 43, 1, 44, 1, 44, 1, 45, 1, 45, 1, 46, 1, 46, 1, 46, 1, 47, 1, 47, 1, 47, 1, 47, 1, 48, 1, 48, 1, 48, 1, 49, 1, 49, 1, 49, 1, 50, 1, 50, 1, 50, 1, 50, 3, 50, 503, 8, 50, 1, 50, 1, 50, 1, 50, 1, 50, 5, 50, 509, 8, 50, 10, 50, 12, 50, 512, 9, 50, 3, 50, 514, 8, 50, 1, 51, 1, 51, 1, 51, 3, 51, 519, 8, 51, 1, 51, 1, 51, 1, 51, 0, 4, 2, 10, 16, 18, 52, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98, 100, 102, 0, 7, 1, 0, 60, 61, 1, 0, 62, 64, 1, 0, 67, 68, 2, 0, 32, 32, 36, 36, 1, 0, 39, 40, 2, 0, 38, 38, 52, 52, 2, 0, 53, 53, 55, 59, 548, 0, 104, 1, 0, 0, 0, 2, 107, 1, 0, 0, 0, 4, 123, 1, 0, 0, 0, 6, 138, 1, 0, 0, 0, 8, 140, 1, 0, 0, 0, 10, 171, 1, 0, 0, 0, 12, 198, 1, 0, 0, 0, 14, 205, 1, 0, 0, 0, 16, 211, 1, 0, 0, 0, 18, 232, 1, 0, 0, 0, 20, 242, 1, 0, 0, 0, 22, 257, 1, 0, 0, 0, 24, 259, 1, 0, 0, 0, 26, 262, 1, 0, 0, 0, 28, 275, 1, 0, 0, 0, 30, 277, 1, 0, 0, 0, 32, 289, 1, 0, 0, 0, 34, 293, 1, 0, 0, 0, 36, 295, 1, 0, 0, 0, 38, 304, 1, 0, 0, 0, 40, 308, 1, 0, 0, 0, 42, 311, 1, 0, 0, 0, 44, 319, 1, 0, 0, 0, 46, 325, 1, 0, 0, 0, 48, 333, 1, 0, 0, 0, 50, 341, 1, 0, 0, 0, 52, 343, 1, 0, 0, 0, 54, 387, 1, 0, 0, 0, 56, 389, 1, 0, 0, 0, 58, 392, 1, 0, 0, 0, 60, 401, 1, 0, 0, 0, 62, 409, 1, 0, 0, 0, 64, 418, 1, 0, 0, 0, 66, 427, 1, 0, 0, 0, 68, 436, 1, 0, 0, 0, 70, 440, 1, 0, 0, 0, 72, 446, 1, 0, 0, 0, 74, 450, 1, 0, 0, 0, 76, 453, 1, 0, 0, 0, 78, 461, 1, 0, 0, 0, 80, 465, 1, 0, 0, 0, 82, 469, 1, 0, 0, 0, 84, 472, 1, 0, 0, 0, 86, 477, 1, 0, 0, 0, 88, 481, 1, 0, 0, 0, 90, 483, 1, 0, 0, 0, 92, 485, 1, 0, 0, 0, 94, 488, 1, 0, 0, 0, 96, 492, 1, 0, 0, 0, 98, 495, 1, 0, 0, 0, 100, 498, 1, 0, 0, 0, 102, 518, 1, 0, 0, 0, 104, 105, 3, 2, 1, 0, 105, 106, 5, 0, 0, 1, 106, 1, 1, 0, 0, 0, 107, 108, 6, 1, -1, 0, 108, 109, 3, 4, 2, 0, 109, 115, 1, 0, 0, 0, 110, 111, 10, 1, 0, 0, 111, 112, 5, 26, 0, 0, 112, 114, 3, 6, 3, 0, 113, 110, 1, 0, 0, 0, 114, 117, 1, 0, 0, 0, 115, 113, 1, 0, 0, 0, 115, 116, 1, 0, 0, 0, 116, 3, 1, 0, 0, 0, 117, 115, 1, 0, 0, 0, 118, 124, 3, 92, 46, 0, 119, 124, 3, 30, 15, 0, 120, 124, 3, 24, 12, 0, 121, 124, 3, 96, 48, 0, 122, 124, 3, 98, 49, 0, 123, 118, 1, 0, 0, 0, 123, 119, 1, 0, 0, 0, 123, 120, 1, 0, 0, 0, 123, 121, 1, 0, 0, 0, 123, 122, 1, 0, 0, 0, 124, 5, 1, 0, 0, 0, 125, 139, 3, 40, 20, 0, 126, 139, 3, 44, 22, 0, 127, 139, 3, 56, 28, 0, 128, 139, 3, 62, 31, 0, 129, 139, 3, 58, 29, 0, 130, 139, 3, 42, 21, 0, 131, 139, 3, 8, 4, 0, 132, 139, 3, 64, 32, 0, 133, 139, 3, 66, 33, 0, 134, 139, 3, 70, 35, 0, 135, 139, 3, 72, 36, 0, 136, 139, 3, 100, 50, 0, 137, 139, 3, 74, 37, 0, 138, 125, 1, 0, 0, 0, 138, 126, 1, 0, 0, 0, 138, 127, 1, 0, 0, 0, 138, 128, 1, 0, 0, 0, 138, 129, 1, 0, 0, 0, 138, 130, 1, 0, 0, 0, 138, 131, 1, 0, 0, 0, 138, 132, 1, 0, 0, 0, 138, 133, 1, 0, 0, 0, 138, 134, 1, 0, 0, 0, 138, 135, 1, 0, 0, 0, 138, 136, 1, 0, 0, 0, 138, 137, 1, 0, 0, 0, 139, 7, 1, 0, 0, 0, 140, 141, 5, 18, 0, 0, 141, 142, 3, 10, 5, 0, 142, 9, 1, 0, 0, 0, 143, 144, 6, 5, -1, 0, 144, 145, 5, 45, 0, 0, 145, 172, 3, 10, 5, 7, 146, 172, 3, 14, 7, 0, 147, 172, 3, 12, 6, 0, 148, 150, 3, 14, 7, 0, 149, 151, 5, 45, 0, 0, 150, 149, 1, 0, 0, 0, 150, 151, 1, 0, 0, 0, 151, 152, 1, 0, 0, 0, 152, 153, 5, 42, 0, 0, 153, 154, 5, 41, 0, 0, 154, 159, 3, 14, 7, 0, 155, 156, 5, 35, 0, 0, 156, 158, 3, 14, 7, 0, 157, 155, 1, 0, 0, 0, 158, 161, 1, 0, 0, 0, 159, 157, 1, 0, 0, 0, 159, 160, 1, 0, 0, 0, 160, 162, 1, 0, 0, 0, 161, 159, 1, 0, 0, 0, 162, 163, 5, 51, 0, 0, 163, 172, 1, 0, 0, 0, 164, 165, 3, 14, 7, 0, 165, 167, 5, 43, 0, 0, 166, 168, 5, 45, 0, 0, 167, 166, 1, 0, 0, 0, 167, 168, 1, 0, 0, 0, 168, 169, 1, 0, 0, 0, 169, 170, 5, 46, 0, 0, 170, 172, 1, 0, 0, 0, 171, 143, 1, 0, 0, 0, 171, 146, 1, 0, 0, 0, 171, 147, 1, 0, 0, 0, 171, 148, 1, 0, 0, 0, 171, 164, 1, 0, 0, 0, 172, 181, 1, 0, 0, 0, 173, 174, 10, 4, 0, 0, 174, 175, 5, 31, 0, 0, 175, 180, 3, 10, 5, 5, 176, 177, 10, 3, 0, 0, 177, 178, 5, 48, 0, 0, 178, 180, 3, 10, 5, 4, 179, 173, 1, 0, 0, 0, 179, 176, 1, 0, 0, 0, 180, 183, 1, 0, 0, 0, 181, 179, 1, 0, 0, 0, 181, 182, 1, 0, 0, 0, 182, 11, 1, 0, 0, 0, 183, 181, 1, 0, 0, 0, 184, 186, 3, 14, 7, 0, 185, 187, 5, 45, 0, 0, 186, 185, 1, 0, 0, 0, 186, 187, 1, 0, 0, 0, 187, 188, 1, 0, 0, 0, 188, 189, 5, 44, 0, 0, 189, 190, 3, 88, 44, 0, 190, 199, 1, 0, 0, 0, 191, 193, 3, 14, 7, 0, 192, 194, 5, 45, 0, 0, 193, 192, 1, 0, 0, 0, 193, 194, 1, 0, 0, 0, 194, 195, 1, 0, 0, 0, 195, 196, 5, 50, 0, 0, 196, 197, 3, 88, 44, 0, 197, 199, 1, 0, 0, 0, 198, 184, 1, 0, 0, 0, 198, 191, 1, 0, 0, 0, 199, 13, 1, 0, 0, 0, 200, 206, 3, 16, 8, 0, 201, 202, 3, 16, 8, 0, 202, 203, 3, 90, 45, 0, 203, 204, 3, 16, 8, 0, 204, 206, 1, 0, 0, 0, 205, 200, 1, 0, 0, 0, 205, 201, 1, 0, 0, 0, 206, 15, 1, 0, 0, 0, 207, 208, 6, 8, -1, 0, 208, 212, 3, 18, 9, 0, 209, 210, 7, 0, 0, 0, 210, 212, 3, 16, 8, 3, 211, 207, 1, 0, 0, 0, 211, 209, 1, 0, 0, 0, 212, 221, 1, 0, 0, 0, 213, 214, 10, 2, 0, 0, 214, 215, 7, 1, 0, 0, 215, 220, 3, 16, 8, 3, 216, 217, 10, 1, 0, 0, 217, 218, 7, 0, 0, 0, 218, 220, 3, 16, 8, 2, 219, 213, 1, 0, 0, 0, 219, 216, 1, 0, 0, 0, 220, 223, 1, 0, 0, 0, 221, 219, 1, 0, 0, 0, 221, 222, 1, 0, 0, 0, 222, 17, 1, 0, 0, 0, 223, 221, 1, 0, 0, 0, 224, 225, 6, 9, -1, 0, 225, 233, 3, 54, 27, 0, 226, 233, 3, 46, 23, 0, 227, 233, 3, 20, 10, 0, 228, 229, 5, 41, 0, 0, 229, 230, 3, 10, 5, 0, 230, 231, 5, 51, 0, 0, 231, 233, 1, 0, 0, 0, 232, 224, 1, 0, 0, 0, 232, 226, 1, 0, 0, 0, 232, 227, 1, 0, 0, 0, 232, 228, 1, 0, 0, 0, 233, 239, 1, 0, 0, 0, 234, 235, 10, 1, 0, 0, 235, 236, 5, 34, 0, 0, 236, 238, 3, 22, 11, 0, 237, 234, 1, 0, 0, 0, 238, 241, 1, 0, 0, 0, 239, 237, 1, 0, 0, 0, 239, 240, 1, 0, 0, 0, 240, 19, 1, 0, 0, 0, 241, 239, 1, 0, 0, 0, 242, 243, 3, 50, 25, 0, 243, 253, 5, 41, 0, 0, 244, 254, 5, 62, 0, 0, 245, 250, 3, 10, 5, 0, 246, 247, 5, 35, 0, 0, 247, 249, 3, 10, 5, 0, 248, 246, 1, 0, 0, 0, 249, 252, 1, 0, 0, 0, 250, 248, 1, 0, 0, 0, 250, 251, 1, 0, 0, 0, 251, 254, 1, 0, 0, 0, 252, 250, 1, 0, 0, 0, 253, 244, 1, 0, 0, 0, 253, 245, 1, 0, 0, 0, 253, 254, 1, 0, 0, 0, 254, 255, 1, 0, 0, 0, 255, 256, 5, 51, 0, 0, 256, 21, 1, 0, 0, 0, 257, 258, 3, 50, 25, 0, 258, 23, 1, 0, 0, 0, 259, 260, 5, 14, 0, 0, 260, 261, 3, 26, 13, 0, 261, 25, 1, 0, 0, 0, 262, 267, 3, 28, 14, 0, 263, 264, 5, 35, 0, 0, 264, 266, 3, 28, 14, 0, 265, 263, 1, 0, 0, 0, 266, 269, 1, 0, 0, 0, 267, 265, 1, 0, 0, 0, 267, 268, 1, 0, 0, 0, 268, 27, 1, 0, 0, 0, 269, 267, 1, 0, 0, 0, 270, 276, 3, 10, 5, 0, 271, 272, 3, 46, 23, 0, 272, 273, 5, 33, 0, 0, 273, 274, 3, 10, 5, 0, 274, 276, 1, 0, 0, 0, 275, 270, 1, 0, 0, 0, 275, 271, 1, 0, 0, 0, 276, 29, 1, 0, 0, 0, 277, 278, 5, 6, 0, 0, 278, 283, 3, 32, 16, 0, 279, 280, 5, 35, 0, 0, 280, 282, 3, 32, 16, 0, 281, 279, 1, 0, 0, 0, 282, 285, 1, 0, 0, 0, 283, 281, 1, 0, 0, 0, 283, 284, 1, 0, 0, 0, 284, 287, 1, 0, 0, 0, 285, 283, 1, 0, 0, 0, 286, 288, 3, 34, 17, 0, 287, 286, 1, 0, 0, 0, 287, 288, 1, 0, 0, 0, 288, 31, 1, 0, 0, 0, 289, 290, 5, 73, 0, 0, 290, 33, 1, 0, 0, 0, 291, 294, 3, 36, 18, 0, 292, 294, 3, 38, 19, 0, 293, 291, 1, 0, 0, 0, 293, 292, 1, 0, 0, 0, 294, 35, 1, 0, 0, 0, 295, 296, 5, 72, 0, 0, 296, 301, 3, 32, 16, 0, 297, 298, 5, 35, 0, 0, 298, 300, 3, 32, 16, 0, 299, 297, 1, 0, 0, 0, 300, 303, 1, 0, 0, 0, 301, 299, 1, 0, 0, 0, 301, 302, 1, 0, 0, 0, 302, 37, 1, 0, 0, 0, 303, 301, 1, 0, 0, 0, 304, 305, 5, 65, 0, 0, 305, 306, 3, 36, 18, 0, 306, 307, 5, 66, 0, 0, 307, 39, 1, 0, 0, 0, 308, 309, 5, 4, 0, 0, 309, 310, 3, 26, 13, 0, 310, 41, 1, 0, 0, 0, 311, 313, 5, 17, 0, 0, 312, 314, 3, 26, 13, 0, 313, 312, 1, 0, 0, 0, 313, 314, 1, 0, 0, 0, 314, 317, 1, 0, 0, 0, 315, 316, 5, 30, 0, 0, 316, 318, 3, 26, 13, 0, 317, 315, 1, 0, 0, 0, 317, 318, 1, 0, 0, 0, 318, 43, 1, 0, 0, 0, 319, 320, 5, 8, 0, 0, 320, 323, 3, 26, 13, 0, 321, 322, 5, 30, 0, 0, 322, 324, 3, 26, 13, 0, 323, 321, 1, 0, 0, 0, 323, 324, 1, 0, 0, 0, 324, 45, 1, 0, 0, 0, 325, 330, 3, 50, 25, 0, 326, 327, 5, 37, 0, 0, 327, 329, 3, 50, 25, 0, 328, 326, 1, 0, 0, 0, 329, 332, 1, 0, 0, 0, 330, 328, 1, 0, 0, 0, 330, 331, 1, 0, 0, 0, 331, 47, 1, 0, 0, 0, 332, 330, 1, 0, 0, 0, 333, 338, 3, 52, 26, 0, 334, 335, 5, 37, 0, 0, 335, 337, 3, 52, 26, 0, 336, 334, 1, 0, 0, 0, 337, 340, 1, 0, 0, 0, 338, 336, 1, 0, 0, 0, 338, 339, 1, 0, 0, 0, 339, 49, 1, 0, 0, 0, 340, 338, 1, 0, 0, 0, 341, 342, 7, 2, 0, 0, 342, 51, 1, 0, 0, 0, 343, 344, 5, 77, 0, 0, 344, 53, 1, 0, 0, 0, 345, 388, 5, 46, 0, 0, 346, 347, 3, 86, 43, 0, 347, 348, 5, 67, 0, 0, 348, 388, 1, 0, 0, 0, 349, 388, 3, 84, 42, 0, 350, 388, 3, 86, 43, 0, 351, 388, 3, 80, 40, 0, 352, 388, 5, 49, 0, 0, 353, 388, 3, 88, 44, 0, 354, 355, 5, 65, 0, 0, 355, 360, 3, 82, 41, 0, 356, 357, 5, 35, 0, 0, 357, 359, 3, 82, 41, 0, 358, 356, 1, 0, 0, 0, 359, 362, 1, 0, 0, 0, 360, 358, 1, 0, 0, 0, 360, 361, 1, 0, 0, 0, 361, 363, 1, 0, 0, 0, 362, 360, 1, 0, 0, 0, 363, 364, 5, 66, 0, 0, 364, 388, 1, 0, 0, 0, 365, 366, 5, 65, 0, 0, 366, 371, 3, 80, 40, 0, 367, 368, 5, 35, 0, 0, 368, 370, 3, 80, 40, 0, 369, 367, 1, 0, 0, 0, 370, 373, 1, 0, 0, 0, 371, 369, 1, 0, 0, 0, 371, 372, 1, 0, 0, 0, 372, 374, 1, 0, 0, 0, 373, 371, 1, 0, 0, 0, 374, 375, 5, 66, 0, 0, 375, 388, 1, 0, 0, 0, 376, 377, 5, 65, 0, 0, 377, 382, 3, 88, 44, 0, 378, 379, 5, 35, 0, 0, 379, 381, 3, 88, 44, 0, 380, 378, 1, 0, 0, 0, 381, 384, 1, 0, 0, 0, 382, 380, 1, 0, 0, 0, 382, 383, 1, 0, 0, 0, 383, 385, 1, 0, 0, 0, 384, 382, 1, 0, 0, 0, 385, 386, 5, 66, 0, 0, 386, 388, 1, 0, 0, 0, 387, 345, 1, 0, 0, 0, 387, 346, 1, 0, 0, 0, 387, 349, 1, 0, 0, 0, 387, 350, 1, 0, 0, 0, 387, 351, 1, 0, 0, 0, 387, 352, 1, 0, 0, 0, 387, 353, 1, 0, 0, 0, 387, 354, 1, 0, 0, 0, 387, 365, 1, 0, 0, 0, 387, 376, 1, 0, 0, 0, 388, 55, 1, 0, 0, 0, 389, 390, 5, 10, 0, 0, 390, 391, 5, 28, 0, 0, 391, 57, 1, 0, 0, 0, 392, 393, 5, 16, 0, 0, 393, 398, 3, 60, 30, 0, 394, 395, 5, 35, 0, 0, 395, 397, 3, 60, 30, 0, 396, 394, 1, 0, 0, 0, 397, 400, 1, 0, 0, 0, 398, 396, 1, 0, 0, 0, 398, 399, 1, 0, 0, 0, 399, 59, 1, 0, 0, 0, 400, 398, 1, 0, 0, 0, 401, 403, 3, 10, 5, 0, 402, 404, 7, 3, 0, 0, 403, 402, 1, 0, 0, 0, 403, 404, 1, 0, 0, 0, 404, 407, 1, 0, 0, 0, 405, 406, 5, 47, 0, 0, 406, 408, 7, 4, 0, 0, 407, 405, 1, 0, 0, 0, 407, 408, 1, 0, 0, 0, 408, 61, 1, 0, 0, 0, 409, 410, 5, 9, 0, 0, 410, 415, 3, 48, 24, 0, 411, 412, 5, 35, 0, 0, 412, 414, 3, 48, 24, 0, 413, 411, 1, 0, 0, 0, 414, 417, 1, 0, 0, 0, 415, 413, 1, 0, 0, 0, 415, 416, 1, 0, 0, 0, 416, 63, 1, 0, 0, 0, 417, 415, 1, 0, 0, 0, 418, 419, 5, 2, 0, 0, 419, 424, 3, 48, 24, 0, 420, 421, 5, 35, 0, 0, 421, 423, 3, 48, 24, 0, 422, 420, 1, 0, 0, 0, 423, 426, 1, 0, 0, 0, 424, 422, 1, 0, 0, 0, 424, 425, 1, 0, 0, 0, 425, 65, 1, 0, 0, 0, 426, 424, 1, 0, 0, 0, 427, 428, 5, 13, 0, 0, 428, 433, 3, 68, 34, 0, 429, 430, 5, 35, 0, 0, 430, 432, 3, 68, 34, 0, 431, 429, 1, 0, 0, 0, 432, 435, 1, 0, 0, 0, 433, 431, 1, 0, 0, 0, 433, 434, 1, 0, 0, 0, 434, 67, 1, 0, 0, 0, 435, 433, 1, 0, 0, 0, 436, 437, 3, 48, 24, 0, 437, 438, 5, 81, 0, 0, 438, 439, 3, 48, 24, 0, 439, 69, 1, 0, 0, 0, 440, 441, 5, 1, 0, 0, 441, 442, 3, 18, 9, 0, 442, 444, 3, 88, 44, 0, 443, 445, 3, 76, 38, 0, 444, 443, 1, 0, 0, 0, 444, 445, 1, 0, 0, 0, 445, 71, 1, 0, 0, 0, 446, 447, 5, 7, 0, 0, 447, 448, 3, 18, 9, 0, 448, 449, 3, 88, 44, 0, 449, 73, 1, 0, 0, 0, 450, 451, 5, 12, 0, 0, 451, 452, 3, 46, 23, 0, 452, 75, 1, 0, 0, 0, 453, 458, 3, 78, 39, 0, 454, 455, 5, 35, 0, 0, 455, 457, 3, 78, 39, 0, 456, 454, 1, 0, 0, 0, 457, 460, 1, 0, 0, 0, 458, 456, 1, 0, 0, 0, 458, 459, 1, 0, 0, 0, 459, 77, 1, 0, 0, 0, 460, 458, 1, 0, 0, 0, 461, 462, 3, 50, 25, 0, 462, 463, 5, 33, 0, 0, 463, 464, 3, 54, 27, 0, 464, 79, 1, 0, 0, 0, 465, 466, 7, 5, 0, 0, 466, 81, 1, 0, 0, 0, 467, 470, 3, 84, 42, 0, 468, 470, 3, 86, 43, 0, 469, 467, 1, 0, 0, 0, 469, 468, 1, 0, 0, 0, 470, 83, 1, 0, 0, 0, 471, 473, 7, 0, 0, 0, 472, 471, 1, 0, 0, 0, 472, 473, 1, 0, 0, 0, 473, 474, 1, 0, 0, 0, 474, 475, 5, 29, 0, 0, 475, 85, 1, 0, 0, 0, 476, 478, 7, 0, 0, 0, 477, 476, 1, 0, 0, 0, 477, 478, 1, 0, 0, 0, 478, 479, 1, 0, 0, 0, 479, 480, 5, 28, 0, 0, 480, 87, 1, 0, 0, 0, 481, 482, 5, 27, 0, 0, 482, 89, 1, 0, 0, 0, 483, 484, 7, 6, 0, 0, 484, 91, 1, 0, 0, 0, 485, 486, 5, 5, 0, 0, 486, 487, 3, 94, 47, 0, 487, 93, 1, 0, 0, 0, 488, 489, 5, 65, 0, 0, 489, 490, 3, 2, 1, 0, 490, 491, 5, 66, 0, 0, 491, 95, 1, 0, 0, 0, 492, 493, 5, 15, 0, 0, 493, 494, 5, 97, 0, 0, 494, 97, 1, 0, 0, 0, 495, 496, 5, 11, 0, 0, 496, 497, 5, 101, 0, 0, 497, 99, 1, 0, 0, 0, 498, 499, 5, 3, 0, 0, 499, 502, 5, 87, 0, 0, 500, 501, 5, 85, 0, 0, 501, 503, 3, 48, 24, 0, 502, 500, 1, 0, 0, 0, 502, 503, 1, 0, 0, 0, 503, 513, 1, 0, 0, 0, 504, 505, 5, 86, 0, 0, 505, 510, 3, 102, 51, 0, 506, 507, 5, 35, 0, 0, 507, 509, 3, 102, 51, 0, 508, 506, 1, 0, 0, 0, 509, 512, 1, 0, 0, 0, 510, 508, 1, 0, 0, 0, 510, 511, 1, 0, 0, 0, 511, 514, 1, 0, 0, 0, 512, 510, 1, 0, 0, 0, 513, 504, 1, 0, 0, 0, 513, 514, 1, 0, 0, 0, 514, 101, 1, 0, 0, 0, 515, 516, 3, 48, 24, 0, 516, 517, 5, 33, 0, 0, 517, 519, 1, 0, 0, 0, 518, 515, 1, 0, 0, 0, 518, 519, 1, 0, 0, 0, 519, 520, 1, 0, 0, 0, 520, 521, 3, 48, 24, 0, 521, 103, 1, 0, 0, 0, 50, 115, 123, 138, 150, 159, 167, 171, 179, 181, 186, 193, 198, 205, 211, 219, 221, 232, 239, 250, 253, 267, 275, 283, 287, 293, 301, 313, 317, 323, 330, 338, 360, 371, 382, 387, 398, 403, 407, 415, 424, 433, 444, 458, 469, 472, 477, 502, 510, 513, 518] \ No newline at end of file diff --git a/packages/kbn-esql-ast/src/antlr/esql_parser.tokens b/packages/kbn-esql-ast/src/antlr/esql_parser.tokens index b496aa68b61f7..d2e7a695282ec 100644 --- a/packages/kbn-esql-ast/src/antlr/esql_parser.tokens +++ b/packages/kbn-esql-ast/src/antlr/esql_parser.tokens @@ -69,45 +69,44 @@ QUOTED_IDENTIFIER=68 EXPR_LINE_COMMENT=69 EXPR_MULTILINE_COMMENT=70 EXPR_WS=71 -OPTIONS=72 -METADATA=73 -FROM_UNQUOTED_IDENTIFIER=74 -FROM_LINE_COMMENT=75 -FROM_MULTILINE_COMMENT=76 -FROM_WS=77 -ID_PATTERN=78 -PROJECT_LINE_COMMENT=79 -PROJECT_MULTILINE_COMMENT=80 -PROJECT_WS=81 -AS=82 -RENAME_LINE_COMMENT=83 -RENAME_MULTILINE_COMMENT=84 -RENAME_WS=85 -ON=86 -WITH=87 -ENRICH_POLICY_NAME=88 -ENRICH_LINE_COMMENT=89 -ENRICH_MULTILINE_COMMENT=90 -ENRICH_WS=91 -ENRICH_FIELD_LINE_COMMENT=92 -ENRICH_FIELD_MULTILINE_COMMENT=93 -ENRICH_FIELD_WS=94 -MVEXPAND_LINE_COMMENT=95 -MVEXPAND_MULTILINE_COMMENT=96 -MVEXPAND_WS=97 -INFO=98 -SHOW_LINE_COMMENT=99 -SHOW_MULTILINE_COMMENT=100 -SHOW_WS=101 -FUNCTIONS=102 -META_LINE_COMMENT=103 -META_MULTILINE_COMMENT=104 -META_WS=105 -COLON=106 -SETTING=107 -SETTING_LINE_COMMENT=108 -SETTTING_MULTILINE_COMMENT=109 -SETTING_WS=110 +METADATA=72 +FROM_UNQUOTED_IDENTIFIER=73 +FROM_LINE_COMMENT=74 +FROM_MULTILINE_COMMENT=75 +FROM_WS=76 +ID_PATTERN=77 +PROJECT_LINE_COMMENT=78 +PROJECT_MULTILINE_COMMENT=79 +PROJECT_WS=80 +AS=81 +RENAME_LINE_COMMENT=82 +RENAME_MULTILINE_COMMENT=83 +RENAME_WS=84 +ON=85 +WITH=86 +ENRICH_POLICY_NAME=87 +ENRICH_LINE_COMMENT=88 +ENRICH_MULTILINE_COMMENT=89 +ENRICH_WS=90 +ENRICH_FIELD_LINE_COMMENT=91 +ENRICH_FIELD_MULTILINE_COMMENT=92 +ENRICH_FIELD_WS=93 +MVEXPAND_LINE_COMMENT=94 +MVEXPAND_MULTILINE_COMMENT=95 +MVEXPAND_WS=96 +INFO=97 +SHOW_LINE_COMMENT=98 +SHOW_MULTILINE_COMMENT=99 +SHOW_WS=100 +FUNCTIONS=101 +META_LINE_COMMENT=102 +META_MULTILINE_COMMENT=103 +META_WS=104 +COLON=105 +SETTING=106 +SETTING_LINE_COMMENT=107 +SETTTING_MULTILINE_COMMENT=108 +SETTING_WS=109 'dissect'=1 'drop'=2 'enrich'=3 @@ -163,11 +162,10 @@ SETTING_WS=110 '/'=63 '%'=64 ']'=66 -'options'=72 -'metadata'=73 -'as'=82 -'on'=86 -'with'=87 -'info'=98 -'functions'=102 -':'=106 +'metadata'=72 +'as'=81 +'on'=85 +'with'=86 +'info'=97 +'functions'=101 +':'=105 diff --git a/packages/kbn-esql-ast/src/antlr/esql_parser.ts b/packages/kbn-esql-ast/src/antlr/esql_parser.ts index f8151aae343e8..d0258b35756e9 100644 --- a/packages/kbn-esql-ast/src/antlr/esql_parser.ts +++ b/packages/kbn-esql-ast/src/antlr/esql_parser.ts @@ -89,45 +89,44 @@ export default class esql_parser extends Parser { public static readonly EXPR_LINE_COMMENT = 69; public static readonly EXPR_MULTILINE_COMMENT = 70; public static readonly EXPR_WS = 71; - public static readonly OPTIONS = 72; - public static readonly METADATA = 73; - public static readonly FROM_UNQUOTED_IDENTIFIER = 74; - public static readonly FROM_LINE_COMMENT = 75; - public static readonly FROM_MULTILINE_COMMENT = 76; - public static readonly FROM_WS = 77; - public static readonly ID_PATTERN = 78; - public static readonly PROJECT_LINE_COMMENT = 79; - public static readonly PROJECT_MULTILINE_COMMENT = 80; - public static readonly PROJECT_WS = 81; - public static readonly AS = 82; - public static readonly RENAME_LINE_COMMENT = 83; - public static readonly RENAME_MULTILINE_COMMENT = 84; - public static readonly RENAME_WS = 85; - public static readonly ON = 86; - public static readonly WITH = 87; - public static readonly ENRICH_POLICY_NAME = 88; - public static readonly ENRICH_LINE_COMMENT = 89; - public static readonly ENRICH_MULTILINE_COMMENT = 90; - public static readonly ENRICH_WS = 91; - public static readonly ENRICH_FIELD_LINE_COMMENT = 92; - public static readonly ENRICH_FIELD_MULTILINE_COMMENT = 93; - public static readonly ENRICH_FIELD_WS = 94; - public static readonly MVEXPAND_LINE_COMMENT = 95; - public static readonly MVEXPAND_MULTILINE_COMMENT = 96; - public static readonly MVEXPAND_WS = 97; - public static readonly INFO = 98; - public static readonly SHOW_LINE_COMMENT = 99; - public static readonly SHOW_MULTILINE_COMMENT = 100; - public static readonly SHOW_WS = 101; - public static readonly FUNCTIONS = 102; - public static readonly META_LINE_COMMENT = 103; - public static readonly META_MULTILINE_COMMENT = 104; - public static readonly META_WS = 105; - public static readonly COLON = 106; - public static readonly SETTING = 107; - public static readonly SETTING_LINE_COMMENT = 108; - public static readonly SETTTING_MULTILINE_COMMENT = 109; - public static readonly SETTING_WS = 110; + public static readonly METADATA = 72; + public static readonly FROM_UNQUOTED_IDENTIFIER = 73; + public static readonly FROM_LINE_COMMENT = 74; + public static readonly FROM_MULTILINE_COMMENT = 75; + public static readonly FROM_WS = 76; + public static readonly ID_PATTERN = 77; + public static readonly PROJECT_LINE_COMMENT = 78; + public static readonly PROJECT_MULTILINE_COMMENT = 79; + public static readonly PROJECT_WS = 80; + public static readonly AS = 81; + public static readonly RENAME_LINE_COMMENT = 82; + public static readonly RENAME_MULTILINE_COMMENT = 83; + public static readonly RENAME_WS = 84; + public static readonly ON = 85; + public static readonly WITH = 86; + public static readonly ENRICH_POLICY_NAME = 87; + public static readonly ENRICH_LINE_COMMENT = 88; + public static readonly ENRICH_MULTILINE_COMMENT = 89; + public static readonly ENRICH_WS = 90; + public static readonly ENRICH_FIELD_LINE_COMMENT = 91; + public static readonly ENRICH_FIELD_MULTILINE_COMMENT = 92; + public static readonly ENRICH_FIELD_WS = 93; + public static readonly MVEXPAND_LINE_COMMENT = 94; + public static readonly MVEXPAND_MULTILINE_COMMENT = 95; + public static readonly MVEXPAND_WS = 96; + public static readonly INFO = 97; + public static readonly SHOW_LINE_COMMENT = 98; + public static readonly SHOW_MULTILINE_COMMENT = 99; + public static readonly SHOW_WS = 100; + public static readonly FUNCTIONS = 101; + public static readonly META_LINE_COMMENT = 102; + public static readonly META_MULTILINE_COMMENT = 103; + public static readonly META_WS = 104; + public static readonly COLON = 105; + public static readonly SETTING = 106; + public static readonly SETTING_LINE_COMMENT = 107; + public static readonly SETTTING_MULTILINE_COMMENT = 108; + public static readonly SETTING_WS = 109; public static readonly EOF = Token.EOF; public static readonly RULE_singleStatement = 0; public static readonly RULE_query = 1; @@ -146,43 +145,41 @@ export default class esql_parser extends Parser { public static readonly RULE_field = 14; public static readonly RULE_fromCommand = 15; public static readonly RULE_fromIdentifier = 16; - public static readonly RULE_fromOptions = 17; - public static readonly RULE_configOption = 18; - public static readonly RULE_metadata = 19; - public static readonly RULE_metadataOption = 20; - public static readonly RULE_deprecated_metadata = 21; - public static readonly RULE_evalCommand = 22; - public static readonly RULE_statsCommand = 23; - public static readonly RULE_inlinestatsCommand = 24; - public static readonly RULE_qualifiedName = 25; - public static readonly RULE_qualifiedNamePattern = 26; - public static readonly RULE_identifier = 27; - public static readonly RULE_identifierPattern = 28; - public static readonly RULE_constant = 29; - public static readonly RULE_limitCommand = 30; - public static readonly RULE_sortCommand = 31; - public static readonly RULE_orderExpression = 32; - public static readonly RULE_keepCommand = 33; - public static readonly RULE_dropCommand = 34; - public static readonly RULE_renameCommand = 35; - public static readonly RULE_renameClause = 36; - public static readonly RULE_dissectCommand = 37; - public static readonly RULE_grokCommand = 38; - public static readonly RULE_mvExpandCommand = 39; - public static readonly RULE_commandOptions = 40; - public static readonly RULE_commandOption = 41; - public static readonly RULE_booleanValue = 42; - public static readonly RULE_numericValue = 43; - public static readonly RULE_decimalValue = 44; - public static readonly RULE_integerValue = 45; - public static readonly RULE_string = 46; - public static readonly RULE_comparisonOperator = 47; - public static readonly RULE_explainCommand = 48; - public static readonly RULE_subqueryExpression = 49; - public static readonly RULE_showCommand = 50; - public static readonly RULE_metaCommand = 51; - public static readonly RULE_enrichCommand = 52; - public static readonly RULE_enrichWithClause = 53; + public static readonly RULE_metadata = 17; + public static readonly RULE_metadataOption = 18; + public static readonly RULE_deprecated_metadata = 19; + public static readonly RULE_evalCommand = 20; + public static readonly RULE_statsCommand = 21; + public static readonly RULE_inlinestatsCommand = 22; + public static readonly RULE_qualifiedName = 23; + public static readonly RULE_qualifiedNamePattern = 24; + public static readonly RULE_identifier = 25; + public static readonly RULE_identifierPattern = 26; + public static readonly RULE_constant = 27; + public static readonly RULE_limitCommand = 28; + public static readonly RULE_sortCommand = 29; + public static readonly RULE_orderExpression = 30; + public static readonly RULE_keepCommand = 31; + public static readonly RULE_dropCommand = 32; + public static readonly RULE_renameCommand = 33; + public static readonly RULE_renameClause = 34; + public static readonly RULE_dissectCommand = 35; + public static readonly RULE_grokCommand = 36; + public static readonly RULE_mvExpandCommand = 37; + public static readonly RULE_commandOptions = 38; + public static readonly RULE_commandOption = 39; + public static readonly RULE_booleanValue = 40; + public static readonly RULE_numericValue = 41; + public static readonly RULE_decimalValue = 42; + public static readonly RULE_integerValue = 43; + public static readonly RULE_string = 44; + public static readonly RULE_comparisonOperator = 45; + public static readonly RULE_explainCommand = 46; + public static readonly RULE_subqueryExpression = 47; + public static readonly RULE_showCommand = 48; + public static readonly RULE_metaCommand = 49; + public static readonly RULE_enrichCommand = 50; + public static readonly RULE_enrichWithClause = 51; public static readonly literalNames: (string | null)[] = [ null, "'dissect'", "'drop'", "'enrich'", "'eval'", "'explain'", @@ -220,7 +217,6 @@ export default class esql_parser extends Parser { "']'", null, null, null, null, null, - "'options'", "'metadata'", null, null, null, null, @@ -283,7 +279,6 @@ export default class esql_parser extends Parser { "EXPR_LINE_COMMENT", "EXPR_MULTILINE_COMMENT", "EXPR_WS", - "OPTIONS", "METADATA", "FROM_UNQUOTED_IDENTIFIER", "FROM_LINE_COMMENT", @@ -323,12 +318,12 @@ export default class esql_parser extends Parser { "singleStatement", "query", "sourceCommand", "processingCommand", "whereCommand", "booleanExpression", "regexBooleanExpression", "valueExpression", "operatorExpression", "primaryExpression", "functionExpression", "dataType", "rowCommand", "fields", - "field", "fromCommand", "fromIdentifier", "fromOptions", "configOption", - "metadata", "metadataOption", "deprecated_metadata", "evalCommand", "statsCommand", - "inlinestatsCommand", "qualifiedName", "qualifiedNamePattern", "identifier", - "identifierPattern", "constant", "limitCommand", "sortCommand", "orderExpression", - "keepCommand", "dropCommand", "renameCommand", "renameClause", "dissectCommand", - "grokCommand", "mvExpandCommand", "commandOptions", "commandOption", "booleanValue", + "field", "fromCommand", "fromIdentifier", "metadata", "metadataOption", + "deprecated_metadata", "evalCommand", "statsCommand", "inlinestatsCommand", + "qualifiedName", "qualifiedNamePattern", "identifier", "identifierPattern", + "constant", "limitCommand", "sortCommand", "orderExpression", "keepCommand", + "dropCommand", "renameCommand", "renameClause", "dissectCommand", "grokCommand", + "mvExpandCommand", "commandOptions", "commandOption", "booleanValue", "numericValue", "decimalValue", "integerValue", "string", "comparisonOperator", "explainCommand", "subqueryExpression", "showCommand", "metaCommand", "enrichCommand", "enrichWithClause", @@ -354,9 +349,9 @@ export default class esql_parser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 108; + this.state = 104; this.query(0); - this.state = 109; + this.state = 105; this.match(esql_parser.EOF); } } @@ -398,11 +393,11 @@ export default class esql_parser extends Parser { this._ctx = localctx; _prevctx = localctx; - this.state = 112; + this.state = 108; this.sourceCommand(); } this._ctx.stop = this._input.LT(-1); - this.state = 119; + this.state = 115; this._errHandler.sync(this); _alt = this._interp.adaptivePredict(this._input, 0, this._ctx); while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { @@ -415,18 +410,18 @@ export default class esql_parser extends Parser { { localctx = new CompositeQueryContext(this, new QueryContext(this, _parentctx, _parentState)); this.pushNewRecursionContext(localctx, _startState, esql_parser.RULE_query); - this.state = 114; + this.state = 110; if (!(this.precpred(this._ctx, 1))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 1)"); } - this.state = 115; + this.state = 111; this.match(esql_parser.PIPE); - this.state = 116; + this.state = 112; this.processingCommand(); } } } - this.state = 121; + this.state = 117; this._errHandler.sync(this); _alt = this._interp.adaptivePredict(this._input, 0, this._ctx); } @@ -451,41 +446,41 @@ export default class esql_parser extends Parser { let localctx: SourceCommandContext = new SourceCommandContext(this, this._ctx, this.state); this.enterRule(localctx, 4, esql_parser.RULE_sourceCommand); try { - this.state = 127; + this.state = 123; this._errHandler.sync(this); switch (this._input.LA(1)) { case 5: this.enterOuterAlt(localctx, 1); { - this.state = 122; + this.state = 118; this.explainCommand(); } break; case 6: this.enterOuterAlt(localctx, 2); { - this.state = 123; + this.state = 119; this.fromCommand(); } break; case 14: this.enterOuterAlt(localctx, 3); { - this.state = 124; + this.state = 120; this.rowCommand(); } break; case 15: this.enterOuterAlt(localctx, 4); { - this.state = 125; + this.state = 121; this.showCommand(); } break; case 11: this.enterOuterAlt(localctx, 5); { - this.state = 126; + this.state = 122; this.metaCommand(); } break; @@ -512,97 +507,97 @@ export default class esql_parser extends Parser { let localctx: ProcessingCommandContext = new ProcessingCommandContext(this, this._ctx, this.state); this.enterRule(localctx, 6, esql_parser.RULE_processingCommand); try { - this.state = 142; + this.state = 138; this._errHandler.sync(this); switch (this._input.LA(1)) { case 4: this.enterOuterAlt(localctx, 1); { - this.state = 129; + this.state = 125; this.evalCommand(); } break; case 8: this.enterOuterAlt(localctx, 2); { - this.state = 130; + this.state = 126; this.inlinestatsCommand(); } break; case 10: this.enterOuterAlt(localctx, 3); { - this.state = 131; + this.state = 127; this.limitCommand(); } break; case 9: this.enterOuterAlt(localctx, 4); { - this.state = 132; + this.state = 128; this.keepCommand(); } break; case 16: this.enterOuterAlt(localctx, 5); { - this.state = 133; + this.state = 129; this.sortCommand(); } break; case 17: this.enterOuterAlt(localctx, 6); { - this.state = 134; + this.state = 130; this.statsCommand(); } break; case 18: this.enterOuterAlt(localctx, 7); { - this.state = 135; + this.state = 131; this.whereCommand(); } break; case 2: this.enterOuterAlt(localctx, 8); { - this.state = 136; + this.state = 132; this.dropCommand(); } break; case 13: this.enterOuterAlt(localctx, 9); { - this.state = 137; + this.state = 133; this.renameCommand(); } break; case 1: this.enterOuterAlt(localctx, 10); { - this.state = 138; + this.state = 134; this.dissectCommand(); } break; case 7: this.enterOuterAlt(localctx, 11); { - this.state = 139; + this.state = 135; this.grokCommand(); } break; case 3: this.enterOuterAlt(localctx, 12); { - this.state = 140; + this.state = 136; this.enrichCommand(); } break; case 12: this.enterOuterAlt(localctx, 13); { - this.state = 141; + this.state = 137; this.mvExpandCommand(); } break; @@ -631,9 +626,9 @@ export default class esql_parser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 144; + this.state = 140; this.match(esql_parser.WHERE); - this.state = 145; + this.state = 141; this.booleanExpression(0); } } @@ -671,7 +666,7 @@ export default class esql_parser extends Parser { let _alt: number; this.enterOuterAlt(localctx, 1); { - this.state = 175; + this.state = 171; this._errHandler.sync(this); switch ( this._interp.adaptivePredict(this._input, 6, this._ctx) ) { case 1: @@ -680,9 +675,9 @@ export default class esql_parser extends Parser { this._ctx = localctx; _prevctx = localctx; - this.state = 148; + this.state = 144; this.match(esql_parser.NOT); - this.state = 149; + this.state = 145; this.booleanExpression(7); } break; @@ -691,7 +686,7 @@ export default class esql_parser extends Parser { localctx = new BooleanDefaultContext(this, localctx); this._ctx = localctx; _prevctx = localctx; - this.state = 150; + this.state = 146; this.valueExpression(); } break; @@ -700,7 +695,7 @@ export default class esql_parser extends Parser { localctx = new RegexExpressionContext(this, localctx); this._ctx = localctx; _prevctx = localctx; - this.state = 151; + this.state = 147; this.regexBooleanExpression(); } break; @@ -709,41 +704,41 @@ export default class esql_parser extends Parser { localctx = new LogicalInContext(this, localctx); this._ctx = localctx; _prevctx = localctx; - this.state = 152; + this.state = 148; this.valueExpression(); - this.state = 154; + this.state = 150; this._errHandler.sync(this); _la = this._input.LA(1); if (_la===45) { { - this.state = 153; + this.state = 149; this.match(esql_parser.NOT); } } - this.state = 156; + this.state = 152; this.match(esql_parser.IN); - this.state = 157; + this.state = 153; this.match(esql_parser.LP); - this.state = 158; + this.state = 154; this.valueExpression(); - this.state = 163; + this.state = 159; this._errHandler.sync(this); _la = this._input.LA(1); while (_la===35) { { { - this.state = 159; + this.state = 155; this.match(esql_parser.COMMA); - this.state = 160; + this.state = 156; this.valueExpression(); } } - this.state = 165; + this.state = 161; this._errHandler.sync(this); _la = this._input.LA(1); } - this.state = 166; + this.state = 162; this.match(esql_parser.RP); } break; @@ -752,27 +747,27 @@ export default class esql_parser extends Parser { localctx = new IsNullContext(this, localctx); this._ctx = localctx; _prevctx = localctx; - this.state = 168; + this.state = 164; this.valueExpression(); - this.state = 169; + this.state = 165; this.match(esql_parser.IS); - this.state = 171; + this.state = 167; this._errHandler.sync(this); _la = this._input.LA(1); if (_la===45) { { - this.state = 170; + this.state = 166; this.match(esql_parser.NOT); } } - this.state = 173; + this.state = 169; this.match(esql_parser.NULL); } break; } this._ctx.stop = this._input.LT(-1); - this.state = 185; + this.state = 181; this._errHandler.sync(this); _alt = this._interp.adaptivePredict(this._input, 8, this._ctx); while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { @@ -782,7 +777,7 @@ export default class esql_parser extends Parser { } _prevctx = localctx; { - this.state = 183; + this.state = 179; this._errHandler.sync(this); switch ( this._interp.adaptivePredict(this._input, 7, this._ctx) ) { case 1: @@ -790,13 +785,13 @@ export default class esql_parser extends Parser { localctx = new LogicalBinaryContext(this, new BooleanExpressionContext(this, _parentctx, _parentState)); (localctx as LogicalBinaryContext)._left = _prevctx; this.pushNewRecursionContext(localctx, _startState, esql_parser.RULE_booleanExpression); - this.state = 177; + this.state = 173; if (!(this.precpred(this._ctx, 4))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 4)"); } - this.state = 178; + this.state = 174; (localctx as LogicalBinaryContext)._operator = this.match(esql_parser.AND); - this.state = 179; + this.state = 175; (localctx as LogicalBinaryContext)._right = this.booleanExpression(5); } break; @@ -805,20 +800,20 @@ export default class esql_parser extends Parser { localctx = new LogicalBinaryContext(this, new BooleanExpressionContext(this, _parentctx, _parentState)); (localctx as LogicalBinaryContext)._left = _prevctx; this.pushNewRecursionContext(localctx, _startState, esql_parser.RULE_booleanExpression); - this.state = 180; + this.state = 176; if (!(this.precpred(this._ctx, 3))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 3)"); } - this.state = 181; + this.state = 177; (localctx as LogicalBinaryContext)._operator = this.match(esql_parser.OR); - this.state = 182; + this.state = 178; (localctx as LogicalBinaryContext)._right = this.booleanExpression(4); } break; } } } - this.state = 187; + this.state = 183; this._errHandler.sync(this); _alt = this._interp.adaptivePredict(this._input, 8, this._ctx); } @@ -844,48 +839,48 @@ export default class esql_parser extends Parser { this.enterRule(localctx, 12, esql_parser.RULE_regexBooleanExpression); let _la: number; try { - this.state = 202; + this.state = 198; this._errHandler.sync(this); switch ( this._interp.adaptivePredict(this._input, 11, this._ctx) ) { case 1: this.enterOuterAlt(localctx, 1); { - this.state = 188; + this.state = 184; this.valueExpression(); - this.state = 190; + this.state = 186; this._errHandler.sync(this); _la = this._input.LA(1); if (_la===45) { { - this.state = 189; + this.state = 185; this.match(esql_parser.NOT); } } - this.state = 192; + this.state = 188; localctx._kind = this.match(esql_parser.LIKE); - this.state = 193; + this.state = 189; localctx._pattern = this.string_(); } break; case 2: this.enterOuterAlt(localctx, 2); { - this.state = 195; + this.state = 191; this.valueExpression(); - this.state = 197; + this.state = 193; this._errHandler.sync(this); _la = this._input.LA(1); if (_la===45) { { - this.state = 196; + this.state = 192; this.match(esql_parser.NOT); } } - this.state = 199; + this.state = 195; localctx._kind = this.match(esql_parser.RLIKE); - this.state = 200; + this.state = 196; localctx._pattern = this.string_(); } break; @@ -910,14 +905,14 @@ export default class esql_parser extends Parser { let localctx: ValueExpressionContext = new ValueExpressionContext(this, this._ctx, this.state); this.enterRule(localctx, 14, esql_parser.RULE_valueExpression); try { - this.state = 209; + this.state = 205; this._errHandler.sync(this); switch ( this._interp.adaptivePredict(this._input, 12, this._ctx) ) { case 1: localctx = new ValueExpressionDefaultContext(this, localctx); this.enterOuterAlt(localctx, 1); { - this.state = 204; + this.state = 200; this.operatorExpression(0); } break; @@ -925,11 +920,11 @@ export default class esql_parser extends Parser { localctx = new ComparisonContext(this, localctx); this.enterOuterAlt(localctx, 2); { - this.state = 205; + this.state = 201; (localctx as ComparisonContext)._left = this.operatorExpression(0); - this.state = 206; + this.state = 202; this.comparisonOperator(); - this.state = 207; + this.state = 203; (localctx as ComparisonContext)._right = this.operatorExpression(0); } break; @@ -969,7 +964,7 @@ export default class esql_parser extends Parser { let _alt: number; this.enterOuterAlt(localctx, 1); { - this.state = 215; + this.state = 211; this._errHandler.sync(this); switch ( this._interp.adaptivePredict(this._input, 13, this._ctx) ) { case 1: @@ -978,7 +973,7 @@ export default class esql_parser extends Parser { this._ctx = localctx; _prevctx = localctx; - this.state = 212; + this.state = 208; this.primaryExpression(0); } break; @@ -987,7 +982,7 @@ export default class esql_parser extends Parser { localctx = new ArithmeticUnaryContext(this, localctx); this._ctx = localctx; _prevctx = localctx; - this.state = 213; + this.state = 209; (localctx as ArithmeticUnaryContext)._operator = this._input.LT(1); _la = this._input.LA(1); if(!(_la===60 || _la===61)) { @@ -997,13 +992,13 @@ export default class esql_parser extends Parser { this._errHandler.reportMatch(this); this.consume(); } - this.state = 214; + this.state = 210; this.operatorExpression(3); } break; } this._ctx.stop = this._input.LT(-1); - this.state = 225; + this.state = 221; this._errHandler.sync(this); _alt = this._interp.adaptivePredict(this._input, 15, this._ctx); while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { @@ -1013,7 +1008,7 @@ export default class esql_parser extends Parser { } _prevctx = localctx; { - this.state = 223; + this.state = 219; this._errHandler.sync(this); switch ( this._interp.adaptivePredict(this._input, 14, this._ctx) ) { case 1: @@ -1021,11 +1016,11 @@ export default class esql_parser extends Parser { localctx = new ArithmeticBinaryContext(this, new OperatorExpressionContext(this, _parentctx, _parentState)); (localctx as ArithmeticBinaryContext)._left = _prevctx; this.pushNewRecursionContext(localctx, _startState, esql_parser.RULE_operatorExpression); - this.state = 217; + this.state = 213; if (!(this.precpred(this._ctx, 2))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 2)"); } - this.state = 218; + this.state = 214; (localctx as ArithmeticBinaryContext)._operator = this._input.LT(1); _la = this._input.LA(1); if(!(((((_la - 62)) & ~0x1F) === 0 && ((1 << (_la - 62)) & 7) !== 0))) { @@ -1035,7 +1030,7 @@ export default class esql_parser extends Parser { this._errHandler.reportMatch(this); this.consume(); } - this.state = 219; + this.state = 215; (localctx as ArithmeticBinaryContext)._right = this.operatorExpression(3); } break; @@ -1044,11 +1039,11 @@ export default class esql_parser extends Parser { localctx = new ArithmeticBinaryContext(this, new OperatorExpressionContext(this, _parentctx, _parentState)); (localctx as ArithmeticBinaryContext)._left = _prevctx; this.pushNewRecursionContext(localctx, _startState, esql_parser.RULE_operatorExpression); - this.state = 220; + this.state = 216; if (!(this.precpred(this._ctx, 1))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 1)"); } - this.state = 221; + this.state = 217; (localctx as ArithmeticBinaryContext)._operator = this._input.LT(1); _la = this._input.LA(1); if(!(_la===60 || _la===61)) { @@ -1058,14 +1053,14 @@ export default class esql_parser extends Parser { this._errHandler.reportMatch(this); this.consume(); } - this.state = 222; + this.state = 218; (localctx as ArithmeticBinaryContext)._right = this.operatorExpression(2); } break; } } } - this.state = 227; + this.state = 223; this._errHandler.sync(this); _alt = this._interp.adaptivePredict(this._input, 15, this._ctx); } @@ -1104,7 +1099,7 @@ export default class esql_parser extends Parser { let _alt: number; this.enterOuterAlt(localctx, 1); { - this.state = 236; + this.state = 232; this._errHandler.sync(this); switch ( this._interp.adaptivePredict(this._input, 16, this._ctx) ) { case 1: @@ -1113,7 +1108,7 @@ export default class esql_parser extends Parser { this._ctx = localctx; _prevctx = localctx; - this.state = 229; + this.state = 225; this.constant(); } break; @@ -1122,7 +1117,7 @@ export default class esql_parser extends Parser { localctx = new DereferenceContext(this, localctx); this._ctx = localctx; _prevctx = localctx; - this.state = 230; + this.state = 226; this.qualifiedName(); } break; @@ -1131,7 +1126,7 @@ export default class esql_parser extends Parser { localctx = new FunctionContext(this, localctx); this._ctx = localctx; _prevctx = localctx; - this.state = 231; + this.state = 227; this.functionExpression(); } break; @@ -1140,17 +1135,17 @@ export default class esql_parser extends Parser { localctx = new ParenthesizedExpressionContext(this, localctx); this._ctx = localctx; _prevctx = localctx; - this.state = 232; + this.state = 228; this.match(esql_parser.LP); - this.state = 233; + this.state = 229; this.booleanExpression(0); - this.state = 234; + this.state = 230; this.match(esql_parser.RP); } break; } this._ctx.stop = this._input.LT(-1); - this.state = 243; + this.state = 239; this._errHandler.sync(this); _alt = this._interp.adaptivePredict(this._input, 17, this._ctx); while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { @@ -1163,18 +1158,18 @@ export default class esql_parser extends Parser { { localctx = new InlineCastContext(this, new PrimaryExpressionContext(this, _parentctx, _parentState)); this.pushNewRecursionContext(localctx, _startState, esql_parser.RULE_primaryExpression); - this.state = 238; + this.state = 234; if (!(this.precpred(this._ctx, 1))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 1)"); } - this.state = 239; + this.state = 235; this.match(esql_parser.CAST_OP); - this.state = 240; + this.state = 236; this.dataType(); } } } - this.state = 245; + this.state = 241; this._errHandler.sync(this); _alt = this._interp.adaptivePredict(this._input, 17, this._ctx); } @@ -1202,16 +1197,16 @@ export default class esql_parser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 246; + this.state = 242; this.identifier(); - this.state = 247; + this.state = 243; this.match(esql_parser.LP); - this.state = 257; + this.state = 253; this._errHandler.sync(this); switch (this._input.LA(1)) { case 62: { - this.state = 248; + this.state = 244; this.match(esql_parser.ASTERISK); } break; @@ -1231,21 +1226,21 @@ export default class esql_parser extends Parser { case 68: { { - this.state = 249; + this.state = 245; this.booleanExpression(0); - this.state = 254; + this.state = 250; this._errHandler.sync(this); _la = this._input.LA(1); while (_la===35) { { { - this.state = 250; + this.state = 246; this.match(esql_parser.COMMA); - this.state = 251; + this.state = 247; this.booleanExpression(0); } } - this.state = 256; + this.state = 252; this._errHandler.sync(this); _la = this._input.LA(1); } @@ -1257,7 +1252,7 @@ export default class esql_parser extends Parser { default: break; } - this.state = 259; + this.state = 255; this.match(esql_parser.RP); } } @@ -1283,7 +1278,7 @@ export default class esql_parser extends Parser { localctx = new ToDataTypeContext(this, localctx); this.enterOuterAlt(localctx, 1); { - this.state = 261; + this.state = 257; this.identifier(); } } @@ -1308,9 +1303,9 @@ export default class esql_parser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 263; + this.state = 259; this.match(esql_parser.ROW); - this.state = 264; + this.state = 260; this.fields(); } } @@ -1336,23 +1331,23 @@ export default class esql_parser extends Parser { let _alt: number; this.enterOuterAlt(localctx, 1); { - this.state = 266; + this.state = 262; this.field(); - this.state = 271; + this.state = 267; this._errHandler.sync(this); _alt = this._interp.adaptivePredict(this._input, 20, this._ctx); while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { if (_alt === 1) { { { - this.state = 267; + this.state = 263; this.match(esql_parser.COMMA); - this.state = 268; + this.state = 264; this.field(); } } } - this.state = 273; + this.state = 269; this._errHandler.sync(this); _alt = this._interp.adaptivePredict(this._input, 20, this._ctx); } @@ -1377,24 +1372,24 @@ export default class esql_parser extends Parser { let localctx: FieldContext = new FieldContext(this, this._ctx, this.state); this.enterRule(localctx, 28, esql_parser.RULE_field); try { - this.state = 279; + this.state = 275; this._errHandler.sync(this); switch ( this._interp.adaptivePredict(this._input, 21, this._ctx) ) { case 1: this.enterOuterAlt(localctx, 1); { - this.state = 274; + this.state = 270; this.booleanExpression(0); } break; case 2: this.enterOuterAlt(localctx, 2); { - this.state = 275; + this.state = 271; this.qualifiedName(); - this.state = 276; + this.state = 272; this.match(esql_parser.ASSIGN); - this.state = 277; + this.state = 273; this.booleanExpression(0); } break; @@ -1422,48 +1417,38 @@ export default class esql_parser extends Parser { let _alt: number; this.enterOuterAlt(localctx, 1); { - this.state = 281; + this.state = 277; this.match(esql_parser.FROM); - this.state = 282; + this.state = 278; this.fromIdentifier(); - this.state = 287; + this.state = 283; this._errHandler.sync(this); _alt = this._interp.adaptivePredict(this._input, 22, this._ctx); while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { if (_alt === 1) { { { - this.state = 283; + this.state = 279; this.match(esql_parser.COMMA); - this.state = 284; + this.state = 280; this.fromIdentifier(); } } } - this.state = 289; + this.state = 285; this._errHandler.sync(this); _alt = this._interp.adaptivePredict(this._input, 22, this._ctx); } - this.state = 291; + this.state = 287; this._errHandler.sync(this); switch ( this._interp.adaptivePredict(this._input, 23, this._ctx) ) { case 1: { - this.state = 290; + this.state = 286; this.metadata(); } break; } - this.state = 294; - this._errHandler.sync(this); - switch ( this._interp.adaptivePredict(this._input, 24, this._ctx) ) { - case 1: - { - this.state = 293; - this.fromOptions(); - } - break; - } } } catch (re) { @@ -1487,7 +1472,7 @@ export default class esql_parser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 296; + this.state = 289; this.match(esql_parser.FROM_UNQUOTED_IDENTIFIER); } } @@ -1506,99 +1491,24 @@ export default class esql_parser extends Parser { return localctx; } // @RuleVersion(0) - public fromOptions(): FromOptionsContext { - let localctx: FromOptionsContext = new FromOptionsContext(this, this._ctx, this.state); - this.enterRule(localctx, 34, esql_parser.RULE_fromOptions); - try { - let _alt: number; - this.enterOuterAlt(localctx, 1); - { - this.state = 298; - this.match(esql_parser.OPTIONS); - this.state = 299; - this.configOption(); - this.state = 304; - this._errHandler.sync(this); - _alt = this._interp.adaptivePredict(this._input, 25, this._ctx); - while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { - if (_alt === 1) { - { - { - this.state = 300; - this.match(esql_parser.COMMA); - this.state = 301; - this.configOption(); - } - } - } - this.state = 306; - this._errHandler.sync(this); - _alt = this._interp.adaptivePredict(this._input, 25, this._ctx); - } - } - } - catch (re) { - if (re instanceof RecognitionException) { - localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return localctx; - } - // @RuleVersion(0) - public configOption(): ConfigOptionContext { - let localctx: ConfigOptionContext = new ConfigOptionContext(this, this._ctx, this.state); - this.enterRule(localctx, 36, esql_parser.RULE_configOption); - try { - this.enterOuterAlt(localctx, 1); - { - this.state = 307; - this.string_(); - this.state = 308; - this.match(esql_parser.ASSIGN); - this.state = 309; - this.string_(); - } - } - catch (re) { - if (re instanceof RecognitionException) { - localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } - finally { - this.exitRule(); - } - return localctx; - } - // @RuleVersion(0) public metadata(): MetadataContext { let localctx: MetadataContext = new MetadataContext(this, this._ctx, this.state); - this.enterRule(localctx, 38, esql_parser.RULE_metadata); + this.enterRule(localctx, 34, esql_parser.RULE_metadata); try { - this.state = 313; + this.state = 293; this._errHandler.sync(this); switch (this._input.LA(1)) { - case 73: + case 72: this.enterOuterAlt(localctx, 1); { - this.state = 311; + this.state = 291; this.metadataOption(); } break; case 65: this.enterOuterAlt(localctx, 2); { - this.state = 312; + this.state = 292; this.deprecated_metadata(); } break; @@ -1623,32 +1533,32 @@ export default class esql_parser extends Parser { // @RuleVersion(0) public metadataOption(): MetadataOptionContext { let localctx: MetadataOptionContext = new MetadataOptionContext(this, this._ctx, this.state); - this.enterRule(localctx, 40, esql_parser.RULE_metadataOption); + this.enterRule(localctx, 36, esql_parser.RULE_metadataOption); try { let _alt: number; this.enterOuterAlt(localctx, 1); { - this.state = 315; + this.state = 295; this.match(esql_parser.METADATA); - this.state = 316; + this.state = 296; this.fromIdentifier(); - this.state = 321; + this.state = 301; this._errHandler.sync(this); - _alt = this._interp.adaptivePredict(this._input, 27, this._ctx); + _alt = this._interp.adaptivePredict(this._input, 25, this._ctx); while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { if (_alt === 1) { { { - this.state = 317; + this.state = 297; this.match(esql_parser.COMMA); - this.state = 318; + this.state = 298; this.fromIdentifier(); } } } - this.state = 323; + this.state = 303; this._errHandler.sync(this); - _alt = this._interp.adaptivePredict(this._input, 27, this._ctx); + _alt = this._interp.adaptivePredict(this._input, 25, this._ctx); } } } @@ -1669,15 +1579,15 @@ export default class esql_parser extends Parser { // @RuleVersion(0) public deprecated_metadata(): Deprecated_metadataContext { let localctx: Deprecated_metadataContext = new Deprecated_metadataContext(this, this._ctx, this.state); - this.enterRule(localctx, 42, esql_parser.RULE_deprecated_metadata); + this.enterRule(localctx, 38, esql_parser.RULE_deprecated_metadata); try { this.enterOuterAlt(localctx, 1); { - this.state = 324; + this.state = 304; this.match(esql_parser.OPENING_BRACKET); - this.state = 325; + this.state = 305; this.metadataOption(); - this.state = 326; + this.state = 306; this.match(esql_parser.CLOSING_BRACKET); } } @@ -1698,13 +1608,13 @@ export default class esql_parser extends Parser { // @RuleVersion(0) public evalCommand(): EvalCommandContext { let localctx: EvalCommandContext = new EvalCommandContext(this, this._ctx, this.state); - this.enterRule(localctx, 44, esql_parser.RULE_evalCommand); + this.enterRule(localctx, 40, esql_parser.RULE_evalCommand); try { this.enterOuterAlt(localctx, 1); { - this.state = 328; + this.state = 308; this.match(esql_parser.EVAL); - this.state = 329; + this.state = 309; this.fields(); } } @@ -1725,30 +1635,30 @@ export default class esql_parser extends Parser { // @RuleVersion(0) public statsCommand(): StatsCommandContext { let localctx: StatsCommandContext = new StatsCommandContext(this, this._ctx, this.state); - this.enterRule(localctx, 46, esql_parser.RULE_statsCommand); + this.enterRule(localctx, 42, esql_parser.RULE_statsCommand); try { this.enterOuterAlt(localctx, 1); { - this.state = 331; + this.state = 311; this.match(esql_parser.STATS); - this.state = 333; + this.state = 313; this._errHandler.sync(this); - switch ( this._interp.adaptivePredict(this._input, 28, this._ctx) ) { + switch ( this._interp.adaptivePredict(this._input, 26, this._ctx) ) { case 1: { - this.state = 332; + this.state = 312; localctx._stats = this.fields(); } break; } - this.state = 337; + this.state = 317; this._errHandler.sync(this); - switch ( this._interp.adaptivePredict(this._input, 29, this._ctx) ) { + switch ( this._interp.adaptivePredict(this._input, 27, this._ctx) ) { case 1: { - this.state = 335; + this.state = 315; this.match(esql_parser.BY); - this.state = 336; + this.state = 316; localctx._grouping = this.fields(); } break; @@ -1772,22 +1682,22 @@ export default class esql_parser extends Parser { // @RuleVersion(0) public inlinestatsCommand(): InlinestatsCommandContext { let localctx: InlinestatsCommandContext = new InlinestatsCommandContext(this, this._ctx, this.state); - this.enterRule(localctx, 48, esql_parser.RULE_inlinestatsCommand); + this.enterRule(localctx, 44, esql_parser.RULE_inlinestatsCommand); try { this.enterOuterAlt(localctx, 1); { - this.state = 339; + this.state = 319; this.match(esql_parser.INLINESTATS); - this.state = 340; + this.state = 320; localctx._stats = this.fields(); - this.state = 343; + this.state = 323; this._errHandler.sync(this); - switch ( this._interp.adaptivePredict(this._input, 30, this._ctx) ) { + switch ( this._interp.adaptivePredict(this._input, 28, this._ctx) ) { case 1: { - this.state = 341; + this.state = 321; this.match(esql_parser.BY); - this.state = 342; + this.state = 322; localctx._grouping = this.fields(); } break; @@ -1811,30 +1721,30 @@ export default class esql_parser extends Parser { // @RuleVersion(0) public qualifiedName(): QualifiedNameContext { let localctx: QualifiedNameContext = new QualifiedNameContext(this, this._ctx, this.state); - this.enterRule(localctx, 50, esql_parser.RULE_qualifiedName); + this.enterRule(localctx, 46, esql_parser.RULE_qualifiedName); try { let _alt: number; this.enterOuterAlt(localctx, 1); { - this.state = 345; + this.state = 325; this.identifier(); - this.state = 350; + this.state = 330; this._errHandler.sync(this); - _alt = this._interp.adaptivePredict(this._input, 31, this._ctx); + _alt = this._interp.adaptivePredict(this._input, 29, this._ctx); while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { if (_alt === 1) { { { - this.state = 346; + this.state = 326; this.match(esql_parser.DOT); - this.state = 347; + this.state = 327; this.identifier(); } } } - this.state = 352; + this.state = 332; this._errHandler.sync(this); - _alt = this._interp.adaptivePredict(this._input, 31, this._ctx); + _alt = this._interp.adaptivePredict(this._input, 29, this._ctx); } } } @@ -1855,30 +1765,30 @@ export default class esql_parser extends Parser { // @RuleVersion(0) public qualifiedNamePattern(): QualifiedNamePatternContext { let localctx: QualifiedNamePatternContext = new QualifiedNamePatternContext(this, this._ctx, this.state); - this.enterRule(localctx, 52, esql_parser.RULE_qualifiedNamePattern); + this.enterRule(localctx, 48, esql_parser.RULE_qualifiedNamePattern); try { let _alt: number; this.enterOuterAlt(localctx, 1); { - this.state = 353; + this.state = 333; this.identifierPattern(); - this.state = 358; + this.state = 338; this._errHandler.sync(this); - _alt = this._interp.adaptivePredict(this._input, 32, this._ctx); + _alt = this._interp.adaptivePredict(this._input, 30, this._ctx); while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { if (_alt === 1) { { { - this.state = 354; + this.state = 334; this.match(esql_parser.DOT); - this.state = 355; + this.state = 335; this.identifierPattern(); } } } - this.state = 360; + this.state = 340; this._errHandler.sync(this); - _alt = this._interp.adaptivePredict(this._input, 32, this._ctx); + _alt = this._interp.adaptivePredict(this._input, 30, this._ctx); } } } @@ -1899,12 +1809,12 @@ export default class esql_parser extends Parser { // @RuleVersion(0) public identifier(): IdentifierContext { let localctx: IdentifierContext = new IdentifierContext(this, this._ctx, this.state); - this.enterRule(localctx, 54, esql_parser.RULE_identifier); + this.enterRule(localctx, 50, esql_parser.RULE_identifier); let _la: number; try { this.enterOuterAlt(localctx, 1); { - this.state = 361; + this.state = 341; _la = this._input.LA(1); if(!(_la===67 || _la===68)) { this._errHandler.recoverInline(this); @@ -1932,11 +1842,11 @@ export default class esql_parser extends Parser { // @RuleVersion(0) public identifierPattern(): IdentifierPatternContext { let localctx: IdentifierPatternContext = new IdentifierPatternContext(this, this._ctx, this.state); - this.enterRule(localctx, 56, esql_parser.RULE_identifierPattern); + this.enterRule(localctx, 52, esql_parser.RULE_identifierPattern); try { this.enterOuterAlt(localctx, 1); { - this.state = 363; + this.state = 343; this.match(esql_parser.ID_PATTERN); } } @@ -1957,17 +1867,17 @@ export default class esql_parser extends Parser { // @RuleVersion(0) public constant(): ConstantContext { let localctx: ConstantContext = new ConstantContext(this, this._ctx, this.state); - this.enterRule(localctx, 58, esql_parser.RULE_constant); + this.enterRule(localctx, 54, esql_parser.RULE_constant); let _la: number; try { - this.state = 407; + this.state = 387; this._errHandler.sync(this); - switch ( this._interp.adaptivePredict(this._input, 36, this._ctx) ) { + switch ( this._interp.adaptivePredict(this._input, 34, this._ctx) ) { case 1: localctx = new NullLiteralContext(this, localctx); this.enterOuterAlt(localctx, 1); { - this.state = 365; + this.state = 345; this.match(esql_parser.NULL); } break; @@ -1975,9 +1885,9 @@ export default class esql_parser extends Parser { localctx = new QualifiedIntegerLiteralContext(this, localctx); this.enterOuterAlt(localctx, 2); { - this.state = 366; + this.state = 346; this.integerValue(); - this.state = 367; + this.state = 347; this.match(esql_parser.UNQUOTED_IDENTIFIER); } break; @@ -1985,7 +1895,7 @@ export default class esql_parser extends Parser { localctx = new DecimalLiteralContext(this, localctx); this.enterOuterAlt(localctx, 3); { - this.state = 369; + this.state = 349; this.decimalValue(); } break; @@ -1993,7 +1903,7 @@ export default class esql_parser extends Parser { localctx = new IntegerLiteralContext(this, localctx); this.enterOuterAlt(localctx, 4); { - this.state = 370; + this.state = 350; this.integerValue(); } break; @@ -2001,7 +1911,7 @@ export default class esql_parser extends Parser { localctx = new BooleanLiteralContext(this, localctx); this.enterOuterAlt(localctx, 5); { - this.state = 371; + this.state = 351; this.booleanValue(); } break; @@ -2009,7 +1919,7 @@ export default class esql_parser extends Parser { localctx = new InputParamContext(this, localctx); this.enterOuterAlt(localctx, 6); { - this.state = 372; + this.state = 352; this.match(esql_parser.PARAM); } break; @@ -2017,7 +1927,7 @@ export default class esql_parser extends Parser { localctx = new StringLiteralContext(this, localctx); this.enterOuterAlt(localctx, 7); { - this.state = 373; + this.state = 353; this.string_(); } break; @@ -2025,27 +1935,27 @@ export default class esql_parser extends Parser { localctx = new NumericArrayLiteralContext(this, localctx); this.enterOuterAlt(localctx, 8); { - this.state = 374; + this.state = 354; this.match(esql_parser.OPENING_BRACKET); - this.state = 375; + this.state = 355; this.numericValue(); - this.state = 380; + this.state = 360; this._errHandler.sync(this); _la = this._input.LA(1); while (_la===35) { { { - this.state = 376; + this.state = 356; this.match(esql_parser.COMMA); - this.state = 377; + this.state = 357; this.numericValue(); } } - this.state = 382; + this.state = 362; this._errHandler.sync(this); _la = this._input.LA(1); } - this.state = 383; + this.state = 363; this.match(esql_parser.CLOSING_BRACKET); } break; @@ -2053,27 +1963,27 @@ export default class esql_parser extends Parser { localctx = new BooleanArrayLiteralContext(this, localctx); this.enterOuterAlt(localctx, 9); { - this.state = 385; + this.state = 365; this.match(esql_parser.OPENING_BRACKET); - this.state = 386; + this.state = 366; this.booleanValue(); - this.state = 391; + this.state = 371; this._errHandler.sync(this); _la = this._input.LA(1); while (_la===35) { { { - this.state = 387; + this.state = 367; this.match(esql_parser.COMMA); - this.state = 388; + this.state = 368; this.booleanValue(); } } - this.state = 393; + this.state = 373; this._errHandler.sync(this); _la = this._input.LA(1); } - this.state = 394; + this.state = 374; this.match(esql_parser.CLOSING_BRACKET); } break; @@ -2081,27 +1991,27 @@ export default class esql_parser extends Parser { localctx = new StringArrayLiteralContext(this, localctx); this.enterOuterAlt(localctx, 10); { - this.state = 396; + this.state = 376; this.match(esql_parser.OPENING_BRACKET); - this.state = 397; + this.state = 377; this.string_(); - this.state = 402; + this.state = 382; this._errHandler.sync(this); _la = this._input.LA(1); while (_la===35) { { { - this.state = 398; + this.state = 378; this.match(esql_parser.COMMA); - this.state = 399; + this.state = 379; this.string_(); } } - this.state = 404; + this.state = 384; this._errHandler.sync(this); _la = this._input.LA(1); } - this.state = 405; + this.state = 385; this.match(esql_parser.CLOSING_BRACKET); } break; @@ -2124,13 +2034,13 @@ export default class esql_parser extends Parser { // @RuleVersion(0) public limitCommand(): LimitCommandContext { let localctx: LimitCommandContext = new LimitCommandContext(this, this._ctx, this.state); - this.enterRule(localctx, 60, esql_parser.RULE_limitCommand); + this.enterRule(localctx, 56, esql_parser.RULE_limitCommand); try { this.enterOuterAlt(localctx, 1); { - this.state = 409; + this.state = 389; this.match(esql_parser.LIMIT); - this.state = 410; + this.state = 390; this.match(esql_parser.INTEGER_LITERAL); } } @@ -2151,32 +2061,32 @@ export default class esql_parser extends Parser { // @RuleVersion(0) public sortCommand(): SortCommandContext { let localctx: SortCommandContext = new SortCommandContext(this, this._ctx, this.state); - this.enterRule(localctx, 62, esql_parser.RULE_sortCommand); + this.enterRule(localctx, 58, esql_parser.RULE_sortCommand); try { let _alt: number; this.enterOuterAlt(localctx, 1); { - this.state = 412; + this.state = 392; this.match(esql_parser.SORT); - this.state = 413; + this.state = 393; this.orderExpression(); - this.state = 418; + this.state = 398; this._errHandler.sync(this); - _alt = this._interp.adaptivePredict(this._input, 37, this._ctx); + _alt = this._interp.adaptivePredict(this._input, 35, this._ctx); while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { if (_alt === 1) { { { - this.state = 414; + this.state = 394; this.match(esql_parser.COMMA); - this.state = 415; + this.state = 395; this.orderExpression(); } } } - this.state = 420; + this.state = 400; this._errHandler.sync(this); - _alt = this._interp.adaptivePredict(this._input, 37, this._ctx); + _alt = this._interp.adaptivePredict(this._input, 35, this._ctx); } } } @@ -2197,19 +2107,19 @@ export default class esql_parser extends Parser { // @RuleVersion(0) public orderExpression(): OrderExpressionContext { let localctx: OrderExpressionContext = new OrderExpressionContext(this, this._ctx, this.state); - this.enterRule(localctx, 64, esql_parser.RULE_orderExpression); + this.enterRule(localctx, 60, esql_parser.RULE_orderExpression); let _la: number; try { this.enterOuterAlt(localctx, 1); { - this.state = 421; + this.state = 401; this.booleanExpression(0); - this.state = 423; + this.state = 403; this._errHandler.sync(this); - switch ( this._interp.adaptivePredict(this._input, 38, this._ctx) ) { + switch ( this._interp.adaptivePredict(this._input, 36, this._ctx) ) { case 1: { - this.state = 422; + this.state = 402; localctx._ordering = this._input.LT(1); _la = this._input.LA(1); if(!(_la===32 || _la===36)) { @@ -2222,14 +2132,14 @@ export default class esql_parser extends Parser { } break; } - this.state = 427; + this.state = 407; this._errHandler.sync(this); - switch ( this._interp.adaptivePredict(this._input, 39, this._ctx) ) { + switch ( this._interp.adaptivePredict(this._input, 37, this._ctx) ) { case 1: { - this.state = 425; + this.state = 405; this.match(esql_parser.NULLS); - this.state = 426; + this.state = 406; localctx._nullOrdering = this._input.LT(1); _la = this._input.LA(1); if(!(_la===39 || _la===40)) { @@ -2261,32 +2171,32 @@ export default class esql_parser extends Parser { // @RuleVersion(0) public keepCommand(): KeepCommandContext { let localctx: KeepCommandContext = new KeepCommandContext(this, this._ctx, this.state); - this.enterRule(localctx, 66, esql_parser.RULE_keepCommand); + this.enterRule(localctx, 62, esql_parser.RULE_keepCommand); try { let _alt: number; this.enterOuterAlt(localctx, 1); { - this.state = 429; + this.state = 409; this.match(esql_parser.KEEP); - this.state = 430; + this.state = 410; this.qualifiedNamePattern(); - this.state = 435; + this.state = 415; this._errHandler.sync(this); - _alt = this._interp.adaptivePredict(this._input, 40, this._ctx); + _alt = this._interp.adaptivePredict(this._input, 38, this._ctx); while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { if (_alt === 1) { { { - this.state = 431; + this.state = 411; this.match(esql_parser.COMMA); - this.state = 432; + this.state = 412; this.qualifiedNamePattern(); } } } - this.state = 437; + this.state = 417; this._errHandler.sync(this); - _alt = this._interp.adaptivePredict(this._input, 40, this._ctx); + _alt = this._interp.adaptivePredict(this._input, 38, this._ctx); } } } @@ -2307,32 +2217,32 @@ export default class esql_parser extends Parser { // @RuleVersion(0) public dropCommand(): DropCommandContext { let localctx: DropCommandContext = new DropCommandContext(this, this._ctx, this.state); - this.enterRule(localctx, 68, esql_parser.RULE_dropCommand); + this.enterRule(localctx, 64, esql_parser.RULE_dropCommand); try { let _alt: number; this.enterOuterAlt(localctx, 1); { - this.state = 438; + this.state = 418; this.match(esql_parser.DROP); - this.state = 439; + this.state = 419; this.qualifiedNamePattern(); - this.state = 444; + this.state = 424; this._errHandler.sync(this); - _alt = this._interp.adaptivePredict(this._input, 41, this._ctx); + _alt = this._interp.adaptivePredict(this._input, 39, this._ctx); while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { if (_alt === 1) { { { - this.state = 440; + this.state = 420; this.match(esql_parser.COMMA); - this.state = 441; + this.state = 421; this.qualifiedNamePattern(); } } } - this.state = 446; + this.state = 426; this._errHandler.sync(this); - _alt = this._interp.adaptivePredict(this._input, 41, this._ctx); + _alt = this._interp.adaptivePredict(this._input, 39, this._ctx); } } } @@ -2353,32 +2263,32 @@ export default class esql_parser extends Parser { // @RuleVersion(0) public renameCommand(): RenameCommandContext { let localctx: RenameCommandContext = new RenameCommandContext(this, this._ctx, this.state); - this.enterRule(localctx, 70, esql_parser.RULE_renameCommand); + this.enterRule(localctx, 66, esql_parser.RULE_renameCommand); try { let _alt: number; this.enterOuterAlt(localctx, 1); { - this.state = 447; + this.state = 427; this.match(esql_parser.RENAME); - this.state = 448; + this.state = 428; this.renameClause(); - this.state = 453; + this.state = 433; this._errHandler.sync(this); - _alt = this._interp.adaptivePredict(this._input, 42, this._ctx); + _alt = this._interp.adaptivePredict(this._input, 40, this._ctx); while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { if (_alt === 1) { { { - this.state = 449; + this.state = 429; this.match(esql_parser.COMMA); - this.state = 450; + this.state = 430; this.renameClause(); } } } - this.state = 455; + this.state = 435; this._errHandler.sync(this); - _alt = this._interp.adaptivePredict(this._input, 42, this._ctx); + _alt = this._interp.adaptivePredict(this._input, 40, this._ctx); } } } @@ -2399,15 +2309,15 @@ export default class esql_parser extends Parser { // @RuleVersion(0) public renameClause(): RenameClauseContext { let localctx: RenameClauseContext = new RenameClauseContext(this, this._ctx, this.state); - this.enterRule(localctx, 72, esql_parser.RULE_renameClause); + this.enterRule(localctx, 68, esql_parser.RULE_renameClause); try { this.enterOuterAlt(localctx, 1); { - this.state = 456; + this.state = 436; localctx._oldName = this.qualifiedNamePattern(); - this.state = 457; + this.state = 437; this.match(esql_parser.AS); - this.state = 458; + this.state = 438; localctx._newName = this.qualifiedNamePattern(); } } @@ -2428,22 +2338,22 @@ export default class esql_parser extends Parser { // @RuleVersion(0) public dissectCommand(): DissectCommandContext { let localctx: DissectCommandContext = new DissectCommandContext(this, this._ctx, this.state); - this.enterRule(localctx, 74, esql_parser.RULE_dissectCommand); + this.enterRule(localctx, 70, esql_parser.RULE_dissectCommand); try { this.enterOuterAlt(localctx, 1); { - this.state = 460; + this.state = 440; this.match(esql_parser.DISSECT); - this.state = 461; + this.state = 441; this.primaryExpression(0); - this.state = 462; + this.state = 442; this.string_(); - this.state = 464; + this.state = 444; this._errHandler.sync(this); - switch ( this._interp.adaptivePredict(this._input, 43, this._ctx) ) { + switch ( this._interp.adaptivePredict(this._input, 41, this._ctx) ) { case 1: { - this.state = 463; + this.state = 443; this.commandOptions(); } break; @@ -2467,15 +2377,15 @@ export default class esql_parser extends Parser { // @RuleVersion(0) public grokCommand(): GrokCommandContext { let localctx: GrokCommandContext = new GrokCommandContext(this, this._ctx, this.state); - this.enterRule(localctx, 76, esql_parser.RULE_grokCommand); + this.enterRule(localctx, 72, esql_parser.RULE_grokCommand); try { this.enterOuterAlt(localctx, 1); { - this.state = 466; + this.state = 446; this.match(esql_parser.GROK); - this.state = 467; + this.state = 447; this.primaryExpression(0); - this.state = 468; + this.state = 448; this.string_(); } } @@ -2496,13 +2406,13 @@ export default class esql_parser extends Parser { // @RuleVersion(0) public mvExpandCommand(): MvExpandCommandContext { let localctx: MvExpandCommandContext = new MvExpandCommandContext(this, this._ctx, this.state); - this.enterRule(localctx, 78, esql_parser.RULE_mvExpandCommand); + this.enterRule(localctx, 74, esql_parser.RULE_mvExpandCommand); try { this.enterOuterAlt(localctx, 1); { - this.state = 470; + this.state = 450; this.match(esql_parser.MV_EXPAND); - this.state = 471; + this.state = 451; this.qualifiedName(); } } @@ -2523,30 +2433,30 @@ export default class esql_parser extends Parser { // @RuleVersion(0) public commandOptions(): CommandOptionsContext { let localctx: CommandOptionsContext = new CommandOptionsContext(this, this._ctx, this.state); - this.enterRule(localctx, 80, esql_parser.RULE_commandOptions); + this.enterRule(localctx, 76, esql_parser.RULE_commandOptions); try { let _alt: number; this.enterOuterAlt(localctx, 1); { - this.state = 473; + this.state = 453; this.commandOption(); - this.state = 478; + this.state = 458; this._errHandler.sync(this); - _alt = this._interp.adaptivePredict(this._input, 44, this._ctx); + _alt = this._interp.adaptivePredict(this._input, 42, this._ctx); while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { if (_alt === 1) { { { - this.state = 474; + this.state = 454; this.match(esql_parser.COMMA); - this.state = 475; + this.state = 455; this.commandOption(); } } } - this.state = 480; + this.state = 460; this._errHandler.sync(this); - _alt = this._interp.adaptivePredict(this._input, 44, this._ctx); + _alt = this._interp.adaptivePredict(this._input, 42, this._ctx); } } } @@ -2567,15 +2477,15 @@ export default class esql_parser extends Parser { // @RuleVersion(0) public commandOption(): CommandOptionContext { let localctx: CommandOptionContext = new CommandOptionContext(this, this._ctx, this.state); - this.enterRule(localctx, 82, esql_parser.RULE_commandOption); + this.enterRule(localctx, 78, esql_parser.RULE_commandOption); try { this.enterOuterAlt(localctx, 1); { - this.state = 481; + this.state = 461; this.identifier(); - this.state = 482; + this.state = 462; this.match(esql_parser.ASSIGN); - this.state = 483; + this.state = 463; this.constant(); } } @@ -2596,12 +2506,12 @@ export default class esql_parser extends Parser { // @RuleVersion(0) public booleanValue(): BooleanValueContext { let localctx: BooleanValueContext = new BooleanValueContext(this, this._ctx, this.state); - this.enterRule(localctx, 84, esql_parser.RULE_booleanValue); + this.enterRule(localctx, 80, esql_parser.RULE_booleanValue); let _la: number; try { this.enterOuterAlt(localctx, 1); { - this.state = 485; + this.state = 465; _la = this._input.LA(1); if(!(_la===38 || _la===52)) { this._errHandler.recoverInline(this); @@ -2629,22 +2539,22 @@ export default class esql_parser extends Parser { // @RuleVersion(0) public numericValue(): NumericValueContext { let localctx: NumericValueContext = new NumericValueContext(this, this._ctx, this.state); - this.enterRule(localctx, 86, esql_parser.RULE_numericValue); + this.enterRule(localctx, 82, esql_parser.RULE_numericValue); try { - this.state = 489; + this.state = 469; this._errHandler.sync(this); - switch ( this._interp.adaptivePredict(this._input, 45, this._ctx) ) { + switch ( this._interp.adaptivePredict(this._input, 43, this._ctx) ) { case 1: this.enterOuterAlt(localctx, 1); { - this.state = 487; + this.state = 467; this.decimalValue(); } break; case 2: this.enterOuterAlt(localctx, 2); { - this.state = 488; + this.state = 468; this.integerValue(); } break; @@ -2667,17 +2577,17 @@ export default class esql_parser extends Parser { // @RuleVersion(0) public decimalValue(): DecimalValueContext { let localctx: DecimalValueContext = new DecimalValueContext(this, this._ctx, this.state); - this.enterRule(localctx, 88, esql_parser.RULE_decimalValue); + this.enterRule(localctx, 84, esql_parser.RULE_decimalValue); let _la: number; try { this.enterOuterAlt(localctx, 1); { - this.state = 492; + this.state = 472; this._errHandler.sync(this); _la = this._input.LA(1); if (_la===60 || _la===61) { { - this.state = 491; + this.state = 471; _la = this._input.LA(1); if(!(_la===60 || _la===61)) { this._errHandler.recoverInline(this); @@ -2689,7 +2599,7 @@ export default class esql_parser extends Parser { } } - this.state = 494; + this.state = 474; this.match(esql_parser.DECIMAL_LITERAL); } } @@ -2710,17 +2620,17 @@ export default class esql_parser extends Parser { // @RuleVersion(0) public integerValue(): IntegerValueContext { let localctx: IntegerValueContext = new IntegerValueContext(this, this._ctx, this.state); - this.enterRule(localctx, 90, esql_parser.RULE_integerValue); + this.enterRule(localctx, 86, esql_parser.RULE_integerValue); let _la: number; try { this.enterOuterAlt(localctx, 1); { - this.state = 497; + this.state = 477; this._errHandler.sync(this); _la = this._input.LA(1); if (_la===60 || _la===61) { { - this.state = 496; + this.state = 476; _la = this._input.LA(1); if(!(_la===60 || _la===61)) { this._errHandler.recoverInline(this); @@ -2732,7 +2642,7 @@ export default class esql_parser extends Parser { } } - this.state = 499; + this.state = 479; this.match(esql_parser.INTEGER_LITERAL); } } @@ -2753,11 +2663,11 @@ export default class esql_parser extends Parser { // @RuleVersion(0) public string_(): StringContext { let localctx: StringContext = new StringContext(this, this._ctx, this.state); - this.enterRule(localctx, 92, esql_parser.RULE_string); + this.enterRule(localctx, 88, esql_parser.RULE_string); try { this.enterOuterAlt(localctx, 1); { - this.state = 501; + this.state = 481; this.match(esql_parser.QUOTED_STRING); } } @@ -2778,12 +2688,12 @@ export default class esql_parser extends Parser { // @RuleVersion(0) public comparisonOperator(): ComparisonOperatorContext { let localctx: ComparisonOperatorContext = new ComparisonOperatorContext(this, this._ctx, this.state); - this.enterRule(localctx, 94, esql_parser.RULE_comparisonOperator); + this.enterRule(localctx, 90, esql_parser.RULE_comparisonOperator); let _la: number; try { this.enterOuterAlt(localctx, 1); { - this.state = 503; + this.state = 483; _la = this._input.LA(1); if(!(((((_la - 53)) & ~0x1F) === 0 && ((1 << (_la - 53)) & 125) !== 0))) { this._errHandler.recoverInline(this); @@ -2811,13 +2721,13 @@ export default class esql_parser extends Parser { // @RuleVersion(0) public explainCommand(): ExplainCommandContext { let localctx: ExplainCommandContext = new ExplainCommandContext(this, this._ctx, this.state); - this.enterRule(localctx, 96, esql_parser.RULE_explainCommand); + this.enterRule(localctx, 92, esql_parser.RULE_explainCommand); try { this.enterOuterAlt(localctx, 1); { - this.state = 505; + this.state = 485; this.match(esql_parser.EXPLAIN); - this.state = 506; + this.state = 486; this.subqueryExpression(); } } @@ -2838,15 +2748,15 @@ export default class esql_parser extends Parser { // @RuleVersion(0) public subqueryExpression(): SubqueryExpressionContext { let localctx: SubqueryExpressionContext = new SubqueryExpressionContext(this, this._ctx, this.state); - this.enterRule(localctx, 98, esql_parser.RULE_subqueryExpression); + this.enterRule(localctx, 94, esql_parser.RULE_subqueryExpression); try { this.enterOuterAlt(localctx, 1); { - this.state = 508; + this.state = 488; this.match(esql_parser.OPENING_BRACKET); - this.state = 509; + this.state = 489; this.query(0); - this.state = 510; + this.state = 490; this.match(esql_parser.CLOSING_BRACKET); } } @@ -2867,14 +2777,14 @@ export default class esql_parser extends Parser { // @RuleVersion(0) public showCommand(): ShowCommandContext { let localctx: ShowCommandContext = new ShowCommandContext(this, this._ctx, this.state); - this.enterRule(localctx, 100, esql_parser.RULE_showCommand); + this.enterRule(localctx, 96, esql_parser.RULE_showCommand); try { localctx = new ShowInfoContext(this, localctx); this.enterOuterAlt(localctx, 1); { - this.state = 512; + this.state = 492; this.match(esql_parser.SHOW); - this.state = 513; + this.state = 493; this.match(esql_parser.INFO); } } @@ -2895,14 +2805,14 @@ export default class esql_parser extends Parser { // @RuleVersion(0) public metaCommand(): MetaCommandContext { let localctx: MetaCommandContext = new MetaCommandContext(this, this._ctx, this.state); - this.enterRule(localctx, 102, esql_parser.RULE_metaCommand); + this.enterRule(localctx, 98, esql_parser.RULE_metaCommand); try { localctx = new MetaFunctionsContext(this, localctx); this.enterOuterAlt(localctx, 1); { - this.state = 515; + this.state = 495; this.match(esql_parser.META); - this.state = 516; + this.state = 496; this.match(esql_parser.FUNCTIONS); } } @@ -2923,53 +2833,53 @@ export default class esql_parser extends Parser { // @RuleVersion(0) public enrichCommand(): EnrichCommandContext { let localctx: EnrichCommandContext = new EnrichCommandContext(this, this._ctx, this.state); - this.enterRule(localctx, 104, esql_parser.RULE_enrichCommand); + this.enterRule(localctx, 100, esql_parser.RULE_enrichCommand); try { let _alt: number; this.enterOuterAlt(localctx, 1); { - this.state = 518; + this.state = 498; this.match(esql_parser.ENRICH); - this.state = 519; + this.state = 499; localctx._policyName = this.match(esql_parser.ENRICH_POLICY_NAME); - this.state = 522; + this.state = 502; this._errHandler.sync(this); - switch ( this._interp.adaptivePredict(this._input, 48, this._ctx) ) { + switch ( this._interp.adaptivePredict(this._input, 46, this._ctx) ) { case 1: { - this.state = 520; + this.state = 500; this.match(esql_parser.ON); - this.state = 521; + this.state = 501; localctx._matchField = this.qualifiedNamePattern(); } break; } - this.state = 533; + this.state = 513; this._errHandler.sync(this); - switch ( this._interp.adaptivePredict(this._input, 50, this._ctx) ) { + switch ( this._interp.adaptivePredict(this._input, 48, this._ctx) ) { case 1: { - this.state = 524; + this.state = 504; this.match(esql_parser.WITH); - this.state = 525; + this.state = 505; this.enrichWithClause(); - this.state = 530; + this.state = 510; this._errHandler.sync(this); - _alt = this._interp.adaptivePredict(this._input, 49, this._ctx); + _alt = this._interp.adaptivePredict(this._input, 47, this._ctx); while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { if (_alt === 1) { { { - this.state = 526; + this.state = 506; this.match(esql_parser.COMMA); - this.state = 527; + this.state = 507; this.enrichWithClause(); } } } - this.state = 532; + this.state = 512; this._errHandler.sync(this); - _alt = this._interp.adaptivePredict(this._input, 49, this._ctx); + _alt = this._interp.adaptivePredict(this._input, 47, this._ctx); } } break; @@ -2993,23 +2903,23 @@ export default class esql_parser extends Parser { // @RuleVersion(0) public enrichWithClause(): EnrichWithClauseContext { let localctx: EnrichWithClauseContext = new EnrichWithClauseContext(this, this._ctx, this.state); - this.enterRule(localctx, 106, esql_parser.RULE_enrichWithClause); + this.enterRule(localctx, 102, esql_parser.RULE_enrichWithClause); try { this.enterOuterAlt(localctx, 1); { - this.state = 538; + this.state = 518; this._errHandler.sync(this); - switch ( this._interp.adaptivePredict(this._input, 51, this._ctx) ) { + switch ( this._interp.adaptivePredict(this._input, 49, this._ctx) ) { case 1: { - this.state = 535; + this.state = 515; localctx._newName = this.qualifiedNamePattern(); - this.state = 536; + this.state = 516; this.match(esql_parser.ASSIGN); } break; } - this.state = 540; + this.state = 520; localctx._enrichField = this.qualifiedNamePattern(); } } @@ -3074,183 +2984,176 @@ export default class esql_parser extends Parser { return true; } - public static readonly _serializedATN: number[] = [4,1,110,543,2,0,7,0, + public static readonly _serializedATN: number[] = [4,1,109,523,2,0,7,0, 2,1,7,1,2,2,7,2,2,3,7,3,2,4,7,4,2,5,7,5,2,6,7,6,2,7,7,7,2,8,7,8,2,9,7,9, 2,10,7,10,2,11,7,11,2,12,7,12,2,13,7,13,2,14,7,14,2,15,7,15,2,16,7,16,2, 17,7,17,2,18,7,18,2,19,7,19,2,20,7,20,2,21,7,21,2,22,7,22,2,23,7,23,2,24, 7,24,2,25,7,25,2,26,7,26,2,27,7,27,2,28,7,28,2,29,7,29,2,30,7,30,2,31,7, 31,2,32,7,32,2,33,7,33,2,34,7,34,2,35,7,35,2,36,7,36,2,37,7,37,2,38,7,38, 2,39,7,39,2,40,7,40,2,41,7,41,2,42,7,42,2,43,7,43,2,44,7,44,2,45,7,45,2, - 46,7,46,2,47,7,47,2,48,7,48,2,49,7,49,2,50,7,50,2,51,7,51,2,52,7,52,2,53, - 7,53,1,0,1,0,1,0,1,1,1,1,1,1,1,1,1,1,1,1,5,1,118,8,1,10,1,12,1,121,9,1, - 1,2,1,2,1,2,1,2,1,2,3,2,128,8,2,1,3,1,3,1,3,1,3,1,3,1,3,1,3,1,3,1,3,1,3, - 1,3,1,3,1,3,3,3,143,8,3,1,4,1,4,1,4,1,5,1,5,1,5,1,5,1,5,1,5,1,5,3,5,155, - 8,5,1,5,1,5,1,5,1,5,1,5,5,5,162,8,5,10,5,12,5,165,9,5,1,5,1,5,1,5,1,5,1, - 5,3,5,172,8,5,1,5,1,5,3,5,176,8,5,1,5,1,5,1,5,1,5,1,5,1,5,5,5,184,8,5,10, - 5,12,5,187,9,5,1,6,1,6,3,6,191,8,6,1,6,1,6,1,6,1,6,1,6,3,6,198,8,6,1,6, - 1,6,1,6,3,6,203,8,6,1,7,1,7,1,7,1,7,1,7,3,7,210,8,7,1,8,1,8,1,8,1,8,3,8, - 216,8,8,1,8,1,8,1,8,1,8,1,8,1,8,5,8,224,8,8,10,8,12,8,227,9,8,1,9,1,9,1, - 9,1,9,1,9,1,9,1,9,1,9,3,9,237,8,9,1,9,1,9,1,9,5,9,242,8,9,10,9,12,9,245, - 9,9,1,10,1,10,1,10,1,10,1,10,1,10,5,10,253,8,10,10,10,12,10,256,9,10,3, - 10,258,8,10,1,10,1,10,1,11,1,11,1,12,1,12,1,12,1,13,1,13,1,13,5,13,270, - 8,13,10,13,12,13,273,9,13,1,14,1,14,1,14,1,14,1,14,3,14,280,8,14,1,15,1, - 15,1,15,1,15,5,15,286,8,15,10,15,12,15,289,9,15,1,15,3,15,292,8,15,1,15, - 3,15,295,8,15,1,16,1,16,1,17,1,17,1,17,1,17,5,17,303,8,17,10,17,12,17,306, - 9,17,1,18,1,18,1,18,1,18,1,19,1,19,3,19,314,8,19,1,20,1,20,1,20,1,20,5, - 20,320,8,20,10,20,12,20,323,9,20,1,21,1,21,1,21,1,21,1,22,1,22,1,22,1,23, - 1,23,3,23,334,8,23,1,23,1,23,3,23,338,8,23,1,24,1,24,1,24,1,24,3,24,344, - 8,24,1,25,1,25,1,25,5,25,349,8,25,10,25,12,25,352,9,25,1,26,1,26,1,26,5, - 26,357,8,26,10,26,12,26,360,9,26,1,27,1,27,1,28,1,28,1,29,1,29,1,29,1,29, - 1,29,1,29,1,29,1,29,1,29,1,29,1,29,1,29,1,29,5,29,379,8,29,10,29,12,29, - 382,9,29,1,29,1,29,1,29,1,29,1,29,1,29,5,29,390,8,29,10,29,12,29,393,9, - 29,1,29,1,29,1,29,1,29,1,29,1,29,5,29,401,8,29,10,29,12,29,404,9,29,1,29, - 1,29,3,29,408,8,29,1,30,1,30,1,30,1,31,1,31,1,31,1,31,5,31,417,8,31,10, - 31,12,31,420,9,31,1,32,1,32,3,32,424,8,32,1,32,1,32,3,32,428,8,32,1,33, - 1,33,1,33,1,33,5,33,434,8,33,10,33,12,33,437,9,33,1,34,1,34,1,34,1,34,5, - 34,443,8,34,10,34,12,34,446,9,34,1,35,1,35,1,35,1,35,5,35,452,8,35,10,35, - 12,35,455,9,35,1,36,1,36,1,36,1,36,1,37,1,37,1,37,1,37,3,37,465,8,37,1, - 38,1,38,1,38,1,38,1,39,1,39,1,39,1,40,1,40,1,40,5,40,477,8,40,10,40,12, - 40,480,9,40,1,41,1,41,1,41,1,41,1,42,1,42,1,43,1,43,3,43,490,8,43,1,44, - 3,44,493,8,44,1,44,1,44,1,45,3,45,498,8,45,1,45,1,45,1,46,1,46,1,47,1,47, - 1,48,1,48,1,48,1,49,1,49,1,49,1,49,1,50,1,50,1,50,1,51,1,51,1,51,1,52,1, - 52,1,52,1,52,3,52,523,8,52,1,52,1,52,1,52,1,52,5,52,529,8,52,10,52,12,52, - 532,9,52,3,52,534,8,52,1,53,1,53,1,53,3,53,539,8,53,1,53,1,53,1,53,0,4, - 2,10,16,18,54,0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40, - 42,44,46,48,50,52,54,56,58,60,62,64,66,68,70,72,74,76,78,80,82,84,86,88, - 90,92,94,96,98,100,102,104,106,0,7,1,0,60,61,1,0,62,64,1,0,67,68,2,0,32, - 32,36,36,1,0,39,40,2,0,38,38,52,52,2,0,53,53,55,59,568,0,108,1,0,0,0,2, - 111,1,0,0,0,4,127,1,0,0,0,6,142,1,0,0,0,8,144,1,0,0,0,10,175,1,0,0,0,12, - 202,1,0,0,0,14,209,1,0,0,0,16,215,1,0,0,0,18,236,1,0,0,0,20,246,1,0,0,0, - 22,261,1,0,0,0,24,263,1,0,0,0,26,266,1,0,0,0,28,279,1,0,0,0,30,281,1,0, - 0,0,32,296,1,0,0,0,34,298,1,0,0,0,36,307,1,0,0,0,38,313,1,0,0,0,40,315, - 1,0,0,0,42,324,1,0,0,0,44,328,1,0,0,0,46,331,1,0,0,0,48,339,1,0,0,0,50, - 345,1,0,0,0,52,353,1,0,0,0,54,361,1,0,0,0,56,363,1,0,0,0,58,407,1,0,0,0, - 60,409,1,0,0,0,62,412,1,0,0,0,64,421,1,0,0,0,66,429,1,0,0,0,68,438,1,0, - 0,0,70,447,1,0,0,0,72,456,1,0,0,0,74,460,1,0,0,0,76,466,1,0,0,0,78,470, - 1,0,0,0,80,473,1,0,0,0,82,481,1,0,0,0,84,485,1,0,0,0,86,489,1,0,0,0,88, - 492,1,0,0,0,90,497,1,0,0,0,92,501,1,0,0,0,94,503,1,0,0,0,96,505,1,0,0,0, - 98,508,1,0,0,0,100,512,1,0,0,0,102,515,1,0,0,0,104,518,1,0,0,0,106,538, - 1,0,0,0,108,109,3,2,1,0,109,110,5,0,0,1,110,1,1,0,0,0,111,112,6,1,-1,0, - 112,113,3,4,2,0,113,119,1,0,0,0,114,115,10,1,0,0,115,116,5,26,0,0,116,118, - 3,6,3,0,117,114,1,0,0,0,118,121,1,0,0,0,119,117,1,0,0,0,119,120,1,0,0,0, - 120,3,1,0,0,0,121,119,1,0,0,0,122,128,3,96,48,0,123,128,3,30,15,0,124,128, - 3,24,12,0,125,128,3,100,50,0,126,128,3,102,51,0,127,122,1,0,0,0,127,123, - 1,0,0,0,127,124,1,0,0,0,127,125,1,0,0,0,127,126,1,0,0,0,128,5,1,0,0,0,129, - 143,3,44,22,0,130,143,3,48,24,0,131,143,3,60,30,0,132,143,3,66,33,0,133, - 143,3,62,31,0,134,143,3,46,23,0,135,143,3,8,4,0,136,143,3,68,34,0,137,143, - 3,70,35,0,138,143,3,74,37,0,139,143,3,76,38,0,140,143,3,104,52,0,141,143, - 3,78,39,0,142,129,1,0,0,0,142,130,1,0,0,0,142,131,1,0,0,0,142,132,1,0,0, - 0,142,133,1,0,0,0,142,134,1,0,0,0,142,135,1,0,0,0,142,136,1,0,0,0,142,137, - 1,0,0,0,142,138,1,0,0,0,142,139,1,0,0,0,142,140,1,0,0,0,142,141,1,0,0,0, - 143,7,1,0,0,0,144,145,5,18,0,0,145,146,3,10,5,0,146,9,1,0,0,0,147,148,6, - 5,-1,0,148,149,5,45,0,0,149,176,3,10,5,7,150,176,3,14,7,0,151,176,3,12, - 6,0,152,154,3,14,7,0,153,155,5,45,0,0,154,153,1,0,0,0,154,155,1,0,0,0,155, - 156,1,0,0,0,156,157,5,42,0,0,157,158,5,41,0,0,158,163,3,14,7,0,159,160, - 5,35,0,0,160,162,3,14,7,0,161,159,1,0,0,0,162,165,1,0,0,0,163,161,1,0,0, - 0,163,164,1,0,0,0,164,166,1,0,0,0,165,163,1,0,0,0,166,167,5,51,0,0,167, - 176,1,0,0,0,168,169,3,14,7,0,169,171,5,43,0,0,170,172,5,45,0,0,171,170, - 1,0,0,0,171,172,1,0,0,0,172,173,1,0,0,0,173,174,5,46,0,0,174,176,1,0,0, - 0,175,147,1,0,0,0,175,150,1,0,0,0,175,151,1,0,0,0,175,152,1,0,0,0,175,168, - 1,0,0,0,176,185,1,0,0,0,177,178,10,4,0,0,178,179,5,31,0,0,179,184,3,10, - 5,5,180,181,10,3,0,0,181,182,5,48,0,0,182,184,3,10,5,4,183,177,1,0,0,0, - 183,180,1,0,0,0,184,187,1,0,0,0,185,183,1,0,0,0,185,186,1,0,0,0,186,11, - 1,0,0,0,187,185,1,0,0,0,188,190,3,14,7,0,189,191,5,45,0,0,190,189,1,0,0, - 0,190,191,1,0,0,0,191,192,1,0,0,0,192,193,5,44,0,0,193,194,3,92,46,0,194, - 203,1,0,0,0,195,197,3,14,7,0,196,198,5,45,0,0,197,196,1,0,0,0,197,198,1, - 0,0,0,198,199,1,0,0,0,199,200,5,50,0,0,200,201,3,92,46,0,201,203,1,0,0, - 0,202,188,1,0,0,0,202,195,1,0,0,0,203,13,1,0,0,0,204,210,3,16,8,0,205,206, - 3,16,8,0,206,207,3,94,47,0,207,208,3,16,8,0,208,210,1,0,0,0,209,204,1,0, - 0,0,209,205,1,0,0,0,210,15,1,0,0,0,211,212,6,8,-1,0,212,216,3,18,9,0,213, - 214,7,0,0,0,214,216,3,16,8,3,215,211,1,0,0,0,215,213,1,0,0,0,216,225,1, - 0,0,0,217,218,10,2,0,0,218,219,7,1,0,0,219,224,3,16,8,3,220,221,10,1,0, - 0,221,222,7,0,0,0,222,224,3,16,8,2,223,217,1,0,0,0,223,220,1,0,0,0,224, - 227,1,0,0,0,225,223,1,0,0,0,225,226,1,0,0,0,226,17,1,0,0,0,227,225,1,0, - 0,0,228,229,6,9,-1,0,229,237,3,58,29,0,230,237,3,50,25,0,231,237,3,20,10, - 0,232,233,5,41,0,0,233,234,3,10,5,0,234,235,5,51,0,0,235,237,1,0,0,0,236, - 228,1,0,0,0,236,230,1,0,0,0,236,231,1,0,0,0,236,232,1,0,0,0,237,243,1,0, - 0,0,238,239,10,1,0,0,239,240,5,34,0,0,240,242,3,22,11,0,241,238,1,0,0,0, - 242,245,1,0,0,0,243,241,1,0,0,0,243,244,1,0,0,0,244,19,1,0,0,0,245,243, - 1,0,0,0,246,247,3,54,27,0,247,257,5,41,0,0,248,258,5,62,0,0,249,254,3,10, - 5,0,250,251,5,35,0,0,251,253,3,10,5,0,252,250,1,0,0,0,253,256,1,0,0,0,254, - 252,1,0,0,0,254,255,1,0,0,0,255,258,1,0,0,0,256,254,1,0,0,0,257,248,1,0, - 0,0,257,249,1,0,0,0,257,258,1,0,0,0,258,259,1,0,0,0,259,260,5,51,0,0,260, - 21,1,0,0,0,261,262,3,54,27,0,262,23,1,0,0,0,263,264,5,14,0,0,264,265,3, - 26,13,0,265,25,1,0,0,0,266,271,3,28,14,0,267,268,5,35,0,0,268,270,3,28, - 14,0,269,267,1,0,0,0,270,273,1,0,0,0,271,269,1,0,0,0,271,272,1,0,0,0,272, - 27,1,0,0,0,273,271,1,0,0,0,274,280,3,10,5,0,275,276,3,50,25,0,276,277,5, - 33,0,0,277,278,3,10,5,0,278,280,1,0,0,0,279,274,1,0,0,0,279,275,1,0,0,0, - 280,29,1,0,0,0,281,282,5,6,0,0,282,287,3,32,16,0,283,284,5,35,0,0,284,286, - 3,32,16,0,285,283,1,0,0,0,286,289,1,0,0,0,287,285,1,0,0,0,287,288,1,0,0, - 0,288,291,1,0,0,0,289,287,1,0,0,0,290,292,3,38,19,0,291,290,1,0,0,0,291, - 292,1,0,0,0,292,294,1,0,0,0,293,295,3,34,17,0,294,293,1,0,0,0,294,295,1, - 0,0,0,295,31,1,0,0,0,296,297,5,74,0,0,297,33,1,0,0,0,298,299,5,72,0,0,299, - 304,3,36,18,0,300,301,5,35,0,0,301,303,3,36,18,0,302,300,1,0,0,0,303,306, - 1,0,0,0,304,302,1,0,0,0,304,305,1,0,0,0,305,35,1,0,0,0,306,304,1,0,0,0, - 307,308,3,92,46,0,308,309,5,33,0,0,309,310,3,92,46,0,310,37,1,0,0,0,311, - 314,3,40,20,0,312,314,3,42,21,0,313,311,1,0,0,0,313,312,1,0,0,0,314,39, - 1,0,0,0,315,316,5,73,0,0,316,321,3,32,16,0,317,318,5,35,0,0,318,320,3,32, - 16,0,319,317,1,0,0,0,320,323,1,0,0,0,321,319,1,0,0,0,321,322,1,0,0,0,322, - 41,1,0,0,0,323,321,1,0,0,0,324,325,5,65,0,0,325,326,3,40,20,0,326,327,5, - 66,0,0,327,43,1,0,0,0,328,329,5,4,0,0,329,330,3,26,13,0,330,45,1,0,0,0, - 331,333,5,17,0,0,332,334,3,26,13,0,333,332,1,0,0,0,333,334,1,0,0,0,334, - 337,1,0,0,0,335,336,5,30,0,0,336,338,3,26,13,0,337,335,1,0,0,0,337,338, - 1,0,0,0,338,47,1,0,0,0,339,340,5,8,0,0,340,343,3,26,13,0,341,342,5,30,0, - 0,342,344,3,26,13,0,343,341,1,0,0,0,343,344,1,0,0,0,344,49,1,0,0,0,345, - 350,3,54,27,0,346,347,5,37,0,0,347,349,3,54,27,0,348,346,1,0,0,0,349,352, - 1,0,0,0,350,348,1,0,0,0,350,351,1,0,0,0,351,51,1,0,0,0,352,350,1,0,0,0, - 353,358,3,56,28,0,354,355,5,37,0,0,355,357,3,56,28,0,356,354,1,0,0,0,357, - 360,1,0,0,0,358,356,1,0,0,0,358,359,1,0,0,0,359,53,1,0,0,0,360,358,1,0, - 0,0,361,362,7,2,0,0,362,55,1,0,0,0,363,364,5,78,0,0,364,57,1,0,0,0,365, - 408,5,46,0,0,366,367,3,90,45,0,367,368,5,67,0,0,368,408,1,0,0,0,369,408, - 3,88,44,0,370,408,3,90,45,0,371,408,3,84,42,0,372,408,5,49,0,0,373,408, - 3,92,46,0,374,375,5,65,0,0,375,380,3,86,43,0,376,377,5,35,0,0,377,379,3, - 86,43,0,378,376,1,0,0,0,379,382,1,0,0,0,380,378,1,0,0,0,380,381,1,0,0,0, - 381,383,1,0,0,0,382,380,1,0,0,0,383,384,5,66,0,0,384,408,1,0,0,0,385,386, - 5,65,0,0,386,391,3,84,42,0,387,388,5,35,0,0,388,390,3,84,42,0,389,387,1, - 0,0,0,390,393,1,0,0,0,391,389,1,0,0,0,391,392,1,0,0,0,392,394,1,0,0,0,393, - 391,1,0,0,0,394,395,5,66,0,0,395,408,1,0,0,0,396,397,5,65,0,0,397,402,3, - 92,46,0,398,399,5,35,0,0,399,401,3,92,46,0,400,398,1,0,0,0,401,404,1,0, - 0,0,402,400,1,0,0,0,402,403,1,0,0,0,403,405,1,0,0,0,404,402,1,0,0,0,405, - 406,5,66,0,0,406,408,1,0,0,0,407,365,1,0,0,0,407,366,1,0,0,0,407,369,1, - 0,0,0,407,370,1,0,0,0,407,371,1,0,0,0,407,372,1,0,0,0,407,373,1,0,0,0,407, - 374,1,0,0,0,407,385,1,0,0,0,407,396,1,0,0,0,408,59,1,0,0,0,409,410,5,10, - 0,0,410,411,5,28,0,0,411,61,1,0,0,0,412,413,5,16,0,0,413,418,3,64,32,0, - 414,415,5,35,0,0,415,417,3,64,32,0,416,414,1,0,0,0,417,420,1,0,0,0,418, - 416,1,0,0,0,418,419,1,0,0,0,419,63,1,0,0,0,420,418,1,0,0,0,421,423,3,10, - 5,0,422,424,7,3,0,0,423,422,1,0,0,0,423,424,1,0,0,0,424,427,1,0,0,0,425, - 426,5,47,0,0,426,428,7,4,0,0,427,425,1,0,0,0,427,428,1,0,0,0,428,65,1,0, - 0,0,429,430,5,9,0,0,430,435,3,52,26,0,431,432,5,35,0,0,432,434,3,52,26, - 0,433,431,1,0,0,0,434,437,1,0,0,0,435,433,1,0,0,0,435,436,1,0,0,0,436,67, - 1,0,0,0,437,435,1,0,0,0,438,439,5,2,0,0,439,444,3,52,26,0,440,441,5,35, - 0,0,441,443,3,52,26,0,442,440,1,0,0,0,443,446,1,0,0,0,444,442,1,0,0,0,444, - 445,1,0,0,0,445,69,1,0,0,0,446,444,1,0,0,0,447,448,5,13,0,0,448,453,3,72, - 36,0,449,450,5,35,0,0,450,452,3,72,36,0,451,449,1,0,0,0,452,455,1,0,0,0, - 453,451,1,0,0,0,453,454,1,0,0,0,454,71,1,0,0,0,455,453,1,0,0,0,456,457, - 3,52,26,0,457,458,5,82,0,0,458,459,3,52,26,0,459,73,1,0,0,0,460,461,5,1, - 0,0,461,462,3,18,9,0,462,464,3,92,46,0,463,465,3,80,40,0,464,463,1,0,0, - 0,464,465,1,0,0,0,465,75,1,0,0,0,466,467,5,7,0,0,467,468,3,18,9,0,468,469, - 3,92,46,0,469,77,1,0,0,0,470,471,5,12,0,0,471,472,3,50,25,0,472,79,1,0, - 0,0,473,478,3,82,41,0,474,475,5,35,0,0,475,477,3,82,41,0,476,474,1,0,0, - 0,477,480,1,0,0,0,478,476,1,0,0,0,478,479,1,0,0,0,479,81,1,0,0,0,480,478, - 1,0,0,0,481,482,3,54,27,0,482,483,5,33,0,0,483,484,3,58,29,0,484,83,1,0, - 0,0,485,486,7,5,0,0,486,85,1,0,0,0,487,490,3,88,44,0,488,490,3,90,45,0, - 489,487,1,0,0,0,489,488,1,0,0,0,490,87,1,0,0,0,491,493,7,0,0,0,492,491, - 1,0,0,0,492,493,1,0,0,0,493,494,1,0,0,0,494,495,5,29,0,0,495,89,1,0,0,0, - 496,498,7,0,0,0,497,496,1,0,0,0,497,498,1,0,0,0,498,499,1,0,0,0,499,500, - 5,28,0,0,500,91,1,0,0,0,501,502,5,27,0,0,502,93,1,0,0,0,503,504,7,6,0,0, - 504,95,1,0,0,0,505,506,5,5,0,0,506,507,3,98,49,0,507,97,1,0,0,0,508,509, - 5,65,0,0,509,510,3,2,1,0,510,511,5,66,0,0,511,99,1,0,0,0,512,513,5,15,0, - 0,513,514,5,98,0,0,514,101,1,0,0,0,515,516,5,11,0,0,516,517,5,102,0,0,517, - 103,1,0,0,0,518,519,5,3,0,0,519,522,5,88,0,0,520,521,5,86,0,0,521,523,3, - 52,26,0,522,520,1,0,0,0,522,523,1,0,0,0,523,533,1,0,0,0,524,525,5,87,0, - 0,525,530,3,106,53,0,526,527,5,35,0,0,527,529,3,106,53,0,528,526,1,0,0, - 0,529,532,1,0,0,0,530,528,1,0,0,0,530,531,1,0,0,0,531,534,1,0,0,0,532,530, - 1,0,0,0,533,524,1,0,0,0,533,534,1,0,0,0,534,105,1,0,0,0,535,536,3,52,26, - 0,536,537,5,33,0,0,537,539,1,0,0,0,538,535,1,0,0,0,538,539,1,0,0,0,539, - 540,1,0,0,0,540,541,3,52,26,0,541,107,1,0,0,0,52,119,127,142,154,163,171, - 175,183,185,190,197,202,209,215,223,225,236,243,254,257,271,279,287,291, - 294,304,313,321,333,337,343,350,358,380,391,402,407,418,423,427,435,444, - 453,464,478,489,492,497,522,530,533,538]; + 46,7,46,2,47,7,47,2,48,7,48,2,49,7,49,2,50,7,50,2,51,7,51,1,0,1,0,1,0,1, + 1,1,1,1,1,1,1,1,1,1,1,5,1,114,8,1,10,1,12,1,117,9,1,1,2,1,2,1,2,1,2,1,2, + 3,2,124,8,2,1,3,1,3,1,3,1,3,1,3,1,3,1,3,1,3,1,3,1,3,1,3,1,3,1,3,3,3,139, + 8,3,1,4,1,4,1,4,1,5,1,5,1,5,1,5,1,5,1,5,1,5,3,5,151,8,5,1,5,1,5,1,5,1,5, + 1,5,5,5,158,8,5,10,5,12,5,161,9,5,1,5,1,5,1,5,1,5,1,5,3,5,168,8,5,1,5,1, + 5,3,5,172,8,5,1,5,1,5,1,5,1,5,1,5,1,5,5,5,180,8,5,10,5,12,5,183,9,5,1,6, + 1,6,3,6,187,8,6,1,6,1,6,1,6,1,6,1,6,3,6,194,8,6,1,6,1,6,1,6,3,6,199,8,6, + 1,7,1,7,1,7,1,7,1,7,3,7,206,8,7,1,8,1,8,1,8,1,8,3,8,212,8,8,1,8,1,8,1,8, + 1,8,1,8,1,8,5,8,220,8,8,10,8,12,8,223,9,8,1,9,1,9,1,9,1,9,1,9,1,9,1,9,1, + 9,3,9,233,8,9,1,9,1,9,1,9,5,9,238,8,9,10,9,12,9,241,9,9,1,10,1,10,1,10, + 1,10,1,10,1,10,5,10,249,8,10,10,10,12,10,252,9,10,3,10,254,8,10,1,10,1, + 10,1,11,1,11,1,12,1,12,1,12,1,13,1,13,1,13,5,13,266,8,13,10,13,12,13,269, + 9,13,1,14,1,14,1,14,1,14,1,14,3,14,276,8,14,1,15,1,15,1,15,1,15,5,15,282, + 8,15,10,15,12,15,285,9,15,1,15,3,15,288,8,15,1,16,1,16,1,17,1,17,3,17,294, + 8,17,1,18,1,18,1,18,1,18,5,18,300,8,18,10,18,12,18,303,9,18,1,19,1,19,1, + 19,1,19,1,20,1,20,1,20,1,21,1,21,3,21,314,8,21,1,21,1,21,3,21,318,8,21, + 1,22,1,22,1,22,1,22,3,22,324,8,22,1,23,1,23,1,23,5,23,329,8,23,10,23,12, + 23,332,9,23,1,24,1,24,1,24,5,24,337,8,24,10,24,12,24,340,9,24,1,25,1,25, + 1,26,1,26,1,27,1,27,1,27,1,27,1,27,1,27,1,27,1,27,1,27,1,27,1,27,1,27,1, + 27,5,27,359,8,27,10,27,12,27,362,9,27,1,27,1,27,1,27,1,27,1,27,1,27,5,27, + 370,8,27,10,27,12,27,373,9,27,1,27,1,27,1,27,1,27,1,27,1,27,5,27,381,8, + 27,10,27,12,27,384,9,27,1,27,1,27,3,27,388,8,27,1,28,1,28,1,28,1,29,1,29, + 1,29,1,29,5,29,397,8,29,10,29,12,29,400,9,29,1,30,1,30,3,30,404,8,30,1, + 30,1,30,3,30,408,8,30,1,31,1,31,1,31,1,31,5,31,414,8,31,10,31,12,31,417, + 9,31,1,32,1,32,1,32,1,32,5,32,423,8,32,10,32,12,32,426,9,32,1,33,1,33,1, + 33,1,33,5,33,432,8,33,10,33,12,33,435,9,33,1,34,1,34,1,34,1,34,1,35,1,35, + 1,35,1,35,3,35,445,8,35,1,36,1,36,1,36,1,36,1,37,1,37,1,37,1,38,1,38,1, + 38,5,38,457,8,38,10,38,12,38,460,9,38,1,39,1,39,1,39,1,39,1,40,1,40,1,41, + 1,41,3,41,470,8,41,1,42,3,42,473,8,42,1,42,1,42,1,43,3,43,478,8,43,1,43, + 1,43,1,44,1,44,1,45,1,45,1,46,1,46,1,46,1,47,1,47,1,47,1,47,1,48,1,48,1, + 48,1,49,1,49,1,49,1,50,1,50,1,50,1,50,3,50,503,8,50,1,50,1,50,1,50,1,50, + 5,50,509,8,50,10,50,12,50,512,9,50,3,50,514,8,50,1,51,1,51,1,51,3,51,519, + 8,51,1,51,1,51,1,51,0,4,2,10,16,18,52,0,2,4,6,8,10,12,14,16,18,20,22,24, + 26,28,30,32,34,36,38,40,42,44,46,48,50,52,54,56,58,60,62,64,66,68,70,72, + 74,76,78,80,82,84,86,88,90,92,94,96,98,100,102,0,7,1,0,60,61,1,0,62,64, + 1,0,67,68,2,0,32,32,36,36,1,0,39,40,2,0,38,38,52,52,2,0,53,53,55,59,548, + 0,104,1,0,0,0,2,107,1,0,0,0,4,123,1,0,0,0,6,138,1,0,0,0,8,140,1,0,0,0,10, + 171,1,0,0,0,12,198,1,0,0,0,14,205,1,0,0,0,16,211,1,0,0,0,18,232,1,0,0,0, + 20,242,1,0,0,0,22,257,1,0,0,0,24,259,1,0,0,0,26,262,1,0,0,0,28,275,1,0, + 0,0,30,277,1,0,0,0,32,289,1,0,0,0,34,293,1,0,0,0,36,295,1,0,0,0,38,304, + 1,0,0,0,40,308,1,0,0,0,42,311,1,0,0,0,44,319,1,0,0,0,46,325,1,0,0,0,48, + 333,1,0,0,0,50,341,1,0,0,0,52,343,1,0,0,0,54,387,1,0,0,0,56,389,1,0,0,0, + 58,392,1,0,0,0,60,401,1,0,0,0,62,409,1,0,0,0,64,418,1,0,0,0,66,427,1,0, + 0,0,68,436,1,0,0,0,70,440,1,0,0,0,72,446,1,0,0,0,74,450,1,0,0,0,76,453, + 1,0,0,0,78,461,1,0,0,0,80,465,1,0,0,0,82,469,1,0,0,0,84,472,1,0,0,0,86, + 477,1,0,0,0,88,481,1,0,0,0,90,483,1,0,0,0,92,485,1,0,0,0,94,488,1,0,0,0, + 96,492,1,0,0,0,98,495,1,0,0,0,100,498,1,0,0,0,102,518,1,0,0,0,104,105,3, + 2,1,0,105,106,5,0,0,1,106,1,1,0,0,0,107,108,6,1,-1,0,108,109,3,4,2,0,109, + 115,1,0,0,0,110,111,10,1,0,0,111,112,5,26,0,0,112,114,3,6,3,0,113,110,1, + 0,0,0,114,117,1,0,0,0,115,113,1,0,0,0,115,116,1,0,0,0,116,3,1,0,0,0,117, + 115,1,0,0,0,118,124,3,92,46,0,119,124,3,30,15,0,120,124,3,24,12,0,121,124, + 3,96,48,0,122,124,3,98,49,0,123,118,1,0,0,0,123,119,1,0,0,0,123,120,1,0, + 0,0,123,121,1,0,0,0,123,122,1,0,0,0,124,5,1,0,0,0,125,139,3,40,20,0,126, + 139,3,44,22,0,127,139,3,56,28,0,128,139,3,62,31,0,129,139,3,58,29,0,130, + 139,3,42,21,0,131,139,3,8,4,0,132,139,3,64,32,0,133,139,3,66,33,0,134,139, + 3,70,35,0,135,139,3,72,36,0,136,139,3,100,50,0,137,139,3,74,37,0,138,125, + 1,0,0,0,138,126,1,0,0,0,138,127,1,0,0,0,138,128,1,0,0,0,138,129,1,0,0,0, + 138,130,1,0,0,0,138,131,1,0,0,0,138,132,1,0,0,0,138,133,1,0,0,0,138,134, + 1,0,0,0,138,135,1,0,0,0,138,136,1,0,0,0,138,137,1,0,0,0,139,7,1,0,0,0,140, + 141,5,18,0,0,141,142,3,10,5,0,142,9,1,0,0,0,143,144,6,5,-1,0,144,145,5, + 45,0,0,145,172,3,10,5,7,146,172,3,14,7,0,147,172,3,12,6,0,148,150,3,14, + 7,0,149,151,5,45,0,0,150,149,1,0,0,0,150,151,1,0,0,0,151,152,1,0,0,0,152, + 153,5,42,0,0,153,154,5,41,0,0,154,159,3,14,7,0,155,156,5,35,0,0,156,158, + 3,14,7,0,157,155,1,0,0,0,158,161,1,0,0,0,159,157,1,0,0,0,159,160,1,0,0, + 0,160,162,1,0,0,0,161,159,1,0,0,0,162,163,5,51,0,0,163,172,1,0,0,0,164, + 165,3,14,7,0,165,167,5,43,0,0,166,168,5,45,0,0,167,166,1,0,0,0,167,168, + 1,0,0,0,168,169,1,0,0,0,169,170,5,46,0,0,170,172,1,0,0,0,171,143,1,0,0, + 0,171,146,1,0,0,0,171,147,1,0,0,0,171,148,1,0,0,0,171,164,1,0,0,0,172,181, + 1,0,0,0,173,174,10,4,0,0,174,175,5,31,0,0,175,180,3,10,5,5,176,177,10,3, + 0,0,177,178,5,48,0,0,178,180,3,10,5,4,179,173,1,0,0,0,179,176,1,0,0,0,180, + 183,1,0,0,0,181,179,1,0,0,0,181,182,1,0,0,0,182,11,1,0,0,0,183,181,1,0, + 0,0,184,186,3,14,7,0,185,187,5,45,0,0,186,185,1,0,0,0,186,187,1,0,0,0,187, + 188,1,0,0,0,188,189,5,44,0,0,189,190,3,88,44,0,190,199,1,0,0,0,191,193, + 3,14,7,0,192,194,5,45,0,0,193,192,1,0,0,0,193,194,1,0,0,0,194,195,1,0,0, + 0,195,196,5,50,0,0,196,197,3,88,44,0,197,199,1,0,0,0,198,184,1,0,0,0,198, + 191,1,0,0,0,199,13,1,0,0,0,200,206,3,16,8,0,201,202,3,16,8,0,202,203,3, + 90,45,0,203,204,3,16,8,0,204,206,1,0,0,0,205,200,1,0,0,0,205,201,1,0,0, + 0,206,15,1,0,0,0,207,208,6,8,-1,0,208,212,3,18,9,0,209,210,7,0,0,0,210, + 212,3,16,8,3,211,207,1,0,0,0,211,209,1,0,0,0,212,221,1,0,0,0,213,214,10, + 2,0,0,214,215,7,1,0,0,215,220,3,16,8,3,216,217,10,1,0,0,217,218,7,0,0,0, + 218,220,3,16,8,2,219,213,1,0,0,0,219,216,1,0,0,0,220,223,1,0,0,0,221,219, + 1,0,0,0,221,222,1,0,0,0,222,17,1,0,0,0,223,221,1,0,0,0,224,225,6,9,-1,0, + 225,233,3,54,27,0,226,233,3,46,23,0,227,233,3,20,10,0,228,229,5,41,0,0, + 229,230,3,10,5,0,230,231,5,51,0,0,231,233,1,0,0,0,232,224,1,0,0,0,232,226, + 1,0,0,0,232,227,1,0,0,0,232,228,1,0,0,0,233,239,1,0,0,0,234,235,10,1,0, + 0,235,236,5,34,0,0,236,238,3,22,11,0,237,234,1,0,0,0,238,241,1,0,0,0,239, + 237,1,0,0,0,239,240,1,0,0,0,240,19,1,0,0,0,241,239,1,0,0,0,242,243,3,50, + 25,0,243,253,5,41,0,0,244,254,5,62,0,0,245,250,3,10,5,0,246,247,5,35,0, + 0,247,249,3,10,5,0,248,246,1,0,0,0,249,252,1,0,0,0,250,248,1,0,0,0,250, + 251,1,0,0,0,251,254,1,0,0,0,252,250,1,0,0,0,253,244,1,0,0,0,253,245,1,0, + 0,0,253,254,1,0,0,0,254,255,1,0,0,0,255,256,5,51,0,0,256,21,1,0,0,0,257, + 258,3,50,25,0,258,23,1,0,0,0,259,260,5,14,0,0,260,261,3,26,13,0,261,25, + 1,0,0,0,262,267,3,28,14,0,263,264,5,35,0,0,264,266,3,28,14,0,265,263,1, + 0,0,0,266,269,1,0,0,0,267,265,1,0,0,0,267,268,1,0,0,0,268,27,1,0,0,0,269, + 267,1,0,0,0,270,276,3,10,5,0,271,272,3,46,23,0,272,273,5,33,0,0,273,274, + 3,10,5,0,274,276,1,0,0,0,275,270,1,0,0,0,275,271,1,0,0,0,276,29,1,0,0,0, + 277,278,5,6,0,0,278,283,3,32,16,0,279,280,5,35,0,0,280,282,3,32,16,0,281, + 279,1,0,0,0,282,285,1,0,0,0,283,281,1,0,0,0,283,284,1,0,0,0,284,287,1,0, + 0,0,285,283,1,0,0,0,286,288,3,34,17,0,287,286,1,0,0,0,287,288,1,0,0,0,288, + 31,1,0,0,0,289,290,5,73,0,0,290,33,1,0,0,0,291,294,3,36,18,0,292,294,3, + 38,19,0,293,291,1,0,0,0,293,292,1,0,0,0,294,35,1,0,0,0,295,296,5,72,0,0, + 296,301,3,32,16,0,297,298,5,35,0,0,298,300,3,32,16,0,299,297,1,0,0,0,300, + 303,1,0,0,0,301,299,1,0,0,0,301,302,1,0,0,0,302,37,1,0,0,0,303,301,1,0, + 0,0,304,305,5,65,0,0,305,306,3,36,18,0,306,307,5,66,0,0,307,39,1,0,0,0, + 308,309,5,4,0,0,309,310,3,26,13,0,310,41,1,0,0,0,311,313,5,17,0,0,312,314, + 3,26,13,0,313,312,1,0,0,0,313,314,1,0,0,0,314,317,1,0,0,0,315,316,5,30, + 0,0,316,318,3,26,13,0,317,315,1,0,0,0,317,318,1,0,0,0,318,43,1,0,0,0,319, + 320,5,8,0,0,320,323,3,26,13,0,321,322,5,30,0,0,322,324,3,26,13,0,323,321, + 1,0,0,0,323,324,1,0,0,0,324,45,1,0,0,0,325,330,3,50,25,0,326,327,5,37,0, + 0,327,329,3,50,25,0,328,326,1,0,0,0,329,332,1,0,0,0,330,328,1,0,0,0,330, + 331,1,0,0,0,331,47,1,0,0,0,332,330,1,0,0,0,333,338,3,52,26,0,334,335,5, + 37,0,0,335,337,3,52,26,0,336,334,1,0,0,0,337,340,1,0,0,0,338,336,1,0,0, + 0,338,339,1,0,0,0,339,49,1,0,0,0,340,338,1,0,0,0,341,342,7,2,0,0,342,51, + 1,0,0,0,343,344,5,77,0,0,344,53,1,0,0,0,345,388,5,46,0,0,346,347,3,86,43, + 0,347,348,5,67,0,0,348,388,1,0,0,0,349,388,3,84,42,0,350,388,3,86,43,0, + 351,388,3,80,40,0,352,388,5,49,0,0,353,388,3,88,44,0,354,355,5,65,0,0,355, + 360,3,82,41,0,356,357,5,35,0,0,357,359,3,82,41,0,358,356,1,0,0,0,359,362, + 1,0,0,0,360,358,1,0,0,0,360,361,1,0,0,0,361,363,1,0,0,0,362,360,1,0,0,0, + 363,364,5,66,0,0,364,388,1,0,0,0,365,366,5,65,0,0,366,371,3,80,40,0,367, + 368,5,35,0,0,368,370,3,80,40,0,369,367,1,0,0,0,370,373,1,0,0,0,371,369, + 1,0,0,0,371,372,1,0,0,0,372,374,1,0,0,0,373,371,1,0,0,0,374,375,5,66,0, + 0,375,388,1,0,0,0,376,377,5,65,0,0,377,382,3,88,44,0,378,379,5,35,0,0,379, + 381,3,88,44,0,380,378,1,0,0,0,381,384,1,0,0,0,382,380,1,0,0,0,382,383,1, + 0,0,0,383,385,1,0,0,0,384,382,1,0,0,0,385,386,5,66,0,0,386,388,1,0,0,0, + 387,345,1,0,0,0,387,346,1,0,0,0,387,349,1,0,0,0,387,350,1,0,0,0,387,351, + 1,0,0,0,387,352,1,0,0,0,387,353,1,0,0,0,387,354,1,0,0,0,387,365,1,0,0,0, + 387,376,1,0,0,0,388,55,1,0,0,0,389,390,5,10,0,0,390,391,5,28,0,0,391,57, + 1,0,0,0,392,393,5,16,0,0,393,398,3,60,30,0,394,395,5,35,0,0,395,397,3,60, + 30,0,396,394,1,0,0,0,397,400,1,0,0,0,398,396,1,0,0,0,398,399,1,0,0,0,399, + 59,1,0,0,0,400,398,1,0,0,0,401,403,3,10,5,0,402,404,7,3,0,0,403,402,1,0, + 0,0,403,404,1,0,0,0,404,407,1,0,0,0,405,406,5,47,0,0,406,408,7,4,0,0,407, + 405,1,0,0,0,407,408,1,0,0,0,408,61,1,0,0,0,409,410,5,9,0,0,410,415,3,48, + 24,0,411,412,5,35,0,0,412,414,3,48,24,0,413,411,1,0,0,0,414,417,1,0,0,0, + 415,413,1,0,0,0,415,416,1,0,0,0,416,63,1,0,0,0,417,415,1,0,0,0,418,419, + 5,2,0,0,419,424,3,48,24,0,420,421,5,35,0,0,421,423,3,48,24,0,422,420,1, + 0,0,0,423,426,1,0,0,0,424,422,1,0,0,0,424,425,1,0,0,0,425,65,1,0,0,0,426, + 424,1,0,0,0,427,428,5,13,0,0,428,433,3,68,34,0,429,430,5,35,0,0,430,432, + 3,68,34,0,431,429,1,0,0,0,432,435,1,0,0,0,433,431,1,0,0,0,433,434,1,0,0, + 0,434,67,1,0,0,0,435,433,1,0,0,0,436,437,3,48,24,0,437,438,5,81,0,0,438, + 439,3,48,24,0,439,69,1,0,0,0,440,441,5,1,0,0,441,442,3,18,9,0,442,444,3, + 88,44,0,443,445,3,76,38,0,444,443,1,0,0,0,444,445,1,0,0,0,445,71,1,0,0, + 0,446,447,5,7,0,0,447,448,3,18,9,0,448,449,3,88,44,0,449,73,1,0,0,0,450, + 451,5,12,0,0,451,452,3,46,23,0,452,75,1,0,0,0,453,458,3,78,39,0,454,455, + 5,35,0,0,455,457,3,78,39,0,456,454,1,0,0,0,457,460,1,0,0,0,458,456,1,0, + 0,0,458,459,1,0,0,0,459,77,1,0,0,0,460,458,1,0,0,0,461,462,3,50,25,0,462, + 463,5,33,0,0,463,464,3,54,27,0,464,79,1,0,0,0,465,466,7,5,0,0,466,81,1, + 0,0,0,467,470,3,84,42,0,468,470,3,86,43,0,469,467,1,0,0,0,469,468,1,0,0, + 0,470,83,1,0,0,0,471,473,7,0,0,0,472,471,1,0,0,0,472,473,1,0,0,0,473,474, + 1,0,0,0,474,475,5,29,0,0,475,85,1,0,0,0,476,478,7,0,0,0,477,476,1,0,0,0, + 477,478,1,0,0,0,478,479,1,0,0,0,479,480,5,28,0,0,480,87,1,0,0,0,481,482, + 5,27,0,0,482,89,1,0,0,0,483,484,7,6,0,0,484,91,1,0,0,0,485,486,5,5,0,0, + 486,487,3,94,47,0,487,93,1,0,0,0,488,489,5,65,0,0,489,490,3,2,1,0,490,491, + 5,66,0,0,491,95,1,0,0,0,492,493,5,15,0,0,493,494,5,97,0,0,494,97,1,0,0, + 0,495,496,5,11,0,0,496,497,5,101,0,0,497,99,1,0,0,0,498,499,5,3,0,0,499, + 502,5,87,0,0,500,501,5,85,0,0,501,503,3,48,24,0,502,500,1,0,0,0,502,503, + 1,0,0,0,503,513,1,0,0,0,504,505,5,86,0,0,505,510,3,102,51,0,506,507,5,35, + 0,0,507,509,3,102,51,0,508,506,1,0,0,0,509,512,1,0,0,0,510,508,1,0,0,0, + 510,511,1,0,0,0,511,514,1,0,0,0,512,510,1,0,0,0,513,504,1,0,0,0,513,514, + 1,0,0,0,514,101,1,0,0,0,515,516,3,48,24,0,516,517,5,33,0,0,517,519,1,0, + 0,0,518,515,1,0,0,0,518,519,1,0,0,0,519,520,1,0,0,0,520,521,3,48,24,0,521, + 103,1,0,0,0,50,115,123,138,150,159,167,171,179,181,186,193,198,205,211, + 219,221,232,239,250,253,267,275,283,287,293,301,313,317,323,330,338,360, + 371,382,387,398,403,407,415,424,433,444,458,469,472,477,502,510,513,518]; private static __ATN: ATN; public static get _ATN(): ATN { @@ -4156,9 +4059,6 @@ export class FromCommandContext extends ParserRuleContext { public metadata(): MetadataContext { return this.getTypedRuleContext(MetadataContext, 0) as MetadataContext; } - public fromOptions(): FromOptionsContext { - return this.getTypedRuleContext(FromOptionsContext, 0) as FromOptionsContext; - } public get ruleIndex(): number { return esql_parser.RULE_fromCommand; } @@ -4199,72 +4099,6 @@ export class FromIdentifierContext extends ParserRuleContext { } -export class FromOptionsContext extends ParserRuleContext { - constructor(parser?: esql_parser, parent?: ParserRuleContext, invokingState?: number) { - super(parent, invokingState); - this.parser = parser; - } - public OPTIONS(): TerminalNode { - return this.getToken(esql_parser.OPTIONS, 0); - } - public configOption_list(): ConfigOptionContext[] { - return this.getTypedRuleContexts(ConfigOptionContext) as ConfigOptionContext[]; - } - public configOption(i: number): ConfigOptionContext { - return this.getTypedRuleContext(ConfigOptionContext, i) as ConfigOptionContext; - } - public COMMA_list(): TerminalNode[] { - return this.getTokens(esql_parser.COMMA); - } - public COMMA(i: number): TerminalNode { - return this.getToken(esql_parser.COMMA, i); - } - public get ruleIndex(): number { - return esql_parser.RULE_fromOptions; - } - public enterRule(listener: esql_parserListener): void { - if(listener.enterFromOptions) { - listener.enterFromOptions(this); - } - } - public exitRule(listener: esql_parserListener): void { - if(listener.exitFromOptions) { - listener.exitFromOptions(this); - } - } -} - - -export class ConfigOptionContext extends ParserRuleContext { - constructor(parser?: esql_parser, parent?: ParserRuleContext, invokingState?: number) { - super(parent, invokingState); - this.parser = parser; - } - public string__list(): StringContext[] { - return this.getTypedRuleContexts(StringContext) as StringContext[]; - } - public string_(i: number): StringContext { - return this.getTypedRuleContext(StringContext, i) as StringContext; - } - public ASSIGN(): TerminalNode { - return this.getToken(esql_parser.ASSIGN, 0); - } - public get ruleIndex(): number { - return esql_parser.RULE_configOption; - } - public enterRule(listener: esql_parserListener): void { - if(listener.enterConfigOption) { - listener.enterConfigOption(this); - } - } - public exitRule(listener: esql_parserListener): void { - if(listener.exitConfigOption) { - listener.exitConfigOption(this); - } - } -} - - export class MetadataContext extends ParserRuleContext { constructor(parser?: esql_parser, parent?: ParserRuleContext, invokingState?: number) { super(parent, invokingState); diff --git a/packages/kbn-esql-ast/src/antlr/esql_parser_listener.ts b/packages/kbn-esql-ast/src/antlr/esql_parser_listener.ts index 82bd908fa2b80..75847ae8805ac 100644 --- a/packages/kbn-esql-ast/src/antlr/esql_parser_listener.ts +++ b/packages/kbn-esql-ast/src/antlr/esql_parser_listener.ts @@ -34,8 +34,6 @@ import { FieldsContext } from "./esql_parser"; import { FieldContext } from "./esql_parser"; import { FromCommandContext } from "./esql_parser"; import { FromIdentifierContext } from "./esql_parser"; -import { FromOptionsContext } from "./esql_parser"; -import { ConfigOptionContext } from "./esql_parser"; import { MetadataContext } from "./esql_parser"; import { MetadataOptionContext } from "./esql_parser"; import { Deprecated_metadataContext } from "./esql_parser"; @@ -425,26 +423,6 @@ export default class esql_parserListener extends ParseTreeListener { * @param ctx the parse tree */ exitFromIdentifier?: (ctx: FromIdentifierContext) => void; - /** - * Enter a parse tree produced by `esql_parser.fromOptions`. - * @param ctx the parse tree - */ - enterFromOptions?: (ctx: FromOptionsContext) => void; - /** - * Exit a parse tree produced by `esql_parser.fromOptions`. - * @param ctx the parse tree - */ - exitFromOptions?: (ctx: FromOptionsContext) => void; - /** - * Enter a parse tree produced by `esql_parser.configOption`. - * @param ctx the parse tree - */ - enterConfigOption?: (ctx: ConfigOptionContext) => void; - /** - * Exit a parse tree produced by `esql_parser.configOption`. - * @param ctx the parse tree - */ - exitConfigOption?: (ctx: ConfigOptionContext) => void; /** * Enter a parse tree produced by `esql_parser.metadata`. * @param ctx the parse tree diff --git a/packages/kbn-esql-ast/src/ast_helpers.ts b/packages/kbn-esql-ast/src/ast_helpers.ts index d2ac5a026e316..7104eef95a062 100644 --- a/packages/kbn-esql-ast/src/ast_helpers.ts +++ b/packages/kbn-esql-ast/src/ast_helpers.ts @@ -218,7 +218,7 @@ function getQuotedText(ctx: ParserRuleContext) { } function getUnquotedText(ctx: ParserRuleContext) { - return [67 /* esql_parser.UNQUOTED_IDENTIFIER */, 74 /* esql_parser.FROM_UNQUOTED_IDENTIFIER */] + return [67 /* esql_parser.UNQUOTED_IDENTIFIER */, 73 /* esql_parser.FROM_UNQUOTED_IDENTIFIER */] .map((keyCode) => ctx.getToken(keyCode, 0)) .filter(nonNullable)[0]; } diff --git a/packages/kbn-esql-utils/src/utils/append_to_query.test.ts b/packages/kbn-esql-utils/src/utils/append_to_query.test.ts index cb9465cff05b6..2f3d28c467444 100644 --- a/packages/kbn-esql-utils/src/utils/append_to_query.test.ts +++ b/packages/kbn-esql-utils/src/utils/append_to_query.test.ts @@ -65,7 +65,7 @@ describe('appendToQuery', () => { 'from logstash-* // meow', 'dest', undefined, - '_exists_', + 'is_not_null', 'string' ) ).toBe( @@ -74,6 +74,21 @@ describe('appendToQuery', () => { ); }); + it('appends a where clause in an existing query checking that the value is null if the user filters a null value', () => { + expect( + appendWhereClauseToESQLQuery( + 'from logstash-* // meow', + 'dest', + undefined, + 'is_null', + 'string' + ) + ).toBe( + `from logstash-* // meow +| where \`dest\` is null` + ); + }); + it('appends an and clause in an existing query with where command as the last pipe', () => { expect( appendWhereClauseToESQLQuery( @@ -107,7 +122,7 @@ and \`dest\`=="Crete"` 'from logstash-* | where country IS NOT NULL', 'country', undefined, - '_exists_', + 'is_not_null', 'string' ) ).toBe(`from logstash-* | where country IS NOT NULL`); diff --git a/packages/kbn-esql-utils/src/utils/append_to_query.ts b/packages/kbn-esql-utils/src/utils/append_to_query.ts index d8f6ed3a44073..d1bf0afa33755 100644 --- a/packages/kbn-esql-utils/src/utils/append_to_query.ts +++ b/packages/kbn-esql-utils/src/utils/append_to_query.ts @@ -17,14 +17,17 @@ export function appendWhereClauseToESQLQuery( baseESQLQuery: string, field: string, value: unknown, - operation: '+' | '-' | '_exists_', + operation: '+' | '-' | 'is_not_null' | 'is_null', fieldType?: string ): string { let operator; switch (operation) { - case '_exists_': + case 'is_not_null': operator = ' is not null'; break; + case 'is_null': + operator = ' is null'; + break; case '-': operator = '!='; break; @@ -44,7 +47,7 @@ export function appendWhereClauseToESQLQuery( // checking that the value is not null // this is the existence filter - if (operation === '_exists_') { + if (operation === 'is_not_null' || operation === 'is_null') { fieldName = `\`${String(field)}\``; filterValue = ''; } @@ -67,7 +70,7 @@ export function appendWhereClauseToESQLQuery( const matches = whereClause.match(new RegExp(field + '(.*)' + String(filterValue))); if (matches) { const existingOperator = matches[1]?.trim().replace('`', '').toLowerCase(); - if (!['==', '!=', 'is not null'].includes(existingOperator.trim())) { + if (!['==', '!=', 'is not null', 'is null'].includes(existingOperator.trim())) { return appendToESQLQuery(baseESQLQuery, `and ${fieldName}${operator}${filterValue}`); } // the filter is the same diff --git a/packages/kbn-management/settings/setting_ids/index.ts b/packages/kbn-management/settings/setting_ids/index.ts index 93646978aa1a6..4fd4015baeb2c 100644 --- a/packages/kbn-management/settings/setting_ids/index.ts +++ b/packages/kbn-management/settings/setting_ids/index.ts @@ -123,6 +123,8 @@ export const OBSERVABILITY_ENABLE_COMPARISON_BY_DEFAULT_ID = 'observability:enableComparisonByDefault'; export const OBSERVABILITY_ENABLE_INFRASTRUCTURE_HOSTS_VIEW_ID = 'observability:enableInfrastructureHostsView'; +export const OBSERVABILITY_ENABLE_CONTAINER_ASSET_VIEW_ID = + 'observability:enableContainerAssetView'; export const OBSERVABILITY_ENABLE_INFRASTRUCTURE_ASSET_CUSTOM_DASHBOARDS_ID = 'observability:enableInfrastructureAssetCustomDashboards'; export const OBSERVABILITY_ENABLE_INSPECT_ES_QUERIES_ID = 'observability:enableInspectEsQueries'; diff --git a/packages/kbn-search-api-panels/components/ingest_data.tsx b/packages/kbn-search-api-panels/components/ingest_data.tsx index 0700d2d56d661..e842c499630bb 100644 --- a/packages/kbn-search-api-panels/components/ingest_data.tsx +++ b/packages/kbn-search-api-panels/components/ingest_data.tsx @@ -13,6 +13,8 @@ import { i18n } from '@kbn/i18n'; import type { ApplicationStart } from '@kbn/core-application-browser'; import type { ConsolePluginStart } from '@kbn/console-plugin/public'; import type { SharePluginStart } from '@kbn/share-plugin/public'; +import { IngestGetPipelineResponse } from '@elastic/elasticsearch/lib/api/types'; +import { IngestPipelinePanel } from './ingest_pipelines/ingest_pipeline_panel'; import { CodeBox } from './code_box'; import { LanguageDefinition } from '../types'; import { OverviewPanel } from './overview_panel'; @@ -32,11 +34,16 @@ interface IngestDataProps { languages: LanguageDefinition[]; consoleRequest?: string; additionalIngestionPanel?: React.ReactNode; + ingestPipelineData?: IngestGetPipelineResponse; + selectedPipeline: string; + setSelectedPipeline: (pipelineId: string) => void; + defaultIngestPipeline: string; } export const IngestData: React.FC = ({ codeSnippet, selectedLanguage, + selectedPipeline, setSelectedLanguage, docLinks, assetBasePath, @@ -46,6 +53,9 @@ export const IngestData: React.FC = ({ languages, consoleRequest, additionalIngestionPanel, + ingestPipelineData, + setSelectedPipeline, + defaultIngestPipeline, }) => { return ( = ({ })} > +

{i18n.translate('searchApiPanels.welcomeBanner.ingestData.alternativeOptions', { diff --git a/packages/kbn-search-api-panels/components/ingest_pipelines/ingest_pipeline_options.tsx b/packages/kbn-search-api-panels/components/ingest_pipelines/ingest_pipeline_options.tsx new file mode 100644 index 0000000000000..6a4888a643d4f --- /dev/null +++ b/packages/kbn-search-api-panels/components/ingest_pipelines/ingest_pipeline_options.tsx @@ -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 and the Server Side Public License, v 1; you may not 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, { Fragment } from 'react'; +import { EuiFlexItem, EuiText, EuiBadge, EuiFlexGroup } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { IngestPipeline } from '@elastic/elasticsearch/lib/api/types'; +import { IngestGetPipelineResponse } from '@elastic/elasticsearch/lib/api/types'; + +interface OptionItem { + value: string; + inputDisplay: string; + dropdownDisplay: JSX.Element; +} + +export interface IngestPipelineWithDeprecated extends IngestPipeline { + deprecated?: boolean; +} + +const ProcessorCount = ({ item }: { item: IngestPipelineWithDeprecated | undefined }) => ( + + +

+ {i18n.translate('searchApiPanels.welcomeBanner.ingestPipelinePanel.processorCount', { + defaultMessage: '{count} {count, plural, one {processor} other {processors}}', + values: { count: item?.processors?.length }, + })} +

+
+
+); + +const ManagedBadge = ({ item }: { item: IngestPipelineWithDeprecated | undefined }) => { + if (!item?._meta?.managed) return null; + return ( + + + {i18n.translate('searchApiPanels.welcomeBanner.ingestPipelinePanel.managedBadge', { + defaultMessage: 'Managed', + })} + + + ); +}; + +const RecommendedBadge = ({ + pipelineName, + defaultIngestPipeline, +}: { + pipelineName: string; + defaultIngestPipeline: string; +}) => { + if (pipelineName !== defaultIngestPipeline) return null; + return ( + + + {i18n.translate('searchApiPanels.welcomeBanner.ingestPipelinePanel.recommendedBadge', { + defaultMessage: 'Recommended', + })} + + + ); +}; + +const createOptionItem = ( + pipelineName: string, + item: IngestPipelineWithDeprecated | undefined, + defaultIngestPipeline: string +): OptionItem => { + return { + value: pipelineName, + inputDisplay: pipelineName, + dropdownDisplay: ( + + {pipelineName} + + + + + + + ), + }; +}; + +export const createIngestPipelineOptions = ( + ingestPipelinesData: IngestGetPipelineResponse | undefined, + defaultIngestPipeline: string +) => { + if (!ingestPipelinesData) return []; + + let options = Object.keys(ingestPipelinesData) + .filter( + (pipelineName: string) => + !(ingestPipelinesData[pipelineName] as IngestPipelineWithDeprecated)?.deprecated + ) + .map((pipelineName) => + createOptionItem(pipelineName, ingestPipelinesData[pipelineName], defaultIngestPipeline) + ); + + if (ingestPipelinesData[defaultIngestPipeline]) { + const defaultOption = createOptionItem( + defaultIngestPipeline, + ingestPipelinesData[defaultIngestPipeline], + defaultIngestPipeline + ); + options = [ + defaultOption, + ...options.filter((option) => option.value !== defaultIngestPipeline), + ]; + } + + return options; +}; diff --git a/packages/kbn-search-api-panels/components/ingest_pipelines/ingest_pipeline_panel.test.tsx b/packages/kbn-search-api-panels/components/ingest_pipelines/ingest_pipeline_panel.test.tsx new file mode 100644 index 0000000000000..040136864f295 --- /dev/null +++ b/packages/kbn-search-api-panels/components/ingest_pipelines/ingest_pipeline_panel.test.tsx @@ -0,0 +1,118 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { registerTestBed } from '@kbn/test-jest-helpers'; +import { act } from 'react-dom/test-utils'; +import { IngestPipelinePanel } from './ingest_pipeline_panel'; + +const DEFAULT_INGESTION_PIPELINE = 'default-ingestion-pipeline'; + +describe('IngestPipelinePanel', () => { + const setSelectedPipelineMock = jest.fn(); + + const mockPipelineData = { + pipeline1: { + processors: ['processor1', 'processor2'], + _meta: { + managed: true, + }, + }, + pipeline2: { + processors: ['processor1'], + _meta: { + managed: false, + }, + }, + [DEFAULT_INGESTION_PIPELINE]: { + processors: ['processor1', 'processor2', 'processor3'], + _meta: { + managed: true, + }, + }, + deprecated_pipeline: { + processors: ['processor1'], + _meta: { + managed: false, + }, + deprecated: true, + }, + } as any; + + let exists: any; + let find: any; + + beforeAll(async () => { + const setup = registerTestBed(IngestPipelinePanel, { + defaultProps: { + setSelectedPipeline: setSelectedPipelineMock, + ingestPipelinesData: mockPipelineData, + defaultIngestPipeline: DEFAULT_INGESTION_PIPELINE, + }, + memoryRouter: { wrapComponent: false }, + }); + + await act(async () => { + const testBed = setup(); + exists = testBed.exists; + find = testBed.find; + }); + }); + + it('should display Process Data section', () => { + expect(exists('ingestPipelinePanelTitle')).toBe(true); + expect(find('ingestPipelinePanelTitle').contains('Preprocess your data')).toBe(true); + expect( + find('ingestPipelinePanelBody').contains( + 'You can use ingest pipelines to preprocess data before indexing into Elasticsearch.' + ) + ).toBe(true); + expect(find('ingestPipelinePanelTitle').find('.euiBadge__text').contains('Optional')).toBe( + true + ); + }); + + it('should display number of processors', () => { + find('ingestPipelinePanelSelect').simulate('click'); + expect(find('ingestPipelinePanelOptions').at(0).contains('3 processors')).toBe(true); + expect(find('ingestPipelinePanelOptions').at(1).contains('2 processors')).toBe(true); + expect(find('ingestPipelinePanelOptions').at(2).contains('1 processor')).toBe(true); + }); + + it('should display the badges correctly', () => { + find('ingestPipelinePanelSelect').simulate('click'); + expect( + find('ingestPipelinePanelOptions').at(0).find('.euiBadge__text').contains('Recommended') + ).toBe(true); + expect( + find('ingestPipelinePanelOptions').at(1).find('.euiBadge__text').contains('Managed') + ).toBe(true); + expect( + find('ingestPipelinePanelOptions').at(2).find('.euiBadge__text').contains('Managed') + ).toBe(false); + }); + + it('should display only active pipelines', () => { + find('ingestPipelinePanelSelect').simulate('click'); + expect(find('ingestPipelinePanelOptionTitle').contains('pipeline1')).toBe(true); + expect(find('ingestPipelinePanelOptionTitle').contains('deprecated_pipeline')).toBe(false); + }); + + it('should display the recommended pipeline at the beginning', () => { + find('ingestPipelinePanelSelect').simulate('click'); + expect(find('ingestPipelinePanelOptionTitle').at(0).contains(DEFAULT_INGESTION_PIPELINE)).toBe( + true + ); + }); + + describe('when there exists no ingest pipeline', () => { + it('should display an empty list of pipelines', () => { + find('ingestPipelinePanelSelect').simulate('click'); + expect(exists('ingestPipelinePanelOptions')).toBe(false); + }); + }); +}); diff --git a/packages/kbn-search-api-panels/components/ingest_pipelines/ingest_pipeline_panel.tsx b/packages/kbn-search-api-panels/components/ingest_pipelines/ingest_pipeline_panel.tsx new file mode 100644 index 0000000000000..a746b2bc0e61e --- /dev/null +++ b/packages/kbn-search-api-panels/components/ingest_pipelines/ingest_pipeline_panel.tsx @@ -0,0 +1,89 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import React, { useMemo } from 'react'; + +import { + EuiFlexGroup, + EuiFlexItem, + EuiSpacer, + EuiText, + EuiTitle, + EuiBadge, + EuiSuperSelect, +} from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { IngestGetPipelineResponse } from '@elastic/elasticsearch/lib/api/types'; +import { createIngestPipelineOptions } from './ingest_pipeline_options'; + +interface IngestPipelinePanelProps { + selectedPipeline: string; + setSelectedPipeline: (pipeline: string) => void; + ingestPipelinesData?: IngestGetPipelineResponse; + defaultIngestPipeline: string; +} + +export const IngestPipelinePanel: React.FC = ({ + selectedPipeline, + setSelectedPipeline, + ingestPipelinesData, + defaultIngestPipeline, +}) => { + const options = useMemo( + () => createIngestPipelineOptions(ingestPipelinesData, defaultIngestPipeline), + [ingestPipelinesData, defaultIngestPipeline] + ); + + return ( + <> + + + + + {i18n.translate('searchApiPanels.welcomeBanner.ingestPipelinePanel.title', { + defaultMessage: 'Preprocess your data', + })} + + + + + + {i18n.translate('searchApiPanels.welcomeBanner.ingestPipelinePanel.optionalBadge', { + defaultMessage: 'Optional', + })} + + + + + +

+ {i18n.translate('searchApiPanels.welcomeBanner.ingestPipelinePanel.description', { + defaultMessage: + 'You can use ingest pipelines to preprocess data before indexing into Elasticsearch.', + })} +

+
+ + + + + ); +}; diff --git a/packages/kbn-search-api-panels/index.tsx b/packages/kbn-search-api-panels/index.tsx index 10276bc9c5325..f0a64685348de 100644 --- a/packages/kbn-search-api-panels/index.tsx +++ b/packages/kbn-search-api-panels/index.tsx @@ -13,6 +13,7 @@ import { AuthenticatedUser } from '@kbn/security-plugin/common'; export * from './components/cloud_details'; export * from './components/code_box'; +export * from './components/ingest_pipelines/ingest_pipeline_panel'; export * from './components/github_link'; export * from './components/ingest_data'; export * from './components/ingestions_panel'; diff --git a/packages/kbn-search-api-panels/languages/console.ts b/packages/kbn-search-api-panels/languages/console.ts index e156409239242..27aeb96b93ba4 100644 --- a/packages/kbn-search-api-panels/languages/console.ts +++ b/packages/kbn-search-api-panels/languages/console.ts @@ -19,7 +19,9 @@ export const consoleDefinition: Partial = { } } }`, - ingestData: `POST _bulk?pretty + ingestData: ({ ingestPipeline }) => `POST _bulk?pretty${ + ingestPipeline ? `&pipeline=${ingestPipeline}` : '' + } { "index" : { "_index" : "books" } } {"name": "Snow Crash", "author": "Neal Stephenson", "release_date": "1992-06-01", "page_count": 470} { "index" : { "_index" : "books" } } diff --git a/packages/kbn-search-api-panels/tsconfig.json b/packages/kbn-search-api-panels/tsconfig.json index 20294566e4cc3..a3b9c16a04512 100644 --- a/packages/kbn-search-api-panels/tsconfig.json +++ b/packages/kbn-search-api-panels/tsconfig.json @@ -23,6 +23,7 @@ "@kbn/security-plugin", "@kbn/console-plugin", "@kbn/ui-theme", - "@kbn/try-in-console" + "@kbn/try-in-console", + "@kbn/test-jest-helpers" ] } diff --git a/packages/kbn-search-api-panels/utils.test.ts b/packages/kbn-search-api-panels/utils.test.ts index c842dd03cf275..ef77838250312 100644 --- a/packages/kbn-search-api-panels/utils.test.ts +++ b/packages/kbn-search-api-panels/utils.test.ts @@ -12,8 +12,8 @@ import { getConsoleRequest } from './utils'; describe('utils', () => { describe('getConsoleRequest()', () => { test('accepts string values', () => { - const consoleRequest = getConsoleRequest('ingestData'); - expect(consoleRequest).toEqual(consoleDefinition.ingestData); + const consoleRequest = getConsoleRequest('buildSearchQuery'); + expect(consoleRequest).toEqual(consoleDefinition.buildSearchQuery); }); test('accepts function values', () => { diff --git a/packages/kbn-search-connectors/lib/update_filtering.test.ts b/packages/kbn-search-connectors/lib/update_filtering.test.ts new file mode 100644 index 0000000000000..284210539230b --- /dev/null +++ b/packages/kbn-search-connectors/lib/update_filtering.test.ts @@ -0,0 +1,99 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { ElasticsearchClient } from '@kbn/core/server'; + +import { errors } from '@elastic/elasticsearch'; + +import { updateFiltering } from './update_filtering'; +import { FilteringRule, FilteringRules, FilteringValidationState } from '../types/connectors'; + +describe('updateFiltering lib function', () => { + const mockClient = { + transport: { + request: jest.fn(), + }, + }; + + beforeEach(() => { + jest.clearAllMocks(); + jest.useFakeTimers(); + jest.setSystemTime(new Date('2024-05-25T12:00:00.000Z')); + }); + + it('should activate connector filtering draft', async () => { + const filteringRule: FilteringRule = { + updated_at: '2024-05-10T12:14:14.291Z', + created_at: '2024-05-09T14:37:56.090Z', + field: 'name', + id: 'my-rule', + order: 0, + policy: 'exclude', + rule: 'regex', + value: 'test.*', + }; + + const draftToActivate: FilteringRules = { + advanced_snippet: { + created_at: '2024-05-25T12:00:00.000Z', + updated_at: '2024-05-25T12:00:00.000Z', + value: {}, + }, + rules: [ + { + ...filteringRule, + updated_at: '2024-05-25T12:00:00.000Z', + }, + ], + validation: { + errors: [], + state: FilteringValidationState.VALID, + }, + }; + + mockClient.transport.request.mockImplementationOnce(() => ({ result: 'updated' })); + mockClient.transport.request.mockImplementationOnce(() => ({ + filtering: [{ active: draftToActivate }], + })); + + await expect( + updateFiltering(mockClient as unknown as ElasticsearchClient, 'connectorId') + ).resolves.toEqual(draftToActivate); + expect(mockClient.transport.request).toHaveBeenCalledWith({ + method: 'PUT', + path: '/_connector/connectorId/_filtering/activate', + }); + }); + + it('should not index document if there is no connector', async () => { + mockClient.transport.request.mockImplementationOnce(() => { + return Promise.reject( + new errors.ResponseError({ + statusCode: 404, + body: { + error: { + type: `document_missing_exception`, + }, + }, + } as any) + ); + }); + await expect( + updateFiltering(mockClient as unknown as ElasticsearchClient, 'connectorId') + ).rejects.toEqual( + new errors.ResponseError({ + statusCode: 404, + body: { + error: { + type: `document_missing_exception`, + }, + }, + } as any) + ); + }); +}); diff --git a/packages/kbn-search-connectors/lib/update_filtering.ts b/packages/kbn-search-connectors/lib/update_filtering.ts index 9651828fdc313..0c02b9da899a4 100644 --- a/packages/kbn-search-connectors/lib/update_filtering.ts +++ b/packages/kbn-search-connectors/lib/update_filtering.ts @@ -6,59 +6,24 @@ * Side Public License, v 1. */ +import { Result } from '@elastic/elasticsearch/lib/api/types'; import { ElasticsearchClient } from '@kbn/core-elasticsearch-server'; -import { CONNECTORS_INDEX } from '..'; import { fetchConnectorById } from './fetch_connectors'; -import { - Connector, - FilteringRule, - FilteringRules, - FilteringValidationState, -} from '../types/connectors'; +import { FilteringRules } from '../types/connectors'; export const updateFiltering = async ( client: ElasticsearchClient, - connectorId: string, - { - advancedSnippet, - filteringRules, - }: { - advancedSnippet: string; - filteringRules: FilteringRule[]; - } + connectorId: string ): Promise => { - const now = new Date().toISOString(); - const parsedAdvancedSnippet: Record = advancedSnippet - ? JSON.parse(advancedSnippet) - : {}; - const parsedFilteringRules = filteringRules.map((filteringRule) => ({ - ...filteringRule, - created_at: filteringRule.created_at ? filteringRule.created_at : now, - updated_at: now, - })); - const connector = await fetchConnectorById(client, connectorId); - if (!connector) { - throw new Error(`Could not find connector with id ${connectorId}`); - } - const active: FilteringRules = { - advanced_snippet: { - created_at: connector.filtering[0].active.advanced_snippet.created_at || now, - updated_at: now, - value: parsedAdvancedSnippet, - }, - rules: parsedFilteringRules, - validation: { - errors: [], - state: FilteringValidationState.VALID, - }, - }; - - const result = await client.update({ - doc: { ...connector, filtering: [{ ...connector.filtering[0], active, draft: active }] }, - id: connectorId, - index: CONNECTORS_INDEX, + const activateDraftFilteringResult = await client.transport.request<{ result: Result }>({ + method: 'PUT', + path: `/_connector/${connectorId}/_filtering/activate`, }); - return result.result === 'updated' ? active : undefined; + if (activateDraftFilteringResult.result === 'updated') { + const connector = await fetchConnectorById(client, connectorId); + return connector?.filtering?.[0]?.active; + } + return undefined; }; diff --git a/packages/kbn-search-connectors/lib/update_filtering_draft.test.ts b/packages/kbn-search-connectors/lib/update_filtering_draft.test.ts new file mode 100644 index 0000000000000..cfbc4e9d70713 --- /dev/null +++ b/packages/kbn-search-connectors/lib/update_filtering_draft.test.ts @@ -0,0 +1,116 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { ElasticsearchClient } from '@kbn/core/server'; + +import { errors } from '@elastic/elasticsearch'; + +import { updateFilteringDraft } from './update_filtering_draft'; +import { FilteringRule, FilteringRules, FilteringValidationState } from '../types/connectors'; + +describe('updateFilteringDraft lib function', () => { + const mockClient = { + transport: { + request: jest.fn(), + }, + }; + + beforeEach(() => { + jest.clearAllMocks(); + jest.useFakeTimers(); + jest.setSystemTime(new Date('2024-05-25T12:00:00.000Z')); + }); + + it('should update connector filtering draft', async () => { + const filteringRule: FilteringRule = { + updated_at: '2024-05-10T12:14:14.291Z', + created_at: '2024-05-09T14:37:56.090Z', + field: 'name', + id: 'my-rule', + order: 0, + policy: 'exclude', + rule: 'regex', + value: 'test.*', + }; + + const draft: FilteringRules = { + advanced_snippet: { + created_at: '2024-05-25T12:00:00.000Z', + updated_at: '2024-05-25T12:00:00.000Z', + value: {}, + }, + rules: [ + { + ...filteringRule, + updated_at: '2024-05-25T12:00:00.000Z', + }, + ], + validation: { + errors: [], + state: FilteringValidationState.EDITED, + }, + }; + + mockClient.transport.request.mockImplementationOnce(() => ({ result: 'updated' })); + mockClient.transport.request.mockImplementationOnce(() => ({ filtering: [{ draft }] })); + + await expect( + updateFilteringDraft(mockClient as unknown as ElasticsearchClient, 'connectorId', { + advancedSnippet: '{}', + filteringRules: [filteringRule], + }) + ).resolves.toEqual(draft); + expect(mockClient.transport.request).toHaveBeenCalledWith({ + body: { + advanced_snippet: { + created_at: '2024-05-25T12:00:00.000Z', + updated_at: '2024-05-25T12:00:00.000Z', + value: {}, + }, + rules: [ + { + ...filteringRule, + updated_at: '2024-05-25T12:00:00.000Z', + }, + ], + }, + method: 'PUT', + path: '/_connector/connectorId/_filtering', + }); + }); + + it('should not index document if there is no connector', async () => { + mockClient.transport.request.mockImplementationOnce(() => { + return Promise.reject( + new errors.ResponseError({ + statusCode: 404, + body: { + error: { + type: `document_missing_exception`, + }, + }, + } as any) + ); + }); + await expect( + updateFilteringDraft(mockClient as unknown as ElasticsearchClient, 'connectorId', { + advancedSnippet: '{}', + filteringRules: [], + }) + ).rejects.toEqual( + new errors.ResponseError({ + statusCode: 404, + body: { + error: { + type: `document_missing_exception`, + }, + }, + } as any) + ); + }); +}); diff --git a/packages/kbn-search-connectors/lib/update_filtering_draft.ts b/packages/kbn-search-connectors/lib/update_filtering_draft.ts index 154f85f4becb0..6d580604004c8 100644 --- a/packages/kbn-search-connectors/lib/update_filtering_draft.ts +++ b/packages/kbn-search-connectors/lib/update_filtering_draft.ts @@ -6,16 +6,11 @@ * Side Public License, v 1. */ +import { Result } from '@elastic/elasticsearch/lib/api/types'; import { ElasticsearchClient } from '@kbn/core-elasticsearch-server'; -import { CONNECTORS_INDEX } from '..'; import { fetchConnectorById } from './fetch_connectors'; -import { - Connector, - FilteringRule, - FilteringRules, - FilteringValidationState, -} from '../types/connectors'; +import { FilteringRule, FilteringRules } from '../types/connectors'; export const updateFilteringDraft = async ( client: ElasticsearchClient, @@ -37,28 +32,25 @@ export const updateFilteringDraft = async ( created_at: filteringRule.created_at ? filteringRule.created_at : now, updated_at: now, })); - const draft: FilteringRules = { + + const draft = { advanced_snippet: { created_at: now, updated_at: now, value: parsedAdvancedSnippet, }, rules: parsedFilteringRules, - validation: { - errors: [], - state: FilteringValidationState.EDITED, - }, }; - const connector = await fetchConnectorById(client, connectorId); - if (!connector) { - throw new Error(`Could not find connector with id ${connectorId}`); - } - const result = await client.update({ - doc: { ...connector, filtering: [{ ...connector.filtering[0], draft }] }, - id: connectorId, - index: CONNECTORS_INDEX, + const updateDraftFilteringResult = await client.transport.request<{ result: Result }>({ + method: 'PUT', + path: `/_connector/${connectorId}/_filtering`, + body: draft, }); - return result.result === 'updated' ? draft : undefined; + if (updateDraftFilteringResult.result === 'updated') { + const connector = await fetchConnectorById(client, connectorId); + return connector?.filtering?.[0]?.draft; + } + return undefined; }; diff --git a/packages/kbn-std/src/is_internal_url.test.ts b/packages/kbn-std/src/is_internal_url.test.ts index cc1f5a32d7db4..24e043a72073c 100644 --- a/packages/kbn-std/src/is_internal_url.test.ts +++ b/packages/kbn-std/src/is_internal_url.test.ts @@ -61,6 +61,84 @@ describe('isInternalURL', () => { const href = `${basePath}/app/kibana/../../../management`; expect(isInternalURL(href, basePath)).toBe(false); }); + + it('should return `false` if absolute URL contains tabs or new lines', () => { + // These URLs can either be treated as internal or external depending on the presence of the special characters. + const getURLsWithCharInRelativeScheme = (char: string) => [ + `/${char}${basePath}app/kibana`, + `/${char}/${basePath}/app/kibana`, + `/${char}${basePath}/example.com`, + `/${char}/${basePath}/example.com`, + `/${char}${basePath}/example.org`, + `/${char}/${basePath}/example.org`, + `/${char}${basePath}/example.org:5601`, + `/${char}/${basePath}/example.org:5601`, + ]; + + // These URLs can either be treated as internal or external depending on the presence of the special characters + // AND spaces since these affect how URL's scheme is parsed. + const getURLsWithCharInScheme = (char: string) => [ + `htt${char}ps://example.com${basePath}`, + `htt${char}ps://example.org${basePath}`, + `htt${char}ps://example.org:5601${basePath}`, + `java${char}script:${basePath}alert(1)`, + `htt${char}p:/${basePath}/example.org:5601`, + `file${char}:/${basePath}/example.com`, + ]; + + // These URLs should always be recognized as external irrespective to the presence of the special characters or + // spaces since these affect URLs hostname. + const getURLsWithCharInHost = (char: string) => [ + `//${char}${basePath}/app/kibana`, + `//${char}/example.com${basePath}`, + `//${char}/example.org${basePath}`, + `//${char}/example.org:5601${basePath}`, + `https:/${char}/example.com${basePath}`, + // This URL is only valid if the `char` is a tab or newline character. + `https://example${char}.com${basePath}/path`, + ]; + + // Detection logic should treat URLs as if tab and newline characters weren't present. + for (const char of ['', '\t', '\n', '\r', '\t\n\r']) { + for (const url of [ + ...getURLsWithCharInRelativeScheme(char), + ...getURLsWithCharInScheme(char), + ...getURLsWithCharInHost(char), + ]) { + expect(isInternalURL(url)).toBe(false); + } + } + + // Characters that aren't tabs, spaces, or newline characters turn absolute scheme-relative URLs to relative URLs. + for (const char of ['1', 'a']) { + for (const url of getURLsWithCharInRelativeScheme(char)) { + expect(isInternalURL(url)).toBe(true); + } + + for (const url of getURLsWithCharInScheme(char)) { + expect(isInternalURL(url)).toBe(false); + } + + for (const url of getURLsWithCharInHost(char)) { + expect(isInternalURL(url)).toBe(false); + } + } + + // Spaces aren't allowed in scheme definition and turn absolute URLs into relative URLs. + for (const char of [' ']) { + for (const url of getURLsWithCharInRelativeScheme(char)) { + expect(isInternalURL(url)).toBe(true); + } + + for (const url of getURLsWithCharInScheme(char)) { + expect(isInternalURL(url)).toBe(true); + } + + for (const url of getURLsWithCharInHost(char)) { + expect(isInternalURL(url)).toBe(false); + } + } + }); }); describe('without basePath defined', () => { @@ -86,5 +164,83 @@ describe('isInternalURL', () => { const hrefWithThreeSlashes = `///app/kibana`; expect(isInternalURL(hrefWithThreeSlashes)).toBe(false); }); + + it('should properly handle tabs or newline characters in the URL', () => { + // These URLs can either be treated as internal or external depending on the presence of the special characters. + const getURLsWithCharInRelativeScheme = (char: string) => [ + `/${char}/app/kibana`, + `/${char}//app/kibana`, + `/${char}/example.com`, + `/${char}//example.com`, + `/${char}/example.org`, + `/${char}//example.org`, + `/${char}/example.org:5601`, + `/${char}//example.org:5601`, + ]; + + // These URLs can either be treated as internal or external depending on the presence of the special characters + // AND spaces since these affect how URL's scheme is parsed. + const getURLsWithCharInScheme = (char: string) => [ + `htt${char}ps://example.com`, + `htt${char}ps://example.org`, + `htt${char}ps://example.org:5601`, + `java${char}script:alert(1)`, + `htt${char}p://example.org:5601`, + `file${char}://example.com`, + ]; + + // These URLs should always be recognized as external irrespective to the presence of the special characters or + // spaces since these affect URLs hostname. + const getURLsWithCharInHost = (char: string) => [ + `//${char}/app/kibana`, + `//${char}/example.com`, + `//${char}/example.org`, + `//${char}/example.org:5601`, + `https:/${char}/example.com`, + // This URL is only valid if the `char` is a tab or newline character. + `https://example${char}.com/path`, + ]; + + // Detection logic should treat URLs as if tab and newline characters weren't present. + for (const char of ['', '\t', '\n', '\r', '\t\n\r']) { + for (const url of [ + ...getURLsWithCharInRelativeScheme(char), + ...getURLsWithCharInScheme(char), + ...getURLsWithCharInHost(char), + ]) { + expect(isInternalURL(url)).toBe(false); + } + } + + // Characters that aren't tabs, spaces, or newline characters turn absolute scheme-relative URLs to relative URLs. + for (const char of ['1', 'a']) { + for (const url of getURLsWithCharInRelativeScheme(char)) { + expect(isInternalURL(url)).toBe(true); + } + + for (const url of getURLsWithCharInScheme(char)) { + expect(isInternalURL(url)).toBe(false); + } + + for (const url of getURLsWithCharInHost(char)) { + expect(isInternalURL(url)).toBe(false); + } + } + + // Spaces aren't allowed in scheme definition and turn absolute URLs into relative URLs. + for (const char of [' ']) { + for (const url of getURLsWithCharInRelativeScheme(char)) { + expect(isInternalURL(url)).toBe(true); + } + + for (const url of getURLsWithCharInScheme(char)) { + expect(isInternalURL(url)).toBe(true); + } + + for (const url of getURLsWithCharInHost(char)) { + expect(isInternalURL(url)).toBe(false); + } + } + }); }); }); diff --git a/packages/kbn-std/src/is_internal_url.ts b/packages/kbn-std/src/is_internal_url.ts index 434fa6eaf7c27..d6251594aafc0 100644 --- a/packages/kbn-std/src/is_internal_url.ts +++ b/packages/kbn-std/src/is_internal_url.ts @@ -6,37 +6,35 @@ * Side Public License, v 1. */ -import { parse as parseUrl } from 'url'; - /** * Determine if url is outside of this Kibana install. */ export function isInternalURL(url: string, basePath = '') { - const { protocol, hostname, port, pathname } = parseUrl( - url, - false /* parseQueryString */, - true /* slashesDenoteHost */ - ); - - // We should explicitly compare `protocol`, `port` and `hostname` to null to make sure these are not - // detected in the URL at all. For example `hostname` can be empty string for Node URL parser, but - // browser (because of various bwc reasons) processes URL differently (e.g. `///abc.com` - for browser - // hostname is `abc.com`, but for Node hostname is an empty string i.e. everything between schema (`//`) - // and the first slash that belongs to path. - if (protocol !== null || hostname !== null || port !== null) { + // We use the WHATWG parser TWICE with completely different dummy base URLs to ensure that the parsed URL always + // inherits the origin of the base URL. This means that the specified URL isn't an absolute URL, or a scheme-relative + // URL (//), or a scheme-relative URL with an empty host (///). Browsers may process such URLs unexpectedly due to + // backward compatibility reasons (e.g., a browser may treat `///abc.com` as just `abc.com`). For more details, refer + // to https://url.spec.whatwg.org/#concept-basic-url-parser and https://url.spec.whatwg.org/#url-representation. + let normalizedURL: URL; + try { + for (const baseURL of ['http://example.org:5601', 'https://example.com']) { + normalizedURL = new URL(url, baseURL); + if (normalizedURL.origin !== baseURL) { + return false; + } + } + } catch { return false; } + // Now we need to normalize URL to make sure any relative path segments (`..`) cannot escape expected base path. if (basePath) { - // Now we need to normalize URL to make sure any relative path segments (`..`) cannot escape expected - // base path. We can rely on `URL` with a localhost to automatically "normalize" the URL. - const normalizedPathname = new URL(String(pathname), 'https://localhost').pathname; - return ( // Normalized pathname can add a leading slash, but we should also make sure it's included in - // the original URL too - pathname?.startsWith('/') && - (normalizedPathname === basePath || normalizedPathname.startsWith(`${basePath}/`)) + // the original URL too. We can safely use non-null assertion operator here since we know `normalizedURL` is + // always defined, otherwise we would have returned `false` already. + url.startsWith('/') && + (normalizedURL!.pathname === basePath || normalizedURL!.pathname.startsWith(`${basePath}/`)) ); } diff --git a/packages/kbn-std/src/pick.test.ts b/packages/kbn-std/src/pick.test.ts new file mode 100644 index 0000000000000..b58c8b1e9a9f8 --- /dev/null +++ b/packages/kbn-std/src/pick.test.ts @@ -0,0 +1,35 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { pick } from './pick'; + +describe('pick', () => { + it('works with object created inline', () => { + const obj = { foo: 'bar', hello: 'dolly' }; + + const result = pick(obj, ['foo']); + expect(result).toEqual({ foo: 'bar' }); + }); + + it('works with objects created via Object.create(null)', () => { + const obj = Object.create(null); + Object.assign(obj, { foo: 'bar', hello: 'dolly' }); + + const result = pick(obj, ['foo']); + expect(result).toEqual({ foo: 'bar' }); + }); + + it('does not pick properties from the prototype', () => { + const proto = { prot: 'o' }; + const obj = Object.create(proto); + Object.assign(obj, { foo: 'bar', hello: 'dolly' }); + + const result = pick(obj, ['foo', 'prot']); + expect(result).toEqual({ foo: 'bar' }); + }); +}); diff --git a/packages/kbn-std/src/pick.ts b/packages/kbn-std/src/pick.ts index c8347aadb219a..8d01c80caee6d 100644 --- a/packages/kbn-std/src/pick.ts +++ b/packages/kbn-std/src/pick.ts @@ -8,10 +8,9 @@ export function pick(obj: T, keys: readonly K[]): Pick { return keys.reduce((acc, key) => { - if (obj.hasOwnProperty(key)) { + if (Object.hasOwn(obj, key)) { acc[key] = obj[key]; } - return acc; }, {} as Pick); } diff --git a/packages/kbn-test/src/es/test_es_cluster.ts b/packages/kbn-test/src/es/test_es_cluster.ts index 12f020175fd4e..a2078a1e56e16 100644 --- a/packages/kbn-test/src/es/test_es_cluster.ts +++ b/packages/kbn-test/src/es/test_es_cluster.ts @@ -182,7 +182,6 @@ export function createTestEsCluster< } = options; const clusterName = `${CI_PARALLEL_PROCESS_PREFIX}${customClusterName}`; - const isFIPSMode = process.env.FTR_FIPS_MODE === '1'; const defaultEsArgs = [ `cluster.name=${clusterName}`, @@ -193,12 +192,7 @@ export function createTestEsCluster< : ['discovery.type=single-node']), ]; - const esArgs = assignArgs( - defaultEsArgs, - // ML has issues running in FIPS mode due to custom OpenSSL - // Remove after https://github.com/elastic/kibana-operations/issues/96 - isFIPSMode ? [...customEsArgs, 'xpack.ml.enabled=false'] : customEsArgs - ); + const esArgs = assignArgs(defaultEsArgs, customEsArgs); const config = { version: esTestConfig.getVersion(), @@ -231,22 +225,21 @@ export function createTestEsCluster< async start() { let installPath: string; + let disableEsTmpDir: boolean; // We only install once using the first node. If the cluster has // multiple nodes, they'll all share the same ESinstallation. const firstNode = this.nodes[0]; if (esFrom === 'source') { - installPath = ( - await firstNode.installSource({ - sourcePath: config.sourcePath, - license: config.license, - password: config.password, - basePath: config.basePath, - esArgs: config.esArgs, - }) - ).installPath; + ({ installPath, disableEsTmpDir } = await firstNode.installSource({ + sourcePath: config.sourcePath, + license: config.license, + password: config.password, + basePath: config.basePath, + esArgs: config.esArgs, + })); } else if (esFrom === 'snapshot') { - installPath = (await firstNode.installSnapshot(config)).installPath; + ({ installPath, disableEsTmpDir } = await firstNode.installSnapshot(config)); } else if (esFrom === 'serverless') { if (!esServerlessOptions) { throw new Error( @@ -308,6 +301,7 @@ export function createTestEsCluster< skipReadyCheck: this.nodes.length > 1 && i < this.nodes.length - 1, onEarlyExit, writeLogsToPath, + disableEsTmpDir, }); }); } diff --git a/packages/kbn-text-based-editor/src/text_based_languages_editor.tsx b/packages/kbn-text-based-editor/src/text_based_languages_editor.tsx index 64dac6802e6fc..fd20d9c2b25ca 100644 --- a/packages/kbn-text-based-editor/src/text_based_languages_editor.tsx +++ b/packages/kbn-text-based-editor/src/text_based_languages_editor.tsx @@ -359,8 +359,8 @@ export const TextBasedLanguagesEditor = memo(function TextBasedLanguagesEditor({ return { cache: fn.cache, memoizedFieldsFromESQL: fn }; }, []); - const esqlCallbacks: ESQLCallbacks = useMemo( - () => ({ + const esqlCallbacks: ESQLCallbacks = useMemo(() => { + const callbacks: ESQLCallbacks = { getSources: async () => { const [remoteIndices, localIndices] = await Promise.all([ getRemoteIndicesList(dataViews), @@ -399,16 +399,16 @@ export const TextBasedLanguagesEditor = memo(function TextBasedLanguagesEditor({ } return policies.map(({ type, query: policyQuery, ...rest }) => rest); }, - }), - [ - dataViews, - expressions, - indexManagementApiService, - esqlFieldsCache, - memoizedFieldsFromESQL, - abortController, - ] - ); + }; + return callbacks; + }, [ + dataViews, + expressions, + indexManagementApiService, + esqlFieldsCache, + memoizedFieldsFromESQL, + abortController, + ]); const parseMessages = useCallback(async () => { if (editorModel.current) { 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 2fa22873190e5..015c517e9a6b8 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 @@ -85,6 +85,7 @@ describe('checking migration metadata changes on all registered SO types', () => "core-usage-stats": "b3c04da317c957741ebcdedfea4524049fdc79ff", "csp-rule-template": "c151324d5f85178169395eecb12bac6b96064654", "dashboard": "211e9ca30f5a95d5f3c27b1bf2b58e6cfa0c9ae9", + "endpoint:unified-user-artifact-manifest": "71c7fcb52c658b21ea2800a6b6a76972ae1c776e", "endpoint:user-artifact-manifest": "1c3533161811a58772e30cdc77bac4631da3ef2b", "enterprise_search_telemetry": "9ac912e1417fc8681e0cd383775382117c9e3d3d", "epm-packages": "f8ee125b57df31fd035dc04ad81aef475fd2f5bd", @@ -111,7 +112,7 @@ describe('checking migration metadata changes on all registered SO types', () => "ingest-agent-policies": "803dc27e106440c41e8f3c3d8ee8bbb0821bcde2", "ingest-download-sources": "279a68147e62e4d8858c09ad1cf03bd5551ce58d", "ingest-outputs": "daafff49255ab700e07491376fe89f04fc998b91", - "ingest-package-policies": "d63e091b2b3cf2eecaa46ae2533bdd5214a983fc", + "ingest-package-policies": "e6da7d0ee2996241ade23b3a7811fe5d3e449cb2", "ingest_manager_settings": "91445219e7115ff0c45d1dabd5d614a80b421797", "inventory-view": "b8683c8e352a286b4aca1ab21003115a4800af83", "kql-telemetry": "93c1d16c1a0dfca9c8842062cf5ef8f62ae401ad", diff --git a/src/core/server/integration_tests/http/cookie_session_storage.test.ts b/src/core/server/integration_tests/http/cookie_session_storage.test.ts index 4a71502db0ccb..192a3daf8fd2d 100644 --- a/src/core/server/integration_tests/http/cookie_session_storage.test.ts +++ b/src/core/server/integration_tests/http/cookie_session_storage.test.ts @@ -134,7 +134,7 @@ describe('Cookie based SessionStorage', () => { const response = await supertest(innerServer.listener).get('/').expect(200); - const cookies = response.get('set-cookie'); + const cookies = response.get('set-cookie')!; expect(cookies).toBeDefined(); expect(cookies).toHaveLength(1); @@ -172,7 +172,7 @@ describe('Cookie based SessionStorage', () => { const response = await supertest(innerServer.listener).get('/').expect(200); - const cookies = response.get('set-cookie'); + const cookies = response.get('set-cookie')!; expect(cookies).toBeDefined(); expect(cookies).toHaveLength(1); @@ -204,7 +204,7 @@ describe('Cookie based SessionStorage', () => { const response = await supertest(innerServer.listener).get('/').expect(200, { value: null }); - const cookies = response.get('set-cookie'); + const cookies = response.get('set-cookie')!; expect(cookies).not.toBeDefined(); }); @@ -237,7 +237,7 @@ describe('Cookie based SessionStorage', () => { .get('/') .expect(200, { value: userData }); - const cookies = response.get('set-cookie'); + const cookies = response.get('set-cookie')!; expect(cookies).toBeDefined(); await delay(sessionDurationMs); @@ -283,7 +283,7 @@ describe('Cookie based SessionStorage', () => { .get('/') .expect(200, { value: userData }); - const cookies = response.get('set-cookie'); + const cookies = response.get('set-cookie')!; expect(cookies).toBeDefined(); const sessionCookie = retrieveSessionCookie(cookies[0]); @@ -418,7 +418,7 @@ describe('Cookie based SessionStorage', () => { const response = await supertest(innerServer.listener).get('/').expect(200); - const cookies = response.get('set-cookie'); + const cookies = response.get('set-cookie')!; const sessionCookie = retrieveSessionCookie(cookies[0]); const response2 = await supertest(innerServer.listener) @@ -475,7 +475,7 @@ describe('Cookie based SessionStorage', () => { const response = await supertest(innerServer.listener).get('/').expect(200); - const cookies = response.get('set-cookie'); + const cookies = response.get('set-cookie')!; expect(cookies).toBeDefined(); expect(cookies).toHaveLength(1); diff --git a/src/core/server/integration_tests/http/versioned_router.test.ts b/src/core/server/integration_tests/http/versioned_router.test.ts index 86427a2488e2d..72daedb990dff 100644 --- a/src/core/server/integration_tests/http/versioned_router.test.ts +++ b/src/core/server/integration_tests/http/versioned_router.test.ts @@ -29,7 +29,7 @@ interface AdditionalOptions { describe('Routing versioned requests', () => { let router: IRouter; - let supertest: Supertest.SuperTest; + let supertest: Supertest.Agent; async function setupServer(cliArgs: Partial = {}, options: AdditionalOptions = {}) { logger = loggingSystemMock.create(); diff --git a/src/core/server/integration_tests/metrics/server_collector.test.ts b/src/core/server/integration_tests/metrics/server_collector.test.ts index 6151cd1ebe6bf..481447f599b21 100644 --- a/src/core/server/integration_tests/metrics/server_collector.test.ts +++ b/src/core/server/integration_tests/metrics/server_collector.test.ts @@ -116,7 +116,7 @@ describe('ServerMetricsCollector', () => { // Subscribe to the aborted$ event const waitFor1stAbort = disconnectAborted$.pipe(take(1)).toPromise(); - discoReq1.abort(); + void discoReq1.abort(); // Wait for the aborted$ event await waitFor1stAbort; @@ -132,7 +132,7 @@ describe('ServerMetricsCollector', () => { // Subscribe to the aborted$ event const waitFor2ndAbort = disconnectAborted$.pipe(take(1)).toPromise(); - discoReq2.abort(); + void discoReq2.abort(); // Wait for the aborted$ event await waitFor2ndAbort; diff --git a/src/core/server/integration_tests/saved_objects/migrations/group3/type_registrations.test.ts b/src/core/server/integration_tests/saved_objects/migrations/group3/type_registrations.test.ts index 43f0d03b86552..712ddd4bca932 100644 --- a/src/core/server/integration_tests/saved_objects/migrations/group3/type_registrations.test.ts +++ b/src/core/server/integration_tests/saved_objects/migrations/group3/type_registrations.test.ts @@ -49,6 +49,7 @@ const previouslyRegisteredTypes = [ 'event-annotation-group', 'endpoint:user-artifact', 'endpoint:user-artifact-manifest', + 'endpoint:unified-user-artifact-manifest', 'enterprise_search_telemetry', 'epm-packages', 'epm-packages-assets', diff --git a/src/core/server/integration_tests/saved_objects/migrations/group5/dot_kibana_split.test.ts b/src/core/server/integration_tests/saved_objects/migrations/group5/dot_kibana_split.test.ts index 22a3b9858599a..dcb40a3b07621 100644 --- a/src/core/server/integration_tests/saved_objects/migrations/group5/dot_kibana_split.test.ts +++ b/src/core/server/integration_tests/saved_objects/migrations/group5/dot_kibana_split.test.ts @@ -205,6 +205,7 @@ describe('split .kibana index into multiple system indices', () => { "connector_token", "core-usage-stats", "csp-rule-template", + "endpoint:unified-user-artifact-manifest", "endpoint:user-artifact-manifest", "enterprise_search_telemetry", "epm-packages", 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 9a58281ba55b3..d9e67b8389326 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 @@ -107,7 +107,7 @@ RUN for iter in {1..10}; do \ apt-get update && \ apt-get upgrade -y && \ apt-get install -y --no-install-recommends \ - fontconfig libnss3 ca-certificates && \ + fontconfig libnss3 curl ca-certificates && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* && exit_code=0 && break || exit_code=$? && echo "apt-get error: retry $iter in 10s" && \ sleep 10; \ diff --git a/src/plugins/data_views/server/index_patterns_api_client.ts b/src/plugins/data_views/server/index_patterns_api_client.ts index 849102c46aa91..28c79836cf8e5 100644 --- a/src/plugins/data_views/server/index_patterns_api_client.ts +++ b/src/plugins/data_views/server/index_patterns_api_client.ts @@ -31,6 +31,7 @@ export class IndexPatternsApiServer implements IDataViewsApiClient { allowNoIndex, indexFilter, fields, + includeEmptyFields, }: GetFieldsOptions) { const indexPatterns = new IndexPatternsFetcher(this.esClient, { uiSettingsClient: this.uiSettingsClient, @@ -45,6 +46,7 @@ export class IndexPatternsApiServer implements IDataViewsApiClient { rollupIndex, indexFilter, fields, + includeEmptyFields, }) .catch((err) => { if ( diff --git a/src/plugins/discover/common/data_types/logs/constants.ts b/src/plugins/discover/common/data_types/logs/constants.ts new file mode 100644 index 0000000000000..5726bf8439b8f --- /dev/null +++ b/src/plugins/discover/common/data_types/logs/constants.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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { fieldConstants } from '@kbn/discover-utils'; +import { SmartFieldGridColumnOptions } from './display_options'; + +export * from '@kbn/discover-utils/src/field_constants'; + +export const LOGS_EXPLORER_PROFILE_ID = 'logs-explorer'; + +// Virtual column fields +export const CONTENT_FIELD = 'content'; +export const RESOURCE_FIELD = 'resource'; + +// Sizing +export const DATA_GRID_COLUMN_WIDTH_SMALL = 240; +export const DATA_GRID_COLUMN_WIDTH_MEDIUM = 320; +export const ACTIONS_COLUMN_WIDTH = 80; + +export const RESOURCE_FIELD_CONFIGURATION: SmartFieldGridColumnOptions = { + type: 'smart-field', + smartField: RESOURCE_FIELD, + fallbackFields: [fieldConstants.HOST_NAME_FIELD, fieldConstants.SERVICE_NAME_FIELD], + width: DATA_GRID_COLUMN_WIDTH_MEDIUM, +}; + +export const CONTENT_FIELD_CONFIGURATION: SmartFieldGridColumnOptions = { + type: 'smart-field', + smartField: CONTENT_FIELD, + fallbackFields: [fieldConstants.MESSAGE_FIELD], +}; + +export const SMART_FALLBACK_FIELDS = { + [CONTENT_FIELD]: CONTENT_FIELD_CONFIGURATION, + [RESOURCE_FIELD]: RESOURCE_FIELD_CONFIGURATION, +}; + +// UI preferences +export const DEFAULT_COLUMNS = [RESOURCE_FIELD_CONFIGURATION, CONTENT_FIELD_CONFIGURATION]; +export const DEFAULT_ROWS_PER_PAGE = 100; + +// List of prefixes which needs to be filtered out for Display in Content Column +export const FILTER_OUT_FIELDS_PREFIXES_FOR_CONTENT = [ + '_', // Filter fields like '_id', '_score' + '@timestamp', + 'agent.', + 'elastic_agent.', + 'data_stream.', + 'ecs.', + 'host.', + 'container.', + 'cloud.', + 'kubernetes.', + 'orchestrator.', + 'log.', + 'service.', +]; + +export const DEFAULT_ALLOWED_DATA_VIEWS = ['logs', 'auditbeat', 'filebeat', 'winlogbeat']; +export const DEFAULT_ALLOWED_LOGS_DATA_VIEWS = ['logs', 'auditbeat', 'filebeat', 'winlogbeat']; diff --git a/src/plugins/discover/common/data_types/logs/display_options.ts b/src/plugins/discover/common/data_types/logs/display_options.ts new file mode 100644 index 0000000000000..13c760649bbbe --- /dev/null +++ b/src/plugins/discover/common/data_types/logs/display_options.ts @@ -0,0 +1,14 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export interface SmartFieldGridColumnOptions { + type: 'smart-field'; + smartField: 'content' | 'resource'; + fallbackFields: string[]; + width?: number; +} diff --git a/src/plugins/discover/public/application/main/components/layout/discover_documents.test.tsx b/src/plugins/discover/public/application/main/components/layout/discover_documents.test.tsx index bc739d9433e63..ae4b05f495cfa 100644 --- a/src/plugins/discover/public/application/main/components/layout/discover_documents.test.tsx +++ b/src/plugins/discover/public/application/main/components/layout/discover_documents.test.tsx @@ -109,17 +109,6 @@ describe('Discover documents layout', () => { }); test('should render customisations', async () => { - const customCellRenderer = { - content: () => Test, - }; - - const customGridColumnsConfiguration = { - content: () => ({ - id: 'content', - displayText: Column, - }), - }; - const customControlColumnsConfiguration = () => ({ leadingControlColumns: [], trailingControlColumns: [], @@ -127,8 +116,7 @@ describe('Discover documents layout', () => { const customization: DiscoverCustomization = { id: 'data_table', - customCellRenderer, - customGridColumnsConfiguration, + logsEnabled: true, customControlColumnsConfiguration, }; @@ -137,12 +125,10 @@ describe('Discover documents layout', () => { const discoverGridComponent = component.find(DiscoverGrid); expect(discoverGridComponent.exists()).toBeTruthy(); - expect(discoverGridComponent.prop('externalCustomRenderers')).toEqual(customCellRenderer); - expect(discoverGridComponent.prop('customGridColumnsConfiguration')).toEqual( - customGridColumnsConfiguration - ); expect(discoverGridComponent.prop('customControlColumnsConfiguration')).toEqual( customControlColumnsConfiguration ); + expect(discoverGridComponent.prop('externalCustomRenderers')).toBeDefined(); + expect(discoverGridComponent.prop('customGridColumnsConfiguration')).toBeDefined(); }); }); diff --git a/src/plugins/discover/public/application/main/components/layout/discover_documents.tsx b/src/plugins/discover/public/application/main/components/layout/discover_documents.tsx index 57df6e8639ead..b5f50f2ca9c14 100644 --- a/src/plugins/discover/public/application/main/components/layout/discover_documents.tsx +++ b/src/plugins/discover/public/application/main/components/layout/discover_documents.tsx @@ -67,6 +67,7 @@ import { useFetchMoreRecords } from './use_fetch_more_records'; import { SelectedVSAvailableCallout } from './selected_vs_available_callout'; import { useDiscoverCustomization } from '../../../../customizations'; import { onResizeGridColumn } from '../../../../utils/on_resize_grid_column'; +import { useContextualGridCustomisations } from '../../hooks/grid_customisations'; const containerStyles = css` position: relative; @@ -258,11 +259,9 @@ function DiscoverDocumentsComponent({ [dataView, onAddColumn, onAddFilter, onRemoveColumn, query, savedSearch.id, setExpandedDoc] ); - const { - customCellRenderer: externalCustomRenderers, - customGridColumnsConfiguration, - customControlColumnsConfiguration, - } = useDiscoverCustomization('data_table') || {}; + const { customControlColumnsConfiguration } = useDiscoverCustomization('data_table') || {}; + const { customCellRenderer, customGridColumnsConfiguration } = + useContextualGridCustomisations() || {}; const documents = useObservable(stateContainer.dataState.data$.documents$); @@ -432,7 +431,7 @@ function DiscoverDocumentsComponent({ totalHits={totalHits} onFetchMoreRecords={onFetchMoreRecords} componentsTourSteps={TOUR_STEPS} - externalCustomRenderers={externalCustomRenderers} + externalCustomRenderers={customCellRenderer} customGridColumnsConfiguration={customGridColumnsConfiguration} customControlColumnsConfiguration={customControlColumnsConfiguration} /> diff --git a/src/plugins/discover/public/application/main/components/layout/discover_layout.tsx b/src/plugins/discover/public/application/main/components/layout/discover_layout.tsx index 7065e511951b6..0a7524ef8bddf 100644 --- a/src/plugins/discover/public/application/main/components/layout/discover_layout.tsx +++ b/src/plugins/discover/public/application/main/components/layout/discover_layout.tsx @@ -158,6 +158,21 @@ export function DiscoverLayout({ stateContainer }: DiscoverLayoutProps) { [filterManager, dataView, dataViews, trackUiMetric, capabilities] ); + const getOperator = (fieldName: string, values: unknown, operation: '+' | '-') => { + if (fieldName === '_exists_') { + return 'is_not_null'; + } + if (values == null && operation === '-') { + return 'is_not_null'; + } + + if (values == null && operation === '+') { + return 'is_null'; + } + + return operation; + }; + const onPopulateWhereClause = useCallback( (field: DataViewField | string, values: unknown, operation: '+' | '-') => { if (query && isOfAggregateQueryType(query) && 'esql' in query) { @@ -170,8 +185,8 @@ export function DiscoverLayout({ stateContainer }: DiscoverLayoutProps) { const updatedQuery = appendWhereClauseToESQLQuery( query.esql, fieldName === '_exists_' ? String(values) : fieldName, - fieldName === '_exists_' ? undefined : values, - fieldName === '_exists_' ? '_exists_' : operation, + fieldName === '_exists_' || values == null ? undefined : values, + getOperator(fieldName, values, operation), fieldType ); data.query.queryString.setQuery({ diff --git a/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar_responsive.test.tsx b/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar_responsive.test.tsx index d245eb337bff4..d915821d88e25 100644 --- a/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar_responsive.test.tsx +++ b/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar_responsive.test.tsx @@ -37,7 +37,6 @@ import { buildDataTableRecord } from '@kbn/discover-utils'; import type { DataTableRecord } from '@kbn/discover-utils/types'; import type { DiscoverCustomizationId } from '../../../../customizations/customization_service'; import { FieldListCustomization, SearchBarCustomization } from '../../../../customizations'; -import { DataViewField } from '@kbn/data-views-plugin/common'; const mockSearchBarCustomization: SearchBarCustomization = { id: 'search_bar', @@ -46,22 +45,9 @@ const mockSearchBarCustomization: SearchBarCustomization = { .mockName('CustomDataViewPickerMock'), }; -const smartFields = [ - new DataViewField({ - name: 'mock_field', - type: 'mock_field', - searchable: false, - aggregatable: false, - }), -]; - -const additionalFieldGroups = { - smartFields, -}; - const mockFieldListCustomisation: FieldListCustomization = { id: 'field_list', - additionalFieldGroups, + logsFieldsEnabled: true, }; let mockUseCustomizations = false; @@ -786,7 +772,7 @@ describe('discover responsive sidebar', function () { const smartFieldsCount = findTestSubject(comp, 'fieldListGroupedSmartFields-count'); - expect(smartFieldsCount.text()).toBe('1'); + expect(smartFieldsCount.text()).toBe('2'); }); }); }); diff --git a/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar_responsive.tsx b/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar_responsive.tsx index e9caffaecccbc..67c7bd28f0b0b 100644 --- a/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar_responsive.tsx +++ b/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar_responsive.tsx @@ -38,6 +38,7 @@ import { DiscoverSidebarReducerStatus, } from './lib/sidebar_reducer'; import { useDiscoverCustomization } from '../../../../customizations'; +import { useAdditionalFieldGroups } from '../../hooks/sidebar/use_additional_field_groups'; const EMPTY_FIELD_COUNTS = {}; @@ -331,7 +332,7 @@ export function DiscoverSidebarResponsive(props: DiscoverSidebarResponsiveProps) ); const searchBarCustomization = useDiscoverCustomization('search_bar'); - const fieldListCustomization = useDiscoverCustomization('field_list'); + const additionalFieldGroups = useAdditionalFieldGroups(); const CustomDataViewPicker = searchBarCustomization?.CustomDataViewPicker; const createField = unifiedFieldListSidebarContainerApi?.createField; @@ -408,7 +409,7 @@ export function DiscoverSidebarResponsive(props: DiscoverSidebarResponsiveProps) onAddFilter={onAddFilter} onFieldEdited={onFieldEdited} prependInFlyout={prependDataViewPickerForMobile} - additionalFieldGroups={fieldListCustomization?.additionalFieldGroups} + additionalFieldGroups={additionalFieldGroups} /> ) : null} diff --git a/src/plugins/discover/public/application/main/hooks/grid_customisations/index.ts b/src/plugins/discover/public/application/main/hooks/grid_customisations/index.ts new file mode 100644 index 0000000000000..301c96695de02 --- /dev/null +++ b/src/plugins/discover/public/application/main/hooks/grid_customisations/index.ts @@ -0,0 +1,28 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { useMemo } from 'react'; +import { useDiscoverServices } from '../../../../hooks/use_discover_services'; +import { useDiscoverCustomization } from '../../../../customizations'; +import { getLogsVirtualColumnsConfiguration } from './logs'; + +export * from './logs'; + +export const useContextualGridCustomisations = () => { + const { data } = useDiscoverServices(); + // TODO / NOTE: This will eventually rely on Discover's context resolution to determine which fields + // are returned based on the data type. + const isLogsContext = useDiscoverCustomization('data_table')?.logsEnabled; + + const virtualColumnsConfiguration = useMemo(() => { + if (!isLogsContext) return null; + if (isLogsContext) return getLogsVirtualColumnsConfiguration(data); + }, [data, isLogsContext]); + + return virtualColumnsConfiguration; +}; diff --git a/src/plugins/discover/public/application/main/hooks/grid_customisations/logs.tsx b/src/plugins/discover/public/application/main/hooks/grid_customisations/logs.tsx new file mode 100644 index 0000000000000..ae5c51c265c5c --- /dev/null +++ b/src/plugins/discover/public/application/main/hooks/grid_customisations/logs.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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { DataPublicPluginStart } from '@kbn/data-plugin/public'; +import { CONTENT_FIELD, RESOURCE_FIELD } from '../../../../../common/data_types/logs/constants'; +import { renderCell } from '../../../../components/discover_grid/virtual_columns/logs/cell_renderer'; +import { renderColumn } from '../../../../components/discover_grid/virtual_columns/logs/column'; + +export const getLogsVirtualColumnsConfiguration = (data: DataPublicPluginStart) => { + return { + customCellRenderer: createCustomCellRenderer({ data }), + customGridColumnsConfiguration: createCustomGridColumnsConfiguration(), + }; +}; + +export const createCustomCellRenderer = ({ data }: { data: DataPublicPluginStart }) => { + return { + [CONTENT_FIELD]: renderCell(CONTENT_FIELD, { data }), + [RESOURCE_FIELD]: renderCell(RESOURCE_FIELD, { data }), + }; +}; + +export const createCustomGridColumnsConfiguration = () => ({ + [CONTENT_FIELD]: renderColumn(CONTENT_FIELD), + [RESOURCE_FIELD]: renderColumn(RESOURCE_FIELD), +}); diff --git a/src/plugins/discover/public/application/main/hooks/grid_customisations/use_virtual_column_services.tsx b/src/plugins/discover/public/application/main/hooks/grid_customisations/use_virtual_column_services.tsx new file mode 100644 index 0000000000000..386fc6586258d --- /dev/null +++ b/src/plugins/discover/public/application/main/hooks/grid_customisations/use_virtual_column_services.tsx @@ -0,0 +1,23 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import createContainer from 'constate'; +import type { DataView } from '@kbn/data-views-plugin/common'; +import { DataPublicPluginStart } from '@kbn/data-plugin/public'; + +export interface UseVirtualColumnServices { + services: { + data: DataPublicPluginStart; + dataView: DataView; + }; +} + +const useVirtualColumns = ({ services }: UseVirtualColumnServices) => services; + +export const [VirtualColumnServiceProvider, useVirtualColumnServiceContext] = + createContainer(useVirtualColumns); diff --git a/src/plugins/discover/public/application/main/hooks/sidebar/use_additional_field_groups.tsx b/src/plugins/discover/public/application/main/hooks/sidebar/use_additional_field_groups.tsx new file mode 100644 index 0000000000000..6f9ab0073904f --- /dev/null +++ b/src/plugins/discover/public/application/main/hooks/sidebar/use_additional_field_groups.tsx @@ -0,0 +1,37 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { DataViewField } from '@kbn/data-views-plugin/common'; +import { useDiscoverCustomization } from '../../../../customizations'; +import * as constants from '../../../../../common/data_types/logs/constants'; + +export const useAdditionalFieldGroups = () => { + // TODO / NOTE: This will eventually rely on Discover's context resolution to determine which fields + // are returned based on the data type. + const isLogsContext = useDiscoverCustomization('field_list')?.logsFieldsEnabled; + + if (isLogsContext) { + const smartFields = [ + new DataViewField({ + name: constants.RESOURCE_FIELD, + type: 'smart_field', + searchable: false, + aggregatable: false, + }), + new DataViewField({ + name: constants.CONTENT_FIELD, + type: 'smart_field', + searchable: false, + aggregatable: false, + }), + ]; + return { + smartFields, + }; + } +}; diff --git a/x-pack/plugins/observability_solution/logs_explorer/public/components/common/copy_button.tsx b/src/plugins/discover/public/components/data_types/logs/copy_button.tsx similarity index 82% rename from x-pack/plugins/observability_solution/logs_explorer/public/components/common/copy_button.tsx rename to src/plugins/discover/public/components/data_types/logs/copy_button.tsx index fe02a7a872720..83da6f3896edf 100644 --- a/x-pack/plugins/observability_solution/logs_explorer/public/components/common/copy_button.tsx +++ b/src/plugins/discover/public/components/data_types/logs/copy_button.tsx @@ -1,8 +1,9 @@ /* * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. */ import { EuiButtonEmpty, EuiFlexItem, copyToClipboard } from '@elastic/eui'; diff --git a/x-pack/plugins/observability_solution/logs_explorer/public/components/common/filter_in_button.tsx b/src/plugins/discover/public/components/data_types/logs/filter_in_button.tsx similarity index 75% rename from x-pack/plugins/observability_solution/logs_explorer/public/components/common/filter_in_button.tsx rename to src/plugins/discover/public/components/data_types/logs/filter_in_button.tsx index e2f43d1b0c5fc..71412a90002bd 100644 --- a/x-pack/plugins/observability_solution/logs_explorer/public/components/common/filter_in_button.tsx +++ b/src/plugins/discover/public/components/data_types/logs/filter_in_button.tsx @@ -1,15 +1,16 @@ /* * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. */ import { EuiButtonEmpty, EuiFlexItem } from '@elastic/eui'; import React from 'react'; import { generateFilters } from '@kbn/data-plugin/public'; -import { filterForText, actionFilterForText } from './translations'; -import { useVirtualColumnServiceContext } from '../../hooks/use_virtual_column_services'; +import { useVirtualColumnServiceContext } from '../../../application/main/hooks/grid_customisations/use_virtual_column_services'; +import { actionFilterForText, filterForText } from './translations'; export const FilterInButton = ({ property, value }: { property: string; value: string }) => { const ariaFilterForText = actionFilterForText(value); diff --git a/x-pack/plugins/observability_solution/logs_explorer/public/components/common/filter_out_button.tsx b/src/plugins/discover/public/components/data_types/logs/filter_out_button.tsx similarity index 76% rename from x-pack/plugins/observability_solution/logs_explorer/public/components/common/filter_out_button.tsx rename to src/plugins/discover/public/components/data_types/logs/filter_out_button.tsx index 9291e17cc44fd..3c3892b31ba5e 100644 --- a/x-pack/plugins/observability_solution/logs_explorer/public/components/common/filter_out_button.tsx +++ b/src/plugins/discover/public/components/data_types/logs/filter_out_button.tsx @@ -1,15 +1,16 @@ /* * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. */ import { EuiButtonEmpty, EuiFlexItem } from '@elastic/eui'; import React from 'react'; import { generateFilters } from '@kbn/data-plugin/public'; -import { filterOutText, actionFilterOutText } from './translations'; -import { useVirtualColumnServiceContext } from '../../hooks/use_virtual_column_services'; +import { useVirtualColumnServiceContext } from '../../../application/main/hooks/grid_customisations/use_virtual_column_services'; +import { actionFilterOutText, filterOutText } from './translations'; export const FilterOutButton = ({ property, value }: { property: string; value: string }) => { const ariaFilterOutText = actionFilterOutText(value); diff --git a/x-pack/plugins/observability_solution/logs_explorer/public/components/common/log_level.tsx b/src/plugins/discover/public/components/data_types/logs/log_level.tsx similarity index 79% rename from x-pack/plugins/observability_solution/logs_explorer/public/components/common/log_level.tsx rename to src/plugins/discover/public/components/data_types/logs/log_level.tsx index 9f5dfef23ce0d..bddc6486f3c81 100644 --- a/x-pack/plugins/observability_solution/logs_explorer/public/components/common/log_level.tsx +++ b/src/plugins/discover/public/components/data_types/logs/log_level.tsx @@ -1,15 +1,16 @@ /* * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. */ import React from 'react'; import { useEuiTheme } from '@elastic/eui'; -import { FlyoutDoc } from '../../../common/document'; +import { LogFlyoutDoc } from '@kbn/discover-utils/src'; +import * as constants from '../../../../common/data_types/logs/constants'; import { ChipWithPopover } from './popover_chip'; -import * as constants from '../../../common/constants'; const LEVEL_DICT = { error: 'danger', @@ -19,7 +20,7 @@ const LEVEL_DICT = { } as const; interface LogLevelProps { - level: FlyoutDoc['log.level']; + level: LogFlyoutDoc['log.level']; dataTestSubj?: string; renderInFlyout?: boolean; } diff --git a/x-pack/plugins/observability_solution/logs_explorer/public/components/common/popover_chip.tsx b/src/plugins/discover/public/components/data_types/logs/popover_chip.tsx similarity index 95% rename from x-pack/plugins/observability_solution/logs_explorer/public/components/common/popover_chip.tsx rename to src/plugins/discover/public/components/data_types/logs/popover_chip.tsx index 2811bbf5480c4..8631cb563cddb 100644 --- a/x-pack/plugins/observability_solution/logs_explorer/public/components/common/popover_chip.tsx +++ b/src/plugins/discover/public/components/data_types/logs/popover_chip.tsx @@ -1,8 +1,9 @@ /* * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. */ import React, { useCallback, useState } from 'react'; diff --git a/src/plugins/discover/public/components/data_types/logs/translations.tsx b/src/plugins/discover/public/components/data_types/logs/translations.tsx new file mode 100644 index 0000000000000..fcf846d0ea891 --- /dev/null +++ b/src/plugins/discover/public/components/data_types/logs/translations.tsx @@ -0,0 +1,300 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import React from 'react'; +import { i18n } from '@kbn/i18n'; +import { EuiCode } from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n-react'; + +export const flyoutContentLabel = i18n.translate('discover.logs.flyoutDetail.label.message', { + defaultMessage: 'Content breakdown', +}); + +export const contentLabel = i18n.translate('discover.logs.dataTable.header.popover.content', { + defaultMessage: 'Content', +}); + +export const resourceLabel = i18n.translate('discover.logs.dataTable.header.popover.resource', { + defaultMessage: 'Resource', +}); + +export const actionsLabel = i18n.translate('discover.logs.dataTable.header.popover.actions', { + defaultMessage: 'Actions', +}); + +export const actionsLabelLowerCase = i18n.translate( + 'discover.logs.dataTable.header.popover.actions.lowercase', + { + defaultMessage: 'actions', + } +); + +export const flyoutServiceLabel = i18n.translate('discover.logs.flyoutDetail.label.service', { + defaultMessage: 'Service', +}); + +export const flyoutTraceLabel = i18n.translate('discover.logs.flyoutDetail.label.trace', { + defaultMessage: 'Trace', +}); + +export const flyoutHostNameLabel = i18n.translate('discover.logs.flyoutDetail.label.hostName', { + defaultMessage: 'Host name', +}); + +export const serviceInfraAccordionTitle = i18n.translate( + 'discover.logs.flyoutDetail.accordion.title.serviceInfra', + { + defaultMessage: 'Service & Infrastructure', + } +); + +export const cloudAccordionTitle = i18n.translate( + 'discover.logs.flyoutDetail.accordion.title.cloud', + { + defaultMessage: 'Cloud', + } +); + +export const otherAccordionTitle = i18n.translate( + 'discover.logs.flyoutDetail.accordion.title.other', + { + defaultMessage: 'Other', + } +); + +export const flyoutOrchestratorClusterNameLabel = i18n.translate( + 'discover.logs.flyoutDetail.label.orchestratorClusterName', + { + defaultMessage: 'Orchestrator cluster Name', + } +); + +export const flyoutOrchestratorResourceIdLabel = i18n.translate( + 'discover.logs.flyoutDetail.label.orchestratorResourceId', + { + defaultMessage: 'Orchestrator resource ID', + } +); + +export const flyoutCloudProviderLabel = i18n.translate( + 'discover.logs.flyoutDetail.label.cloudProvider', + { + defaultMessage: 'Cloud provider', + } +); + +export const flyoutCloudRegionLabel = i18n.translate( + 'discover.logs.flyoutDetail.label.cloudRegion', + { + defaultMessage: 'Cloud region', + } +); + +export const flyoutCloudAvailabilityZoneLabel = i18n.translate( + 'discover.logs.flyoutDetail.label.cloudAvailabilityZone', + { + defaultMessage: 'Cloud availability zone', + } +); + +export const flyoutCloudProjectIdLabel = i18n.translate( + 'discover.logs.flyoutDetail.label.cloudProjectId', + { + defaultMessage: 'Cloud project ID', + } +); + +export const flyoutCloudInstanceIdLabel = i18n.translate( + 'discover.logs.flyoutDetail.label.cloudInstanceId', + { + defaultMessage: 'Cloud instance ID', + } +); + +export const flyoutLogPathFileLabel = i18n.translate( + 'discover.logs.flyoutDetail.label.logPathFile', + { + defaultMessage: 'Log path file', + } +); + +export const flyoutNamespaceLabel = i18n.translate('discover.logs.flyoutDetail.label.namespace', { + defaultMessage: 'Namespace', +}); + +export const flyoutDatasetLabel = i18n.translate('discover.logs.flyoutDetail.label.dataset', { + defaultMessage: 'Dataset', +}); + +export const flyoutShipperLabel = i18n.translate('discover.logs.flyoutDetail.label.shipper', { + defaultMessage: 'Shipper', +}); + +export const actionFilterForText = (text: string) => + i18n.translate('discover.logs.flyoutDetail.value.hover.filterFor', { + defaultMessage: 'Filter for this {value}', + values: { + value: text, + }, + }); + +export const actionFilterOutText = (text: string) => + i18n.translate('discover.logs.flyoutDetail.value.hover.filterOut', { + defaultMessage: 'Filter out this {value}', + values: { + value: text, + }, + }); + +export const filterOutText = i18n.translate('discover.logs.popoverAction.filterOut', { + defaultMessage: 'Filter out', +}); + +export const filterForText = i18n.translate('discover.logs.popoverAction.filterFor', { + defaultMessage: 'Filter for', +}); + +export const flyoutHoverActionFilterForFieldPresentText = i18n.translate( + 'discover.logs.flyoutDetail.value.hover.filterForFieldPresent', + { + defaultMessage: 'Filter for field present', + } +); + +export const flyoutHoverActionToggleColumnText = i18n.translate( + 'discover.logs.flyoutDetail.value.hover.toggleColumn', + { + defaultMessage: 'Toggle column in table', + } +); + +export const flyoutHoverActionCopyToClipboardText = i18n.translate( + 'discover.logs.flyoutDetail.value.hover.copyToClipboard', + { + defaultMessage: 'Copy to clipboard', + } +); + +export const copyValueText = i18n.translate('discover.logs.popoverAction.copyValue', { + defaultMessage: 'Copy value', +}); + +export const copyValueAriaText = (fieldName: string) => + i18n.translate('discover.logs.popoverAction.copyValueAriaText', { + defaultMessage: 'Copy value of {fieldName}', + values: { + fieldName, + }, + }); + +export const flyoutAccordionShowMoreText = (count: number) => + i18n.translate('discover.logs.flyoutDetail.section.showMore', { + defaultMessage: '+ {hiddenCount} more', + values: { + hiddenCount: count, + }, + }); + +export const openCellActionPopoverAriaText = i18n.translate( + 'discover.logs.popoverAction.openPopover', + { + defaultMessage: 'Open popover', + } +); + +export const closeCellActionPopoverText = i18n.translate( + 'discover.logs.popoverAction.closePopover', + { + defaultMessage: 'Close popover', + } +); + +export const contentHeaderTooltipParagraph1 = ( + log.level, + message: message, + }} + /> +); + +export const contentHeaderTooltipParagraph2 = i18n.translate( + 'discover.logs.dataTable.header.content.tooltip.paragraph2', + { + defaultMessage: 'When the message field is empty, one of the following is displayed:', + } +); + +export const resourceHeaderTooltipParagraph = i18n.translate( + 'discover.logs.dataTable.header.resource.tooltip.paragraph', + { + defaultMessage: "Fields that provide information on the document's source, such as:", + } +); + +export const actionsHeaderTooltipParagraph = i18n.translate( + 'discover.logs.dataTable.header.actions.tooltip.paragraph', + { + defaultMessage: 'Fields that provide actionable information, such as:', + } +); + +export const actionsHeaderTooltipExpandAction = i18n.translate( + 'discover.logs.dataTable.header.actions.tooltip.expand', + { defaultMessage: 'Expand log details' } +); + +export const actionsHeaderTooltipDegradedAction = ( + + _ignored + + ), + }} + /> +); + +export const actionsHeaderTooltipStacktraceAction = i18n.translate( + 'discover.logs.dataTable.header.actions.tooltip.stacktrace', + { defaultMessage: 'Access to available stacktraces based on:' } +); + +export const degradedDocButtonLabelWhenPresent = i18n.translate( + 'discover.logs.dataTable.controlColumn.actions.button.degradedDocPresent', + { + defaultMessage: + "This document couldn't be parsed correctly. Not all fields are properly populated", + } +); + +export const degradedDocButtonLabelWhenNotPresent = i18n.translate( + 'discover.logs.dataTable.controlColumn.actions.button.degradedDocNotPresent', + { + defaultMessage: 'All fields in this document were parsed correctly', + } +); + +export const stacktraceAvailableControlButton = i18n.translate( + 'discover.logs.dataTable.controlColumn.actions.button.stacktrace.available', + { + defaultMessage: 'Stacktraces available', + } +); + +export const stacktraceNotAvailableControlButton = i18n.translate( + 'discover.logs.dataTable.controlColumn.actions.button.stacktrace.notAvailable', + { + defaultMessage: 'Stacktraces not available', + } +); diff --git a/x-pack/plugins/observability_solution/logs_explorer/public/components/virtual_columns/cell_renderer.tsx b/src/plugins/discover/public/components/discover_grid/virtual_columns/logs/cell_renderer.tsx similarity index 63% rename from x-pack/plugins/observability_solution/logs_explorer/public/components/virtual_columns/cell_renderer.tsx rename to src/plugins/discover/public/components/discover_grid/virtual_columns/logs/cell_renderer.tsx index eefb165167f4a..d7f5b2fc63170 100644 --- a/x-pack/plugins/observability_solution/logs_explorer/public/components/virtual_columns/cell_renderer.tsx +++ b/src/plugins/discover/public/components/discover_grid/virtual_columns/logs/cell_renderer.tsx @@ -1,20 +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. + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. */ import React from 'react'; import type { DataGridCellValueElementProps } from '@kbn/unified-data-table'; -import { LogsExplorerDiscoverServices } from '../../controller'; -import { VirtualColumnServiceProvider } from '../../hooks/use_virtual_column_services'; -import { CONTENT_FIELD, RESOURCE_FIELD } from '../../../common/constants'; +import { DataPublicPluginStart } from '@kbn/data-plugin/public'; +import { VirtualColumnServiceProvider } from '../../../../application/main/hooks/grid_customisations/use_virtual_column_services'; +import { CONTENT_FIELD, RESOURCE_FIELD } from '../../../../../common/data_types/logs/constants'; import { Content } from './content'; import { Resource } from './resource'; export const renderCell = - (type: string, { data }: { data: LogsExplorerDiscoverServices['data'] }) => + (type: string, { data }: { data: DataPublicPluginStart }) => (props: DataGridCellValueElementProps) => { const { dataView } = props; const virtualColumnServices = { diff --git a/x-pack/plugins/observability_solution/logs_explorer/public/components/virtual_columns/column.tsx b/src/plugins/discover/public/components/discover_grid/virtual_columns/logs/column.tsx similarity index 76% rename from x-pack/plugins/observability_solution/logs_explorer/public/components/virtual_columns/column.tsx rename to src/plugins/discover/public/components/discover_grid/virtual_columns/logs/column.tsx index 9e1ad91079ace..b168478dd9388 100644 --- a/x-pack/plugins/observability_solution/logs_explorer/public/components/virtual_columns/column.tsx +++ b/src/plugins/discover/public/components/discover_grid/virtual_columns/logs/column.tsx @@ -1,14 +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. + * 2.0 and the Server Side Public License, v 1; you may not 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 { CustomGridColumnProps } from '@kbn/unified-data-table'; +import { CONTENT_FIELD, RESOURCE_FIELD } from '../../../../../common/data_types/logs/constants'; import { ContentColumnTooltip } from './column_tooltips/content_column_tooltip'; -import { CONTENT_FIELD, RESOURCE_FIELD } from '../../../common/constants'; import { ResourceColumnTooltip } from './column_tooltips/resource_column_tooltip'; export const renderColumn = diff --git a/x-pack/plugins/observability_solution/logs_explorer/public/components/virtual_columns/column_tooltips/content_column_tooltip.tsx b/src/plugins/discover/public/components/discover_grid/virtual_columns/logs/column_tooltips/content_column_tooltip.tsx similarity index 80% rename from x-pack/plugins/observability_solution/logs_explorer/public/components/virtual_columns/column_tooltips/content_column_tooltip.tsx rename to src/plugins/discover/public/components/discover_grid/virtual_columns/logs/column_tooltips/content_column_tooltip.tsx index df33f1f1beff3..948085f2d6e02 100644 --- a/x-pack/plugins/observability_solution/logs_explorer/public/components/virtual_columns/column_tooltips/content_column_tooltip.tsx +++ b/src/plugins/discover/public/components/discover_grid/virtual_columns/logs/column_tooltips/content_column_tooltip.tsx @@ -1,8 +1,9 @@ /* * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. */ import { EuiText, useEuiTheme } from '@elastic/eui'; @@ -13,10 +14,10 @@ import { contentHeaderTooltipParagraph1, contentHeaderTooltipParagraph2, contentLabel, -} from '../../common/translations'; +} from '../../../../data_types/logs/translations'; +import * as constants from '../../../../../../common/data_types/logs/constants'; import { TooltipButton } from './tooltip_button'; import { FieldWithToken } from './field_with_token'; -import * as constants from '../../../../common/constants'; export const ContentColumnTooltip = ({ column, headerRowHeight }: CustomGridColumnProps) => { const { euiTheme } = useEuiTheme(); diff --git a/src/plugins/discover/public/components/discover_grid/virtual_columns/logs/column_tooltips/field_with_token.tsx b/src/plugins/discover/public/components/discover_grid/virtual_columns/logs/column_tooltips/field_with_token.tsx new file mode 100644 index 0000000000000..abe5ed875e767 --- /dev/null +++ b/src/plugins/discover/public/components/discover_grid/virtual_columns/logs/column_tooltips/field_with_token.tsx @@ -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 { EuiFlexGroup, EuiFlexItem, EuiText, EuiToken } from '@elastic/eui'; +import React from 'react'; +import { css } from '@emotion/react'; +import { euiThemeVars } from '@kbn/ui-theme'; + +const spacingXsCss = css` + margin-bottom: ${euiThemeVars.euiSizeXS}; +`; + +export const FieldWithToken = ({ + field, + iconType = 'tokenKeyword', +}: { + field: string; + iconType?: string; +}) => { + return ( +
+ + + + + + + {field} + + + +
+ ); +}; diff --git a/src/plugins/discover/public/components/discover_grid/virtual_columns/logs/column_tooltips/hover_popover.tsx b/src/plugins/discover/public/components/discover_grid/virtual_columns/logs/column_tooltips/hover_popover.tsx new file mode 100644 index 0000000000000..100fb8b31a348 --- /dev/null +++ b/src/plugins/discover/public/components/discover_grid/virtual_columns/logs/column_tooltips/hover_popover.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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import React, { useEffect, useRef, useState } from 'react'; +import { EuiPopover, EuiPopoverTitle } from '@elastic/eui'; + +export const HoverPopover = ({ + children, + button, + title, +}: { + children: React.ReactChild; + button: React.ReactElement; + title: string; +}) => { + const [isPopoverOpen, setIsPopoverOpen] = useState(false); + const leaveTimer = useRef(null); + + const clearTimer = () => { + if (leaveTimer.current) { + clearTimeout(leaveTimer.current); + } + }; + + const onMouseEnter = () => { + clearTimer(); + setIsPopoverOpen(true); + }; + + const onMouseLeave = () => { + leaveTimer.current = setTimeout(() => setIsPopoverOpen(false), 100); + }; + + useEffect(() => { + return () => { + clearTimer(); + }; + }, []); + + return ( +
+ + {title} + {children} + +
+ ); +}; diff --git a/x-pack/plugins/observability_solution/logs_explorer/public/components/virtual_columns/column_tooltips/resource_column_tooltip.tsx b/src/plugins/discover/public/components/discover_grid/virtual_columns/logs/column_tooltips/resource_column_tooltip.tsx similarity index 77% rename from x-pack/plugins/observability_solution/logs_explorer/public/components/virtual_columns/column_tooltips/resource_column_tooltip.tsx rename to src/plugins/discover/public/components/discover_grid/virtual_columns/logs/column_tooltips/resource_column_tooltip.tsx index 64a64156cbaea..1ab50b08dcb1b 100644 --- a/x-pack/plugins/observability_solution/logs_explorer/public/components/virtual_columns/column_tooltips/resource_column_tooltip.tsx +++ b/src/plugins/discover/public/components/discover_grid/virtual_columns/logs/column_tooltips/resource_column_tooltip.tsx @@ -1,8 +1,9 @@ /* * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. */ import React from 'react'; @@ -10,9 +11,12 @@ import { css } from '@emotion/react'; import { EuiText } from '@elastic/eui'; import type { CustomGridColumnProps } from '@kbn/unified-data-table'; import { euiThemeVars } from '@kbn/ui-theme'; -import { resourceHeaderTooltipParagraph, resourceLabel } from '../../common/translations'; +import { + resourceHeaderTooltipParagraph, + resourceLabel, +} from '../../../../data_types/logs/translations'; +import * as constants from '../../../../../../common/data_types/logs/constants'; import { TooltipButton } from './tooltip_button'; -import * as constants from '../../../../common/constants'; import { FieldWithToken } from './field_with_token'; const spacingCSS = css` diff --git a/src/plugins/discover/public/components/discover_grid/virtual_columns/logs/column_tooltips/tooltip_button.tsx b/src/plugins/discover/public/components/discover_grid/virtual_columns/logs/column_tooltips/tooltip_button.tsx new file mode 100644 index 0000000000000..3f7d616be3014 --- /dev/null +++ b/src/plugins/discover/public/components/discover_grid/virtual_columns/logs/column_tooltips/tooltip_button.tsx @@ -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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import React, { useEffect, useRef, useState, useCallback, useMemo } from 'react'; +import { EuiIcon } from '@elastic/eui'; +import ColumnHeaderTruncateContainer from '@kbn/unified-data-table/src/components/column_header_truncate_container'; + +import { EuiPopover, EuiPopoverTitle } from '@elastic/eui'; + +export const TooltipButton = ({ + children, + popoverTitle, + displayText, + headerRowHeight, + iconType = 'questionInCircle', +}: { + children: React.ReactChild; + popoverTitle: string; + displayText?: string; + headerRowHeight?: number; + iconType?: string; +}) => { + const [isPopoverOpen, setIsPopoverOpen] = useState(false); + const leaveTimer = useRef(null); + + const clearTimer = useMemo( + () => () => { + if (leaveTimer.current) { + clearTimeout(leaveTimer.current); + } + }, + [] + ); + + const onMouseEnter = useCallback(() => { + clearTimer(); + setIsPopoverOpen(true); + }, [clearTimer]); + + const onMouseLeave = useCallback(() => { + leaveTimer.current = setTimeout(() => setIsPopoverOpen(false), 100); + }, []); + + useEffect(() => { + return () => { + clearTimer(); + }; + }, [clearTimer]); + + return ( + + {displayText}{' '} + + } + isOpen={isPopoverOpen} + anchorPosition="upCenter" + panelPaddingSize="s" + ownFocus={false} + > + {popoverTitle} + {children} + + + ); +}; diff --git a/x-pack/plugins/observability_solution/logs_explorer/public/components/virtual_columns/content.tsx b/src/plugins/discover/public/components/discover_grid/virtual_columns/logs/content.tsx similarity index 86% rename from x-pack/plugins/observability_solution/logs_explorer/public/components/virtual_columns/content.tsx rename to src/plugins/discover/public/components/discover_grid/virtual_columns/logs/content.tsx index b13cacec025f3..4be45b3d7d96f 100644 --- a/x-pack/plugins/observability_solution/logs_explorer/public/components/virtual_columns/content.tsx +++ b/src/plugins/discover/public/components/discover_grid/virtual_columns/logs/content.tsx @@ -1,8 +1,9 @@ /* * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. */ import React, { useMemo } from 'react'; @@ -18,8 +19,8 @@ import { import { i18n } from '@kbn/i18n'; import type { DataTableRecord } from '@kbn/discover-utils/src/types'; import { dynamic } from '@kbn/shared-ux-utility'; -import { LogLevel } from '../common/log_level'; -import * as constants from '../../../common/constants'; +import * as constants from '../../../../../common/data_types/logs/constants'; +import { LogLevel } from '../../../data_types/logs/log_level'; const SourceDocument = dynamic( () => import('@kbn/unified-data-table/src/components/source_document') @@ -38,10 +39,8 @@ const LogMessage = ({ field, value }: { field?: string; value: string }) => { const renderFieldPrefix = field && field !== constants.MESSAGE_FIELD; return ( - {renderFieldPrefix && ( - {field} - )} - + {renderFieldPrefix && {field}} + {value} @@ -59,7 +58,7 @@ const SourcePopoverContent = ({ }) => { const closeButton = ( )} diff --git a/x-pack/plugins/observability_solution/logs_explorer/public/components/virtual_columns/resource.tsx b/src/plugins/discover/public/components/discover_grid/virtual_columns/logs/resource.tsx similarity index 82% rename from x-pack/plugins/observability_solution/logs_explorer/public/components/virtual_columns/resource.tsx rename to src/plugins/discover/public/components/discover_grid/virtual_columns/logs/resource.tsx index 7cecdeee5ce40..84f95579af7b9 100644 --- a/x-pack/plugins/observability_solution/logs_explorer/public/components/virtual_columns/resource.tsx +++ b/src/plugins/discover/public/components/discover_grid/virtual_columns/logs/resource.tsx @@ -1,18 +1,19 @@ /* * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. */ import React from 'react'; import type { DataGridCellValueElementProps } from '@kbn/unified-data-table'; import { AgentName } from '@kbn/elastic-agent-utils'; import { dynamic } from '@kbn/shared-ux-utility'; -import { ChipWithPopover } from '../common/popover_chip'; -import * as constants from '../../../common/constants'; -import { getUnformattedResourceFields } from '../../utils/resource'; -import { LogDocument } from '../../../common/document'; +import { LogDocument } from '@kbn/discover-utils/src'; +import * as constants from '../../../../../common/data_types/logs/constants'; +import { getUnformattedResourceFields } from './utils/resource'; +import { ChipWithPopover } from '../../../data_types/logs/popover_chip'; const AgentIcon = dynamic(() => import('@kbn/custom-icons/src/components/agent_icon')); diff --git a/x-pack/plugins/observability_solution/logs_explorer/public/utils/resource.ts b/src/plugins/discover/public/components/discover_grid/virtual_columns/logs/utils/resource.ts similarity index 80% rename from x-pack/plugins/observability_solution/logs_explorer/public/utils/resource.ts rename to src/plugins/discover/public/components/discover_grid/virtual_columns/logs/utils/resource.ts index 1b1f3dd078008..7f6d3b5ed7dae 100644 --- a/x-pack/plugins/observability_solution/logs_explorer/public/utils/resource.ts +++ b/src/plugins/discover/public/components/discover_grid/virtual_columns/logs/utils/resource.ts @@ -1,13 +1,13 @@ /* * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. */ -import { LogDocument, ResourceFields } from '../../common/document'; -import * as constants from '../../common/constants'; -import { getFieldFromDoc } from './get_field_from_flattened_doc'; +import { getFieldFromDoc, LogDocument, ResourceFields } from '@kbn/discover-utils/src'; +import * as constants from '../../../../../../common/data_types/logs/constants'; export const getUnformattedResourceFields = (doc: LogDocument): ResourceFields => { const serviceName = getFieldFromDoc(doc, constants.SERVICE_NAME_FIELD); diff --git a/src/plugins/discover/public/customizations/customization_types/data_table_customisation.ts b/src/plugins/discover/public/customizations/customization_types/data_table_customisation.ts index 2ed371fd2109e..3e6e510488fbd 100644 --- a/src/plugins/discover/public/customizations/customization_types/data_table_customisation.ts +++ b/src/plugins/discover/public/customizations/customization_types/data_table_customisation.ts @@ -6,15 +6,10 @@ * Side Public License, v 1. */ -import { - CustomCellRenderer, - CustomControlColumnConfiguration, - CustomGridColumnsConfiguration, -} from '@kbn/unified-data-table'; +import { CustomControlColumnConfiguration } from '@kbn/unified-data-table'; export interface DataTableCustomization { id: 'data_table'; - customCellRenderer?: CustomCellRenderer; - customGridColumnsConfiguration?: CustomGridColumnsConfiguration; + logsEnabled: boolean; // TODO / NOTE: Just temporary until Discover's data type contextual awareness lands. customControlColumnsConfiguration?: CustomControlColumnConfiguration; } diff --git a/src/plugins/discover/public/customizations/customization_types/field_list_customisation.ts b/src/plugins/discover/public/customizations/customization_types/field_list_customisation.ts index 706022112e3fe..a43126a1aaaa3 100644 --- a/src/plugins/discover/public/customizations/customization_types/field_list_customisation.ts +++ b/src/plugins/discover/public/customizations/customization_types/field_list_customisation.ts @@ -6,12 +6,7 @@ * Side Public License, v 1. */ -import type { DataViewField } from '@kbn/data-views-plugin/common'; -import { FieldsGroup } from '@kbn/unified-field-list/src/types'; - export interface FieldListCustomization { id: 'field_list'; - additionalFieldGroups?: { - smartFields?: FieldsGroup['fields']; - }; + logsFieldsEnabled: boolean; // TODO / NOTE: Just temporary until Discover's data type contextual awareness lands. } diff --git a/src/plugins/discover/tsconfig.json b/src/plugins/discover/tsconfig.json index 8ea9e844d10a9..bf4c06f1c5dbe 100644 --- a/src/plugins/discover/tsconfig.json +++ b/src/plugins/discover/tsconfig.json @@ -84,9 +84,13 @@ "@kbn/shared-ux-markdown", "@kbn/data-view-utils", "@kbn/presentation-publishing", + "@kbn/elastic-agent-utils", + "@kbn/custom-icons", "@kbn/observability-ai-assistant-plugin", "@kbn/data-visualizer-plugin", - "@kbn/search-types" + "@kbn/search-types", + "@kbn/custom-icons", + "@kbn/observability-ai-assistant-plugin" ], "exclude": ["target/**/*"] } diff --git a/src/plugins/kibana_usage_collection/server/collectors/management/schema.ts b/src/plugins/kibana_usage_collection/server/collectors/management/schema.ts index fc4786dd5ca3f..9c4e025dd92b5 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/management/schema.ts +++ b/src/plugins/kibana_usage_collection/server/collectors/management/schema.ts @@ -627,6 +627,10 @@ export const stackManagementSchema: MakeSchemaFrom = { type: 'boolean', _meta: { description: 'Non-default value of setting.' }, }, + 'observability:enableInfrastructureContainerAssetView': { + type: 'boolean', + _meta: { description: 'Non-default value of setting.' }, + }, 'observability:enableInfrastructureProfilingIntegration': { type: 'boolean', _meta: { description: 'Non-default value of setting.' }, diff --git a/src/plugins/kibana_usage_collection/server/collectors/management/types.ts b/src/plugins/kibana_usage_collection/server/collectors/management/types.ts index bc1c315edae29..e3b84245ce3f0 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/management/types.ts +++ b/src/plugins/kibana_usage_collection/server/collectors/management/types.ts @@ -46,6 +46,7 @@ export interface UsageStats { 'observability:apmAWSLambdaPriceFactor': string; 'observability:apmAWSLambdaRequestCostPerMillion': number; 'observability:enableInfrastructureHostsView': boolean; + 'observability:enableInfrastructureContainerAssetView': boolean; 'observability:enableInfrastructureProfilingIntegration': boolean; 'observability:enableInfrastructureAssetCustomDashboards': boolean; 'observability:apmAgentExplorerView': boolean; diff --git a/src/plugins/telemetry/schema/oss_plugins.json b/src/plugins/telemetry/schema/oss_plugins.json index 717e5ebabbe1b..673361881b2ff 100644 --- a/src/plugins/telemetry/schema/oss_plugins.json +++ b/src/plugins/telemetry/schema/oss_plugins.json @@ -10404,6 +10404,12 @@ "description": "Non-default value of setting." } }, + "observability:enableInfrastructureContainerAssetView":{ + "type": "boolean", + "_meta": { + "description": "Non-default value of setting." + } + }, "observability:enableInfrastructureProfilingIntegration": { "type": "boolean", "_meta": { diff --git a/src/plugins/unified_doc_viewer/public/components/doc_viewer_source/get_height.test.tsx b/src/plugins/unified_doc_viewer/public/components/doc_viewer_source/get_height.test.tsx index 6c6ae2852e053..e28df4d89d5bc 100644 --- a/src/plugins/unified_doc_viewer/public/components/doc_viewer_source/get_height.test.tsx +++ b/src/plugins/unified_doc_viewer/public/components/doc_viewer_source/get_height.test.tsx @@ -8,6 +8,7 @@ import { monaco } from '@kbn/monaco'; import { getHeight } from './get_height'; +import { MARGIN_BOTTOM } from './source'; describe('getHeight', () => { Object.defineProperty(window, 'innerHeight', { writable: true, configurable: true, value: 500 }); @@ -32,7 +33,7 @@ describe('getHeight', () => { const monacoMock = getMonacoMock(500, 0); const height = getHeight(monacoMock, true); - expect(height).toBe(475); + expect(height).toBe(500 - MARGIN_BOTTOM); }); test('when using document explorer, returning the available height in the flyout has a minimun guarenteed height', () => { diff --git a/src/plugins/unified_doc_viewer/public/components/doc_viewer_source/source.tsx b/src/plugins/unified_doc_viewer/public/components/doc_viewer_source/source.tsx index 13f2ee065f504..740afc99a9c62 100644 --- a/src/plugins/unified_doc_viewer/public/components/doc_viewer_source/source.tsx +++ b/src/plugins/unified_doc_viewer/public/components/doc_viewer_source/source.tsx @@ -36,7 +36,7 @@ interface SourceViewerProps { // inline limitation was necessary to enable virtualized scrolling, which improves performance export const MAX_LINES_CLASSIC_TABLE = 500; // Displayed margin of the code editor to the window bottom when rendered in the document explorer flyout -export const MARGIN_BOTTOM = 25; +export const MARGIN_BOTTOM = 80; // DocViewer flyout has a footer // Minimum height for the source content to guarantee minimum space when the flyout is scrollable. export const MIN_HEIGHT = 400; diff --git a/test/api_integration/apis/data_views/fields_route/cache.ts b/test/api_integration/apis/data_views/fields_route/cache.ts index c97be4b7411f3..dea14dec6bdcd 100644 --- a/test/api_integration/apis/data_views/fields_route/cache.ts +++ b/test/api_integration/apis/data_views/fields_route/cache.ts @@ -70,7 +70,7 @@ export default function ({ getService }: FtrProviderContext) { await supertest .get(FIELDS_PATH) - .set('If-None-Match', response.get('etag')) + .set('If-None-Match', response.get('etag')!) .query({ pattern: '*', include_unmapped: true, diff --git a/test/api_integration/apis/saved_objects_management/scroll_count.ts b/test/api_integration/apis/saved_objects_management/scroll_count.ts index 94e301a085d70..26f4f4e1a626e 100644 --- a/test/api_integration/apis/saved_objects_management/scroll_count.ts +++ b/test/api_integration/apis/saved_objects_management/scroll_count.ts @@ -6,7 +6,6 @@ * Side Public License, v 1. */ -import { SuperTest, Test } from 'supertest'; import expect from '@kbn/expect'; import { FtrProviderContext } from '../../ftr_provider_context'; @@ -14,7 +13,7 @@ const apiUrl = '/api/kibana/management/saved_objects/scroll/counts'; const defaultTypes = ['visualization', 'index-pattern', 'search', 'dashboard']; export default function ({ getService }: FtrProviderContext) { - const supertest = getService('supertest') as SuperTest; + const supertest = getService('supertest'); const kibanaServer = getService('kibanaServer'); const esArchiver = getService('esArchiver'); diff --git a/test/api_integration/apis/telemetry/opt_in.ts b/test/api_integration/apis/telemetry/opt_in.ts index c7d8a42c6e392..a9fc5861368ca 100644 --- a/test/api_integration/apis/telemetry/opt_in.ts +++ b/test/api_integration/apis/telemetry/opt_in.ts @@ -87,7 +87,7 @@ export default function optInTest({ getService }: FtrProviderContext) { } async function postTelemetryV2OptIn( - supertest: SuperTest.SuperTest, + supertest: SuperTest.Agent, value: unknown, statusCode: number ): Promise { diff --git a/test/api_integration/services/supertest.ts b/test/api_integration/services/supertest.ts index baf42703c64a0..d8ce0d918c45a 100644 --- a/test/api_integration/services/supertest.ts +++ b/test/api_integration/services/supertest.ts @@ -13,13 +13,15 @@ import { format as formatUrl } from 'url'; import supertest from 'supertest'; import { FtrProviderContext } from '../../functional/ftr_provider_context'; -export function KibanaSupertestProvider({ getService }: FtrProviderContext) { +export function KibanaSupertestProvider({ getService }: FtrProviderContext): supertest.Agent { const config = getService('config'); const kibanaServerUrl = formatUrl(config.get('servers.kibana')); return supertest(kibanaServerUrl); } -export function ElasticsearchSupertestProvider({ getService }: FtrProviderContext) { +export function ElasticsearchSupertestProvider({ + getService, +}: FtrProviderContext): supertest.Agent { const config = getService('config'); const esServerConfig = config.get('servers.elasticsearch'); diff --git a/test/common/services/bsearch.ts b/test/common/services/bsearch.ts index fd79a9b9a75e8..fd9ef7f703a0b 100644 --- a/test/common/services/bsearch.ts +++ b/test/common/services/bsearch.ts @@ -40,7 +40,7 @@ const getSpaceUrlPrefix = (spaceId?: string): string => { * Options for the send method */ interface SendOptions { - supertest: SuperTest.SuperTest; + supertest: SuperTest.Agent; options: object; strategy: string; space?: string; diff --git a/test/package/Vagrantfile b/test/package/Vagrantfile index ea7e87d74b785..b8c24d02c8eba 100644 --- a/test/package/Vagrantfile +++ b/test/package/Vagrantfile @@ -46,14 +46,7 @@ Vagrant.configure("2") do |config| vb.memory = 4096 vb.cpus = 2 end - fips.vm.box = 'generic/rhel9' - fips.vm.provision "shell", inline: <<-SHELL - echo "export OPENSSL_MODULES=/usr/local/lib64/ossl-modules" >> /etc/profile.d/kibana-fips-env.sh - echo "export TEST_BROWSER_HEADLESS=1" >> /etc/profile.d/kibana-fips-env.sh - echo "export ES_TMPDIR=/home/vagrant/kibana/.es/tmp" >> /etc/profile.d/kibana-fips-env.sh - # Remove after https://github.com/elastic/kibana-operations/issues/96 - echo "export FTR_FIPS_MODE=1" >> /etc/profile.d/kibana-fips-env.sh - SHELL + fips.vm.box = 'ubuntu/jammy64' fips.vm.provision "ansible" do |ansible| ansible.playbook = "fips.yml" end diff --git a/test/package/fips.yml b/test/package/fips.yml index ae62b386c0cde..6682e32b0f6be 100644 --- a/test/package/fips.yml +++ b/test/package/fips.yml @@ -6,7 +6,9 @@ nvm_ver: "0.39.7" openssl_sha: "sha256:6c13d2bf38fdf31eac3ce2a347073673f5d63263398f1f69d0df4a41253e4b3e" openssl_ver: "3.0.8" + openssl_src_path: "{{ kibana_dist_path }}/openssl-{{ openssl_ver }}" + openssl_path: "{{ kibana_dist_path }}/openssl" roles: - - upgrade_yum_packages + - upgrade_apt_packages - install_kibana_fips - assert_fips_enabled diff --git a/test/package/roles/assert_fips_enabled/tasks/main.yml b/test/package/roles/assert_fips_enabled/tasks/main.yml index 936d43c49026a..74ebe283673cb 100644 --- a/test/package/roles/assert_fips_enabled/tasks/main.yml +++ b/test/package/roles/assert_fips_enabled/tasks/main.yml @@ -1,5 +1,7 @@ - name: register kibana node getFips - command: "{{ kibana_dist_path }}/node/bin/node --enable-fips --openssl-config={{ kibana_dist_path }}/config/nodejs.cnf -p 'crypto.getFips()'" + shell: + cmd: "source /home/vagrant/.profile && {{ kibana_dist_path }}/node/bin/node --enable-fips --openssl-config={{ kibana_dist_path }}/config/nodejs.cnf -p 'crypto.getFips()'" + executable: /bin/bash register: kibana_node_fips - debug: diff --git a/test/package/roles/install_kibana_fips/tasks/main.yml b/test/package/roles/install_kibana_fips/tasks/main.yml index 3bfe729f73bd1..49376106171bd 100644 --- a/test/package/roles/install_kibana_fips/tasks/main.yml +++ b/test/package/roles/install_kibana_fips/tasks/main.yml @@ -6,18 +6,37 @@ - "processor_cores" when: ansible_processor_vcpus is not defined -- name: fix /var/log permissions for kibana +- name: setup env variables + blockinfile: + path: "/home/vagrant/.profile" + block: | + export OPENSSL_MODULES=/usr/share/kibana/openssl/lib/ossl-modules + export TEST_BROWSER_HEADLESS=1 + export FTR_DISABLE_ES_TMPDIR=true + owner: vagrant + group: vagrant + mode: '0644' + +- name: add chrome apt signing key become: yes - file: - path: /var/log - state: directory - recurse: true - mode: "0777" + apt_key: + url: https://dl.google.com/linux/linux_signing_key.pub + state: present -- name: create tmp dir for ES - file: - path: "{{ kibana_src_path }}/.es/tmp" - state: directory +- name: add chrome apt repository + become: yes + apt_repository: + repo: deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main + state: present + +- name: install apt packages + become: yes + apt: + pkg: + - build-essential + - google-chrome-stable + - unzip + state: latest - name: slurp kibana node version slurp: @@ -31,7 +50,7 @@ - name: install nvm shell: chdir: "$HOME" - cmd: curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v{{ nvm_ver }}/install.sh | bash + cmd: curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v{{ nvm_ver }}/install.sh | PROFILE=/home/vagrant/.profile bash - name: install kibana node version shell: @@ -40,12 +59,11 @@ args: executable: /bin/bash -- name: "ensure {{ kibana_dist_path }} dir exists" +- name: "ensure {{ openssl_path }} dir exists" become: yes file: - path: "{{ kibana_dist_path }}" + path: "{{ openssl_path }}" state: directory - mode: "0777" - name: find kibana distribution find: @@ -99,35 +117,54 @@ delay: 10 get_url: url: "https://www.openssl.org/source/openssl-{{ openssl_ver }}.tar.gz" - dest: "{{ kibana_dist_path }}/openssl-{{ openssl_ver }}.tar.gz" + dest: "{{ openssl_src_path }}.tar.gz" checksum: "{{ openssl_sha }}" - name: extract OpenSSL become: yes unarchive: - src: "{{ kibana_dist_path }}/openssl-{{ openssl_ver }}.tar.gz" + src: "{{ openssl_src_path }}.tar.gz" dest: "{{ kibana_dist_path }}" remote_src: yes - name: configure OpenSSL for FIPS become: yes shell: - chdir: "{{ kibana_dist_path }}/openssl-{{ openssl_ver }}" - cmd: ./Configure enable-fips + chdir: "{{ openssl_src_path }}" + cmd: "./Configure --prefix={{ openssl_path }} --openssldir={{ openssl_path }}/ssl --libdir={{ openssl_path }}/lib enable-fips" - name: compile OpenSSL with FIPS become: yes make: - chdir: "{{ kibana_dist_path }}/openssl-{{ openssl_ver }}" + chdir: "{{ openssl_src_path }}" jobs: "{{ ansible_facts['processor_vcpus'] }}" - name: install OpenSSL with FIPS become: yes make: - chdir: "{{ kibana_dist_path }}/openssl-{{ openssl_ver }}" + chdir: "{{ openssl_src_path }}" target: install -- name: link OpenSSL package +- name: "change owner of {{ kibana_dist_path }} to vagrant" become: yes - shell: - cmd: ldconfig /usr/local/lib64/ + file: + path: "{{ kibana_dist_path }}" + owner: vagrant + group: vagrant + recurse: yes + +- name: fix /var/log permissions for kibana + become: yes + file: + path: /var/log + state: directory + recurse: true + mode: "0777" + +- name: increase vm.max_map_count for ES + become: yes + sysctl: + name: vm.max_map_count + value: '262144' + state: present + reload: yes \ No newline at end of file diff --git a/test/package/templates/fips/nodejs.cnf b/test/package/templates/fips/nodejs.cnf index bd8fece6674d7..f4f3a076975eb 100644 --- a/test/package/templates/fips/nodejs.cnf +++ b/test/package/templates/fips/nodejs.cnf @@ -9,7 +9,7 @@ ########################################################################## nodejs_conf = nodejs_init -.include /usr/local/ssl/fipsmodule.cnf +.include /usr/share/kibana/openssl/ssl/fipsmodule.cnf [nodejs_init] providers = provider_sect diff --git a/tsconfig.base.json b/tsconfig.base.json index f87d111ac27af..dd82d55b1b0ad 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -774,6 +774,8 @@ "@kbn/encrypted-saved-objects-plugin/*": ["x-pack/plugins/encrypted_saved_objects/*"], "@kbn/enterprise-search-plugin": ["x-pack/plugins/enterprise_search"], "@kbn/enterprise-search-plugin/*": ["x-pack/plugins/enterprise_search/*"], + "@kbn/entities-schema": ["x-pack/packages/kbn-entities-schema"], + "@kbn/entities-schema/*": ["x-pack/packages/kbn-entities-schema/*"], "@kbn/error-boundary-example-plugin": ["examples/error_boundary"], "@kbn/error-boundary-example-plugin/*": ["examples/error_boundary/*"], "@kbn/es": ["packages/kbn-es"], diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/use_assistant_overlay/index.test.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/use_assistant_overlay/index.test.tsx index c49db8d6246a3..9e21d9da57d74 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/use_assistant_overlay/index.test.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/use_assistant_overlay/index.test.tsx @@ -92,6 +92,7 @@ describe('useAssistantOverlay', () => { const id = 'test-id'; const suggestedUserPrompt = 'test user prompt'; const tooltip = 'test tooltip'; + const isAssistantAvailable = true; renderHook(() => useAssistantOverlay( @@ -101,7 +102,8 @@ describe('useAssistantOverlay', () => { getPromptContext, id, suggestedUserPrompt, - tooltip + tooltip, + isAssistantAvailable ) ); @@ -118,6 +120,7 @@ describe('useAssistantOverlay', () => { }); it('calls unRegisterPromptContext on unmount', () => { + const isAssistantAvailable = true; const { unmount } = renderHook(() => useAssistantOverlay( 'event', @@ -126,7 +129,8 @@ describe('useAssistantOverlay', () => { () => Promise.resolve('data'), 'id', null, - 'tooltip' + 'tooltip', + isAssistantAvailable ) ); @@ -136,6 +140,7 @@ describe('useAssistantOverlay', () => { }); it('calls `showAssistantOverlay` from the assistant context', () => { + const isAssistantAvailable = true; const { result } = renderHook(() => useAssistantOverlay( 'event', @@ -144,7 +149,8 @@ describe('useAssistantOverlay', () => { () => Promise.resolve('data'), 'id', null, - 'tooltip' + 'tooltip', + isAssistantAvailable ) ); diff --git a/x-pack/packages/kbn-elastic-assistant/impl/assistant/use_assistant_overlay/index.tsx b/x-pack/packages/kbn-elastic-assistant/impl/assistant/use_assistant_overlay/index.tsx index 8b8a399bc7671..3396223d192ca 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/assistant/use_assistant_overlay/index.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/assistant/use_assistant_overlay/index.tsx @@ -74,6 +74,9 @@ export const useAssistantOverlay = ( */ tooltip: PromptContext['tooltip'], + /** Required to identify the availability of the Assistant for the current license level */ + isAssistantEnabled: boolean, + /** * Optionally provide a map of replacements associated with the context, i.e. replacements for an attack discovery that's provided as context */ @@ -96,7 +99,7 @@ export const useAssistantOverlay = ( const { data: conversations, isLoading } = useFetchCurrentUserConversations({ http, onFetch: onFetchedConversations, - isAssistantEnabled: true, + isAssistantEnabled, }); // memoize the props so that we can use them in the effect below: @@ -135,7 +138,7 @@ export const useAssistantOverlay = ( : undefined; } - if (!conversation && defaultConnector && !isLoading) { + if (isAssistantEnabled && !conversation && defaultConnector && !isLoading) { try { conversation = await createConversation({ apiConfig: { @@ -166,6 +169,7 @@ export const useAssistantOverlay = ( conversations, createConversation, defaultConnector, + isAssistantEnabled, isLoading, promptContextId, ] diff --git a/x-pack/packages/kbn-elastic-assistant/impl/new_chat/index.test.tsx b/x-pack/packages/kbn-elastic-assistant/impl/new_chat/index.test.tsx index 6850c84bf67b4..730c88413833d 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/new_chat/index.test.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/new_chat/index.test.tsx @@ -23,6 +23,7 @@ const defaultProps: Props = { description: 'Test description', getPromptContext: () => Promise.resolve('Test prompt context'), tooltip: 'Test tooltip', + isAssistantEnabled: true, }; describe('NewChat', () => { @@ -38,6 +39,14 @@ describe('NewChat', () => { expect(newChatButton.querySelector('[data-euiicon-type="discuss"]')).toBeInTheDocument(); }); + it('renders the default New Chat button even if the Assistant is disabled', () => { + render(); + + const newChatButton = screen.getByTestId('newChat'); + + expect(newChatButton.querySelector('[data-euiicon-type="discuss"]')).toBeInTheDocument(); + }); + it('renders the default "New Chat" text when children are NOT provided', () => { render(); diff --git a/x-pack/packages/kbn-elastic-assistant/impl/new_chat/index.tsx b/x-pack/packages/kbn-elastic-assistant/impl/new_chat/index.tsx index 3fd798f38c4b9..a4793dfd25a9d 100644 --- a/x-pack/packages/kbn-elastic-assistant/impl/new_chat/index.tsx +++ b/x-pack/packages/kbn-elastic-assistant/impl/new_chat/index.tsx @@ -23,6 +23,8 @@ export type Props = Omit & { promptContextId?: string; /** Optionally specify color of empty button */ color?: 'text' | 'accent' | 'primary' | 'success' | 'warning' | 'danger'; + /** Required to identify the availability of the Assistant for the current license level */ + isAssistantEnabled: boolean; }; const NewChatComponent: React.FC = ({ @@ -36,6 +38,7 @@ const NewChatComponent: React.FC = ({ promptContextId, suggestedUserPrompt, tooltip, + isAssistantEnabled, }) => { const { showAssistantOverlay } = useAssistantOverlay( category, @@ -44,7 +47,8 @@ const NewChatComponent: React.FC = ({ getPromptContext, promptContextId ?? null, suggestedUserPrompt, - tooltip + tooltip, + isAssistantEnabled ); const showOverlay = useCallback(() => { diff --git a/x-pack/packages/kbn-entities-schema/README.md b/x-pack/packages/kbn-entities-schema/README.md new file mode 100644 index 0000000000000..2601be6543c58 --- /dev/null +++ b/x-pack/packages/kbn-entities-schema/README.md @@ -0,0 +1,3 @@ +# @kbn/entities-schema + +The entities schema for the asset model for Observability \ No newline at end of file diff --git a/x-pack/packages/kbn-entities-schema/index.ts b/x-pack/packages/kbn-entities-schema/index.ts new file mode 100644 index 0000000000000..92b93b7938125 --- /dev/null +++ b/x-pack/packages/kbn-entities-schema/index.ts @@ -0,0 +1,10 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export * from './src/schema/entity_definition'; +export * from './src/schema/entity'; +export * from './src/schema/common'; diff --git a/x-pack/packages/kbn-entities-schema/jest.config.js b/x-pack/packages/kbn-entities-schema/jest.config.js new file mode 100644 index 0000000000000..1d10119431ec3 --- /dev/null +++ b/x-pack/packages/kbn-entities-schema/jest.config.js @@ -0,0 +1,12 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +module.exports = { + preset: '@kbn/test', + rootDir: '../../..', + roots: ['/x-pack/packages/kbn-entities-schema'], +}; diff --git a/x-pack/packages/kbn-entities-schema/kibana.jsonc b/x-pack/packages/kbn-entities-schema/kibana.jsonc new file mode 100644 index 0000000000000..9895c2074a584 --- /dev/null +++ b/x-pack/packages/kbn-entities-schema/kibana.jsonc @@ -0,0 +1,5 @@ +{ + "type": "shared-common", + "id": "@kbn/entities-schema", + "owner": "@elastic/obs-knowledge-team" +} diff --git a/x-pack/packages/kbn-entities-schema/package.json b/x-pack/packages/kbn-entities-schema/package.json new file mode 100644 index 0000000000000..0be44d9d75055 --- /dev/null +++ b/x-pack/packages/kbn-entities-schema/package.json @@ -0,0 +1,6 @@ +{ + "name": "@kbn/entities-schema", + "private": true, + "version": "1.0.0", + "license": "Elastic License 2.0" +} \ No newline at end of file diff --git a/x-pack/packages/kbn-entities-schema/src/schema/common.ts b/x-pack/packages/kbn-entities-schema/src/schema/common.ts new file mode 100644 index 0000000000000..6b4f0cc794c2b --- /dev/null +++ b/x-pack/packages/kbn-entities-schema/src/schema/common.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 { z } from 'zod'; +import moment from 'moment'; + +export enum EntityType { + service = 'service', + host = 'host', + pod = 'pod', + node = 'node', +} + +export const arrayOfStringsSchema = z.array(z.string()); + +export const entityTypeSchema = z.nativeEnum(EntityType); + +export enum BasicAggregations { + avg = 'avg', + max = 'max', + min = 'min', + sum = 'sum', + cardinality = 'cardinality', + last_value = 'last_value', + std_deviation = 'std_deviation', +} + +export const basicAggregationsSchema = z.nativeEnum(BasicAggregations); + +const metricNameSchema = z + .string() + .length(1) + .regex(/[a-zA-Z]/) + .toUpperCase(); + +export const filterSchema = z.optional(z.string()); + +export const basicMetricWithFieldSchema = z.object({ + name: metricNameSchema, + aggregation: basicAggregationsSchema, + field: z.string(), + filter: filterSchema, +}); + +export const docCountMetricSchema = z.object({ + name: metricNameSchema, + aggregation: z.literal('doc_count'), + filter: filterSchema, +}); + +export const durationSchema = z + .string() + .regex(/\d+[m|d|s|h]/) + .transform((val: string) => { + const parts = val.match(/(\d+)([m|s|h|d])/); + if (parts === null) { + throw new Error('Unable to parse duration'); + } + const value = parseInt(parts[1], 10); + const unit = parts[2] as 'm' | 's' | 'h' | 'd'; + const duration = moment.duration(value, unit); + return { ...duration, toJSON: () => val }; + }); + +export const percentileMetricSchema = z.object({ + name: metricNameSchema, + aggregation: z.literal('percentile'), + field: z.string(), + percentile: z.number(), + filter: filterSchema, +}); + +export const metricSchema = z.discriminatedUnion('aggregation', [ + basicMetricWithFieldSchema, + docCountMetricSchema, + percentileMetricSchema, +]); + +export type Metric = z.infer; + +export const keyMetricSchema = z.object({ + name: z.string(), + metrics: z.array(metricSchema), + equation: z.string(), +}); + +export type KeyMetric = z.infer; + +export const metadataSchema = z + .object({ + source: z.string(), + destination: z.optional(z.string()), + limit: z.optional(z.number().default(1000)), + }) + .or(z.string().transform((value) => ({ source: value, destination: value, limit: 1000 }))); + +export const identityFieldsSchema = z + .object({ + field: z.string(), + optional: z.boolean(), + }) + .or(z.string().transform((value) => ({ field: value, optional: false }))); diff --git a/x-pack/packages/kbn-entities-schema/src/schema/entity.ts b/x-pack/packages/kbn-entities-schema/src/schema/entity.ts new file mode 100644 index 0000000000000..514ed01494036 --- /dev/null +++ b/x-pack/packages/kbn-entities-schema/src/schema/entity.ts @@ -0,0 +1,21 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { z } from 'zod'; +import { arrayOfStringsSchema } from './common'; + +export const entitySchema = z.intersection( + z.object({ + entity: z.object({ + id: z.string(), + indexPatterns: arrayOfStringsSchema, + identityFields: arrayOfStringsSchema, + metric: z.record(z.string(), z.number()), + }), + }), + z.record(z.string(), z.string().or(z.number())) +); diff --git a/x-pack/packages/kbn-entities-schema/src/schema/entity_definition.ts b/x-pack/packages/kbn-entities-schema/src/schema/entity_definition.ts new file mode 100644 index 0000000000000..48b8c8060efbc --- /dev/null +++ b/x-pack/packages/kbn-entities-schema/src/schema/entity_definition.ts @@ -0,0 +1,42 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { z } from 'zod'; +import { + arrayOfStringsSchema, + entityTypeSchema, + keyMetricSchema, + metadataSchema, + filterSchema, + durationSchema, + identityFieldsSchema, +} from './common'; + +export const entityDefinitionSchema = z.object({ + id: z.string().regex(/^[\w-]+$/), + name: z.string(), + description: z.optional(z.string()), + type: entityTypeSchema, + filter: filterSchema, + indexPatterns: arrayOfStringsSchema, + identityFields: z.array(identityFieldsSchema), + identityTemplate: z.string(), + metadata: z.optional(z.array(metadataSchema)), + metrics: z.optional(z.array(keyMetricSchema)), + staticFields: z.optional(z.record(z.string(), z.string())), + lookback: durationSchema, + timestampField: z.string(), + settings: z.optional( + z.object({ + syncField: z.optional(z.string()), + syncDelay: z.optional(z.string()), + frequency: z.optional(z.string()), + }) + ), +}); + +export type EntityDefinition = z.infer; diff --git a/x-pack/packages/kbn-entities-schema/tsconfig.json b/x-pack/packages/kbn-entities-schema/tsconfig.json new file mode 100644 index 0000000000000..f722f3587e7a2 --- /dev/null +++ b/x-pack/packages/kbn-entities-schema/tsconfig.json @@ -0,0 +1,18 @@ +{ + "extends": "../../../tsconfig.base.json", + "compilerOptions": { + "outDir": "target/types", + "types": [ + "jest", + "node" + ] + }, + "include": [ + "**/*.ts" + ], + "exclude": [ + "target/**/*" + ], + "kbn_references": [ + ] +} diff --git a/x-pack/packages/kbn-slo-schema/src/rest_specs/routes/fetch_historical_summary.ts b/x-pack/packages/kbn-slo-schema/src/rest_specs/routes/fetch_historical_summary.ts index 0df546beecc4c..7912c3ccbedc1 100644 --- a/x-pack/packages/kbn-slo-schema/src/rest_specs/routes/fetch_historical_summary.ts +++ b/x-pack/packages/kbn-slo-schema/src/rest_specs/routes/fetch_historical_summary.ts @@ -14,6 +14,7 @@ import { import { allOrAnyString, allOrAnyStringOrArray, + dateRangeSchema, dateType, summarySchema, } from '../../schema/common'; @@ -33,10 +34,7 @@ const fetchHistoricalSummaryParamsSchema = t.type({ }), t.partial({ remoteName: t.string, - range: t.type({ - from: t.string, - to: t.string, - }), + range: dateRangeSchema, }), ]) ), diff --git a/x-pack/packages/kbn-slo-schema/src/rest_specs/routes/get_preview_data.ts b/x-pack/packages/kbn-slo-schema/src/rest_specs/routes/get_preview_data.ts index 9cc0023704453..aa46600cb3442 100644 --- a/x-pack/packages/kbn-slo-schema/src/rest_specs/routes/get_preview_data.ts +++ b/x-pack/packages/kbn-slo-schema/src/rest_specs/routes/get_preview_data.ts @@ -13,8 +13,8 @@ const getPreviewDataParamsSchema = t.type({ t.type({ indicator: indicatorSchema, range: t.type({ - start: t.number, - end: t.number, + from: dateType, + to: dateType, }), }), t.partial({ diff --git a/x-pack/packages/kbn-slo-schema/src/schema/common.ts b/x-pack/packages/kbn-slo-schema/src/schema/common.ts index a803bcf735796..e2b6d5af0a023 100644 --- a/x-pack/packages/kbn-slo-schema/src/schema/common.ts +++ b/x-pack/packages/kbn-slo-schema/src/schema/common.ts @@ -87,8 +87,8 @@ const groupSummarySchema = t.type({ }); const dateRangeSchema = t.type({ - from: t.union([dateType, t.string]), - to: t.union([dateType, t.string]), + from: dateType, + to: dateType, }); export { diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/tabs/incompatible_tab/index.tsx b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/tabs/incompatible_tab/index.tsx index e1b1bdfc9a403..aa6866555a3b3 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/tabs/incompatible_tab/index.tsx +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/tabs/incompatible_tab/index.tsx @@ -145,18 +145,17 @@ const IncompatibleTabComponent: React.FC = ({ - {isAssistantEnabled && ( - - - - )} + + + diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/tabs/summary_tab/callout_summary/index.tsx b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/tabs/summary_tab/callout_summary/index.tsx index d9403b7159e9f..aa32baafecf19 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/tabs/summary_tab/callout_summary/index.tsx +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/data_quality_panel/tabs/summary_tab/callout_summary/index.tsx @@ -138,18 +138,17 @@ const CalloutSummaryComponent: React.FC = ({ - {isAssistantEnabled && ( - - - - )} + + + diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/helpers.test.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/helpers.test.ts index 48a83974ba94d..8cec06b28d3a3 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/helpers.test.ts +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/helpers.test.ts @@ -1483,10 +1483,9 @@ describe('helpers', () => { }); expect(fetch).toHaveBeenCalledWith( - '/internal/ecs_data_quality_dashboard/results', + '/internal/ecs_data_quality_dashboard/results/indices_latest/auditbeat-*', expect.objectContaining({ method: 'GET', - query: { pattern: 'auditbeat-*' }, }) ); }); diff --git a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/helpers.ts b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/helpers.ts index 368a1d62ac72e..c34f8e35ed289 100644 --- a/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/helpers.ts +++ b/x-pack/packages/security-solution/ecs_data_quality_dashboard/impl/data_quality/helpers.ts @@ -457,6 +457,8 @@ export const getErrorSummaries = ( }; export const RESULTS_API_ROUTE = '/internal/ecs_data_quality_dashboard/results'; +export const RESULTS_INDICES_LATEST_ROUTE = + '/internal/ecs_data_quality_dashboard/results/indices_latest/{pattern}'; export interface StorageResult { batchId: string; @@ -565,11 +567,11 @@ export async function getStorageResults({ abortController: AbortController; }): Promise { try { - const results = await httpFetch(RESULTS_API_ROUTE, { + const route = RESULTS_INDICES_LATEST_ROUTE.replace('{pattern}', pattern); + const results = await httpFetch(route, { method: 'GET', signal: abortController.signal, version: INTERNAL_API_VERSION, - query: { pattern }, }); return results; } catch (err) { diff --git a/x-pack/plugins/actions/server/index.ts b/x-pack/plugins/actions/server/index.ts index 39b94204520b7..ef1c277ff049b 100644 --- a/x-pack/plugins/actions/server/index.ts +++ b/x-pack/plugins/actions/server/index.ts @@ -33,6 +33,7 @@ export { asSavedObjectExecutionSource, asHttpRequestExecutionSource, asNotificationExecutionSource, + getBasicAuthHeader, } from './lib'; export { ACTION_SAVED_OBJECT_TYPE } from './constants/saved_objects'; diff --git a/x-pack/plugins/actions/server/lib/axios_utils.test.ts b/x-pack/plugins/actions/server/lib/axios_utils.test.ts index 43f16b4863e9a..c5e23f6cd3db3 100644 --- a/x-pack/plugins/actions/server/lib/axios_utils.test.ts +++ b/x-pack/plugins/actions/server/lib/axios_utils.test.ts @@ -339,6 +339,55 @@ describe('request', () => { `"Do not use \\"baseURL\\" in the creation of your axios instance because you will mostly break proxy"` ); }); + + test('it converts the auth property to basic auth header', async () => { + await request({ + axios, + url: '/test', + logger, + configurationUtilities, + auth: { username: 'username', password: 'password' }, + }); + + expect(axiosMock).toHaveBeenCalledWith('/test', { + method: 'get', + httpAgent: undefined, + httpsAgent: expect.any(HttpsAgent), + proxy: false, + maxContentLength: 1000000, + timeout: 360000, + headers: { Authorization: `Basic ${Buffer.from('username:password').toString('base64')}` }, + }); + }); + + test('it does not override an authorization header if provided', async () => { + await request({ + axios, + url: '/test', + logger, + configurationUtilities, + auth: { username: 'username', password: 'password' }, + headers: { + 'Content-Type': 'application/json', + 'X-Test-Header': 'test', + Authorization: 'Bearer my_token', + }, + }); + + expect(axiosMock).toHaveBeenCalledWith('/test', { + method: 'get', + httpAgent: undefined, + httpsAgent: expect.any(HttpsAgent), + proxy: false, + maxContentLength: 1000000, + timeout: 360000, + headers: { + 'Content-Type': 'application/json', + 'X-Test-Header': 'test', + Authorization: 'Bearer my_token', + }, + }); + }); }); describe('patch', () => { diff --git a/x-pack/plugins/actions/server/lib/axios_utils.ts b/x-pack/plugins/actions/server/lib/axios_utils.ts index b623f427be681..3852f2a33755b 100644 --- a/x-pack/plugins/actions/server/lib/axios_utils.ts +++ b/x-pack/plugins/actions/server/lib/axios_utils.ts @@ -18,6 +18,7 @@ import { Logger } from '@kbn/core/server'; import { getCustomAgents } from './get_custom_agents'; import { ActionsConfigurationUtilities } from '../actions_config'; import { SSLSettings } from '../types'; +import { combineHeadersWithBasicAuthHeader } from './get_basic_auth_header'; export const request = async ({ axios, @@ -55,10 +56,18 @@ export const request = async ({ const { maxContentLength, timeout: settingsTimeout } = configurationUtilities.getResponseSettings(); + const { auth, ...restConfig } = config; + + const headersWithBasicAuth = combineHeadersWithBasicAuthHeader({ + username: auth?.username, + password: auth?.password, + headers, + }); + return await axios(url, { - ...config, + ...restConfig, method, - headers, + headers: headersWithBasicAuth, ...(data ? { data } : {}), // use httpAgent and httpsAgent and set axios proxy: false, to be able to handle fail on invalid certs httpAgent, diff --git a/x-pack/plugins/actions/server/lib/get_basic_auth_header.test.ts b/x-pack/plugins/actions/server/lib/get_basic_auth_header.test.ts new file mode 100644 index 0000000000000..b5064797de38a --- /dev/null +++ b/x-pack/plugins/actions/server/lib/get_basic_auth_header.test.ts @@ -0,0 +1,69 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { combineHeadersWithBasicAuthHeader, getBasicAuthHeader } from './get_basic_auth_header'; + +describe('get_basic_auth_header', () => { + describe('getBasicAuthHeader', () => { + it('constructs the basic auth header correctly', () => { + expect(getBasicAuthHeader({ username: 'test', password: 'foo' })).toEqual({ + Authorization: `Basic ${Buffer.from('test:foo').toString('base64')}`, + }); + }); + }); + + describe('combineHeadersWithBasicAuthHeader', () => { + it('constructs the basic auth header correctly', () => { + expect(combineHeadersWithBasicAuthHeader({ username: 'test', password: 'foo' })).toEqual({ + Authorization: `Basic ${Buffer.from('test:foo').toString('base64')}`, + }); + }); + + it('adds extra headers correctly', () => { + expect( + combineHeadersWithBasicAuthHeader({ + username: 'test', + password: 'foo', + headers: { 'X-token': 'foo' }, + }) + ).toEqual({ + Authorization: `Basic ${Buffer.from('test:foo').toString('base64')}`, + 'X-token': 'foo', + }); + }); + + it('does not overrides the auth header if provided', () => { + expect( + combineHeadersWithBasicAuthHeader({ + username: 'test', + password: 'foo', + headers: { Authorization: 'Bearer my_token' }, + }) + ).toEqual({ + Authorization: 'Bearer my_token', + }); + }); + + it('returns only the headers if auth is undefined', () => { + expect( + combineHeadersWithBasicAuthHeader({ + headers: { 'X-token': 'foo' }, + }) + ).toEqual({ + 'X-token': 'foo', + }); + }); + + it('returns undefined with no arguments', () => { + expect(combineHeadersWithBasicAuthHeader()).toEqual(undefined); + }); + + it('returns undefined when headers are null', () => { + expect(combineHeadersWithBasicAuthHeader({ headers: null })).toEqual(undefined); + }); + }); +}); diff --git a/x-pack/plugins/actions/server/lib/get_basic_auth_header.ts b/x-pack/plugins/actions/server/lib/get_basic_auth_header.ts new file mode 100644 index 0000000000000..8408f6be76f2b --- /dev/null +++ b/x-pack/plugins/actions/server/lib/get_basic_auth_header.ts @@ -0,0 +1,33 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { AxiosHeaderValue } from 'axios'; + +interface GetBasicAuthHeaderArgs { + username: string; + password: string; +} + +type CombineHeadersWithBasicAuthHeader = Partial & { + headers?: Record | null; +}; + +export const getBasicAuthHeader = ({ username, password }: GetBasicAuthHeaderArgs) => { + const header = `Basic ${Buffer.from(`${username}:${password}`).toString('base64')}`; + + return { Authorization: header }; +}; + +export const combineHeadersWithBasicAuthHeader = ({ + username, + password, + headers, +}: CombineHeadersWithBasicAuthHeader = {}) => { + return username != null && password != null + ? { ...getBasicAuthHeader({ username, password }), ...headers } + : headers ?? undefined; +}; diff --git a/x-pack/plugins/actions/server/lib/index.ts b/x-pack/plugins/actions/server/lib/index.ts index e97198ee7b432..2737d83abfff6 100644 --- a/x-pack/plugins/actions/server/lib/index.ts +++ b/x-pack/plugins/actions/server/lib/index.ts @@ -38,3 +38,4 @@ export { export { validateEmptyStrings } from './validate_empty_strings'; export { parseDate } from './parse_date'; export type { RelatedSavedObjects } from './related_saved_objects'; +export { getBasicAuthHeader, combineHeadersWithBasicAuthHeader } from './get_basic_auth_header'; diff --git a/x-pack/plugins/actions/server/sub_action_framework/mocks.ts b/x-pack/plugins/actions/server/sub_action_framework/mocks.ts index 572aa20422a94..f6c8e86dd5af3 100644 --- a/x-pack/plugins/actions/server/sub_action_framework/mocks.ts +++ b/x-pack/plugins/actions/server/sub_action_framework/mocks.ts @@ -78,6 +78,18 @@ export class TestSubActionConnector extends SubActionConnector } = {}) { + const res = await this.request({ + url: 'https://example.com', + data: {}, + auth: { username: 'username', password: 'password' }, + headers: { 'X-Test-Header': 'test', ...headers }, + responseSchema: schema.object({ status: schema.string() }), + }); + + return res; + } } export class TestNoSubActions extends SubActionConnector { diff --git a/x-pack/plugins/actions/server/sub_action_framework/sub_action_connector.test.ts b/x-pack/plugins/actions/server/sub_action_framework/sub_action_connector.test.ts index 5980072217dd5..1358684d86093 100644 --- a/x-pack/plugins/actions/server/sub_action_framework/sub_action_connector.test.ts +++ b/x-pack/plugins/actions/server/sub_action_framework/sub_action_connector.test.ts @@ -210,5 +210,43 @@ describe('SubActionConnector', () => { 'Request to external service failed. Connector Id: test-id. Connector type: .test. Method: get. URL: https://example.com' ); }); + + it('converts auth axios property to a basic auth header if provided', async () => { + await service.testAuth(); + + expect(requestMock).toHaveBeenCalledTimes(1); + expect(requestMock).toBeCalledWith({ + axios: axiosInstanceMock, + configurationUtilities: mockedActionsConfig, + logger, + method: 'get', + data: {}, + headers: { + 'Content-Type': 'application/json', + 'X-Test-Header': 'test', + Authorization: `Basic ${Buffer.from('username:password').toString('base64')}`, + }, + url: 'https://example.com', + }); + }); + + it('does not override an authorization header if provided', async () => { + await service.testAuth({ headers: { Authorization: 'Bearer my_token' } }); + + expect(requestMock).toHaveBeenCalledTimes(1); + expect(requestMock).toBeCalledWith({ + axios: axiosInstanceMock, + configurationUtilities: mockedActionsConfig, + logger, + method: 'get', + data: {}, + headers: { + 'Content-Type': 'application/json', + 'X-Test-Header': 'test', + Authorization: 'Bearer my_token', + }, + url: 'https://example.com', + }); + }); }); }); diff --git a/x-pack/plugins/actions/server/sub_action_framework/sub_action_connector.ts b/x-pack/plugins/actions/server/sub_action_framework/sub_action_connector.ts index 14e2ded5d1a38..19cc7e90d6254 100644 --- a/x-pack/plugins/actions/server/sub_action_framework/sub_action_connector.ts +++ b/x-pack/plugins/actions/server/sub_action_framework/sub_action_connector.ts @@ -15,6 +15,7 @@ import axios, { AxiosRequestHeaders, AxiosHeaders, AxiosHeaderValue, + AxiosBasicCredentials, } from 'axios'; import { SavedObjectsClientContract } from '@kbn/core-saved-objects-api-server'; import { ElasticsearchClient } from '@kbn/core-elasticsearch-server'; @@ -29,6 +30,7 @@ import { SubAction, SubActionRequestParams } from './types'; import { ServiceParams } from './types'; import * as i18n from './translations'; import { request } from '../lib/axios_utils'; +import { combineHeadersWithBasicAuthHeader } from '../lib/get_basic_auth_header'; const isObject = (value: unknown): value is Record => { return isPlainObject(value); @@ -87,8 +89,17 @@ export abstract class SubActionConnector { } } - private getHeaders(headers?: AxiosRequestHeaders): Record { - return { 'Content-Type': 'application/json', ...headers }; + private getHeaders( + auth?: AxiosBasicCredentials, + headers?: AxiosRequestHeaders + ): Record { + const headersWithBasicAuth = combineHeadersWithBasicAuthHeader({ + username: auth?.username, + password: auth?.password, + headers, + }); + + return { 'Content-Type': 'application/json', ...headersWithBasicAuth }; } private validateResponse(responseSchema: Type, data: unknown) { @@ -137,15 +148,17 @@ export abstract class SubActionConnector { `Request to external service. Connector Id: ${this.connector.id}. Connector type: ${this.connector.type} Method: ${method}. URL: ${normalizedURL}` ); + const { auth, ...restConfig } = config; + const res = await request({ - ...config, + ...restConfig, axios: this.axiosInstance, url: normalizedURL, logger: this.logger, method, data: this.normalizeData(data), configurationUtilities: this.configurationUtilities, - headers: this.getHeaders(headers as AxiosHeaders), + headers: this.getHeaders(auth, headers as AxiosHeaders), timeout, }); diff --git a/x-pack/plugins/aiops/public/components/log_rate_analysis_results_table/log_rate_analysis_results_table.tsx b/x-pack/plugins/aiops/public/components/log_rate_analysis_results_table/log_rate_analysis_results_table.tsx index ac9ae24987b94..59e8f930398e9 100644 --- a/x-pack/plugins/aiops/public/components/log_rate_analysis_results_table/log_rate_analysis_results_table.tsx +++ b/x-pack/plugins/aiops/public/components/log_rate_analysis_results_table/log_rate_analysis_results_table.tsx @@ -16,10 +16,8 @@ import { EuiBadge, EuiBasicTable, EuiCode, - EuiIcon, EuiIconTip, EuiText, - EuiToolTip, } from '@elastic/eui'; import type { FieldStatsServices } from '@kbn/unified-field-list/src/components/field_stats'; @@ -150,7 +148,11 @@ export const LogRateAnalysisResultsTable: FC = /> )} {type === SIGNIFICANT_ITEM_TYPE.LOG_PATTERN && ( - = 'The field value for this field shows an example of the identified significant text field pattern.', } )} - > - - + /> )} @@ -206,21 +201,27 @@ export const LogRateAnalysisResultsTable: FC = width: NARROW_COLUMN_WIDTH, field: 'pValue', name: ( - - <> - - - - + <> + +   + + ), render: (_, { histogram, fieldName, fieldValue }) => ( = width: NARROW_COLUMN_WIDTH, field: 'pValue', name: ( - - <> - - - - + <> + +   + + ), render: (pValue: number | null) => pValue?.toPrecision(3) ?? NOT_AVAILABLE, sortable: true, @@ -278,23 +285,26 @@ export const LogRateAnalysisResultsTable: FC = width: NARROW_COLUMN_WIDTH, field: 'pValue', name: ( - - <> - - - - + <> + +   + + ), render: (_, { pValue }) => { if (typeof pValue !== 'number') return NOT_AVAILABLE; diff --git a/x-pack/plugins/aiops/public/components/log_rate_analysis_results_table/log_rate_analysis_results_table_groups.tsx b/x-pack/plugins/aiops/public/components/log_rate_analysis_results_table/log_rate_analysis_results_table_groups.tsx index 1df6550309ae9..c388555bcf2ca 100644 --- a/x-pack/plugins/aiops/public/components/log_rate_analysis_results_table/log_rate_analysis_results_table_groups.tsx +++ b/x-pack/plugins/aiops/public/components/log_rate_analysis_results_table/log_rate_analysis_results_table_groups.tsx @@ -15,11 +15,10 @@ import { EuiBadge, EuiBasicTable, EuiButtonIcon, - EuiIcon, EuiScreenReaderOnly, EuiSpacer, EuiText, - EuiToolTip, + EuiIconTip, RIGHT_ALIGNMENT, useEuiTheme, euiPaletteColorBlind, @@ -176,25 +175,28 @@ export const LogRateAnalysisResultsGroupsTable: FC - <> - - - - + <> + +   + + ), render: (_, { uniqueItemsCount, groupItemsSortedByUniqueness }) => { const valuesBadges = []; @@ -262,24 +264,27 @@ export const LogRateAnalysisResultsGroupsTable: FC - <> - - - - + <> + +   + + ), render: (_, { histogram, id }) => ( - <> - - - - + <> + +   + + ), render: (pValue: number | null) => pValue?.toPrecision(3) ?? NOT_AVAILABLE, sortable: true, @@ -342,23 +350,26 @@ export const LogRateAnalysisResultsGroupsTable: FC - <> - - - - + <> + +   + + ), render: (_, { pValue }) => { if (!pValue) return NOT_AVAILABLE; diff --git a/x-pack/plugins/cases/public/components/connectors/resilient/use_get_incident_types.test.tsx b/x-pack/plugins/cases/public/components/connectors/resilient/use_get_incident_types.test.tsx index 7bff41383b77a..569483e43e566 100644 --- a/x-pack/plugins/cases/public/components/connectors/resilient/use_get_incident_types.test.tsx +++ b/x-pack/plugins/cases/public/components/connectors/resilient/use_get_incident_types.test.tsx @@ -19,19 +19,18 @@ jest.mock('./api'); const useKibanaMock = useKibana as jest.Mocked; -// FLAKY: https://github.com/elastic/kibana/issues/182845 -describe.skip('useGetIncidentTypes', () => { +describe('useGetIncidentTypes', () => { const { http } = useKibanaMock().services; let appMockRender: AppMockRenderer; beforeEach(() => { - appMockRender = createAppMockRenderer(); jest.clearAllMocks(); + appMockRender = createAppMockRenderer(); }); it('calls the api when invoked with the correct parameters', async () => { const spy = jest.spyOn(api, 'getIncidentTypes'); - const { waitForNextUpdate } = renderHook( + const { waitFor } = renderHook( () => useGetIncidentTypes({ http, @@ -40,7 +39,9 @@ describe.skip('useGetIncidentTypes', () => { { wrapper: appMockRender.AppWrapper } ); - await waitForNextUpdate(); + await waitFor(() => { + expect(spy).toHaveBeenCalled(); + }); expect(spy).toHaveBeenCalledWith({ http, @@ -71,7 +72,7 @@ describe.skip('useGetIncidentTypes', () => { const addError = jest.fn(); (useToasts as jest.Mock).mockReturnValue({ addSuccess: jest.fn(), addError }); - const { waitForNextUpdate } = renderHook( + const { waitFor } = renderHook( () => useGetIncidentTypes({ http, @@ -80,8 +81,9 @@ describe.skip('useGetIncidentTypes', () => { { wrapper: appMockRender.AppWrapper } ); - await waitForNextUpdate(); - expect(addError).toHaveBeenCalled(); + await waitFor(() => { + expect(addError).toHaveBeenCalled(); + }); }); it('calls addError when the getIncidentTypes api returns successfully but contains an error', async () => { @@ -95,7 +97,7 @@ describe.skip('useGetIncidentTypes', () => { const addError = jest.fn(); (useToasts as jest.Mock).mockReturnValue({ addSuccess: jest.fn(), addError }); - const { waitForNextUpdate } = renderHook( + const { waitFor } = renderHook( () => useGetIncidentTypes({ http, @@ -104,7 +106,8 @@ describe.skip('useGetIncidentTypes', () => { { wrapper: appMockRender.AppWrapper } ); - await waitForNextUpdate(); - expect(addError).toHaveBeenCalled(); + await waitFor(() => { + expect(addError).toHaveBeenCalled(); + }); }); }); diff --git a/x-pack/plugins/cases/public/containers/user_profiles/use_get_current_user_profile.test.ts b/x-pack/plugins/cases/public/containers/user_profiles/use_get_current_user_profile.test.ts index cbc39d183d870..c26a6af826548 100644 --- a/x-pack/plugins/cases/public/containers/user_profiles/use_get_current_user_profile.test.ts +++ b/x-pack/plugins/cases/public/containers/user_profiles/use_get_current_user_profile.test.ts @@ -18,16 +18,16 @@ jest.mock('./api'); const useKibanaMock = useKibana as jest.Mock; -// FLAKY: https://github.com/elastic/kibana/issues/183144 -describe.skip('useGetCurrentUserProfile', () => { +describe('useGetCurrentUserProfile', () => { const addSuccess = jest.fn(); (useToasts as jest.Mock).mockReturnValue({ addSuccess, addError: jest.fn() }); let appMockRender: AppMockRenderer; beforeEach(() => { - appMockRender = createAppMockRenderer(); jest.clearAllMocks(); + + appMockRender = createAppMockRenderer(); useKibanaMock.mockReturnValue({ services: { ...createStartServicesMock() }, }); @@ -36,11 +36,13 @@ describe.skip('useGetCurrentUserProfile', () => { it('calls getCurrentUserProfile with correct arguments', async () => { const spyOnGetCurrentUserProfile = jest.spyOn(api, 'getCurrentUserProfile'); - const { result, waitFor } = renderHook(() => useGetCurrentUserProfile(), { + const { waitFor } = renderHook(() => useGetCurrentUserProfile(), { wrapper: appMockRender.AppWrapper, }); - await waitFor(() => result.current.isSuccess); + await waitFor(() => { + expect(spyOnGetCurrentUserProfile).toBeCalled(); + }); expect(spyOnGetCurrentUserProfile).toBeCalledWith({ security: expect.anything(), @@ -57,13 +59,13 @@ describe.skip('useGetCurrentUserProfile', () => { const addError = jest.fn(); (useToasts as jest.Mock).mockReturnValue({ addSuccess, addError }); - const { result, waitFor } = renderHook(() => useGetCurrentUserProfile(), { + const { waitFor } = renderHook(() => useGetCurrentUserProfile(), { wrapper: appMockRender.AppWrapper, }); - await waitFor(() => result.current.isError); - - expect(addError).toHaveBeenCalled(); + await waitFor(() => { + expect(addError).toHaveBeenCalled(); + }); }); it('does not show a toast error message when a 404 error is returned', async () => { @@ -76,13 +78,13 @@ describe.skip('useGetCurrentUserProfile', () => { const addError = jest.fn(); (useToasts as jest.Mock).mockReturnValue({ addSuccess, addError }); - const { result, waitFor } = renderHook(() => useGetCurrentUserProfile(), { + const { waitFor } = renderHook(() => useGetCurrentUserProfile(), { wrapper: appMockRender.AppWrapper, }); - await waitFor(() => result.current.isError); - - expect(addError).not.toHaveBeenCalled(); + await waitFor(() => { + expect(addError).not.toHaveBeenCalled(); + }); }); }); diff --git a/x-pack/plugins/cloud_integrations/cloud_links/public/plugin.test.ts b/x-pack/plugins/cloud_integrations/cloud_links/public/plugin.test.ts index d2f987337a440..d930d024d2484 100644 --- a/x-pack/plugins/cloud_integrations/cloud_links/public/plugin.test.ts +++ b/x-pack/plugins/cloud_integrations/cloud_links/public/plugin.test.ts @@ -26,7 +26,7 @@ describe('Cloud Links Plugin - public', () => { describe('start', () => { beforeEach(() => { - plugin.setup(); + plugin.setup(coreMock.createSetup()); }); afterEach(() => { diff --git a/x-pack/plugins/cloud_integrations/cloud_links/public/plugin.tsx b/x-pack/plugins/cloud_integrations/cloud_links/public/plugin.tsx index 0e8b5eec26f65..9f385500b13e8 100755 --- a/x-pack/plugins/cloud_integrations/cloud_links/public/plugin.tsx +++ b/x-pack/plugins/cloud_integrations/cloud_links/public/plugin.tsx @@ -7,7 +7,7 @@ import React from 'react'; import { FormattedMessage } from '@kbn/i18n-react'; -import type { CoreStart, Plugin } from '@kbn/core/public'; +import type { CoreSetup, CoreStart, Plugin } from '@kbn/core/public'; import type { CloudSetup, CloudStart } from '@kbn/cloud-plugin/public'; import type { SecurityPluginSetup, SecurityPluginStart } from '@kbn/security-plugin/public'; import type { GuidedOnboardingPluginStart } from '@kbn/guided-onboarding-plugin/public'; @@ -30,7 +30,68 @@ interface CloudLinksDepsStart { export class CloudLinksPlugin implements Plugin { - public setup() {} + public setup({ analytics }: CoreSetup) { + analytics.registerEventType({ + eventType: 'connection_details_learn_more_clicked', + schema: {}, + }); + analytics.registerEventType({ + eventType: 'connection_details_tab_switched', + schema: { + tab: { + type: 'keyword', + _meta: { + description: 'Connection details tab that was switched to.', + optional: false, + }, + }, + }, + }); + analytics.registerEventType({ + eventType: 'connection_details_copy_endpoint_url_clicked', + schema: {}, + }); + analytics.registerEventType({ + eventType: 'connection_details_show_cloud_id_toggled', + schema: {}, + }); + analytics.registerEventType({ + eventType: 'connection_details_copy_cloud_id_clicked', + schema: {}, + }); + analytics.registerEventType({ + eventType: 'connection_details_new_api_key_created', + schema: {}, + }); + analytics.registerEventType({ + eventType: 'connection_details_manage_api_keys_clicked', + schema: {}, + }); + analytics.registerEventType({ + eventType: 'connection_details_key_encoding_changed', + schema: { + format: { + type: 'keyword', + _meta: { + description: 'The format of the API key that was changed to.', + optional: false, + }, + }, + }, + }); + analytics.registerEventType({ + eventType: 'connection_details_copy_api_key_clicked', + schema: { + format: { + type: 'keyword', + _meta: { + description: 'The format of the API key that was copied.', + optional: false, + }, + }, + }, + }); + } public start(core: CoreStart, plugins: CloudLinksDepsStart) { const { cloud, security, guidedOnboarding, share } = plugins; diff --git a/x-pack/plugins/ecs_data_quality_dashboard/common/constants.ts b/x-pack/plugins/ecs_data_quality_dashboard/common/constants.ts index d979d22b12b88..7c35cd9b2fbbd 100755 --- a/x-pack/plugins/ecs_data_quality_dashboard/common/constants.ts +++ b/x-pack/plugins/ecs_data_quality_dashboard/common/constants.ts @@ -14,4 +14,5 @@ export const GET_INDEX_MAPPINGS = `${BASE_PATH}/mappings/{pattern}`; export const GET_UNALLOWED_FIELD_VALUES = `${BASE_PATH}/unallowed_field_values`; export const GET_ILM_EXPLAIN = `${BASE_PATH}/ilm_explain/{pattern}`; export const RESULTS_ROUTE_PATH = `${BASE_PATH}/results`; +export const RESULTS_INDICES_LATEST_ROUTE_PATH = `${BASE_PATH}/results/indices_latest/{pattern}`; export const INTERNAL_API_VERSION = '1'; diff --git a/x-pack/plugins/ecs_data_quality_dashboard/server/routes/results/get_results.test.ts b/x-pack/plugins/ecs_data_quality_dashboard/server/routes/results/get_results_indices_latest.test.ts similarity index 91% rename from x-pack/plugins/ecs_data_quality_dashboard/server/routes/results/get_results.test.ts rename to x-pack/plugins/ecs_data_quality_dashboard/server/routes/results/get_results_indices_latest.test.ts index 05a714a27275a..7aad4c347a8cb 100644 --- a/x-pack/plugins/ecs_data_quality_dashboard/server/routes/results/get_results.test.ts +++ b/x-pack/plugins/ecs_data_quality_dashboard/server/routes/results/get_results_indices_latest.test.ts @@ -4,13 +4,13 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import { RESULTS_ROUTE_PATH } from '../../../common/constants'; +import { RESULTS_INDICES_LATEST_ROUTE_PATH } from '../../../common/constants'; import { serverMock } from '../../__mocks__/server'; import { requestMock } from '../../__mocks__/request'; import { requestContextMock } from '../../__mocks__/request_context'; -import type { LatestAggResponseBucket } from './get_results'; -import { getResultsRoute, getQuery } from './get_results'; +import type { LatestAggResponseBucket } from './get_results_indices_latest'; +import { getResultsIndicesLatestRoute, getQuery } from './get_results_indices_latest'; import { loggerMock, type MockedLogger } from '@kbn/logging-mocks'; import { resultDocument } from './results.mock'; import type { SearchResponse } from '@elastic/elasticsearch/lib/api/types'; @@ -41,7 +41,7 @@ jest.mock('./privileges', () => ({ mockCheckIndicesPrivileges(params), })); -describe('getResultsRoute route', () => { +describe('getResultsIndicesLatestRoute route', () => { describe('querying', () => { let server: ReturnType; let { context } = requestContextMock.createTools(); @@ -49,8 +49,8 @@ describe('getResultsRoute route', () => { const req = requestMock.create({ method: 'get', - path: RESULTS_ROUTE_PATH, - query: { pattern: 'logs-*' }, + path: RESULTS_INDICES_LATEST_ROUTE_PATH, + params: { pattern: 'logs-*' }, }); beforeEach(() => { @@ -65,7 +65,7 @@ describe('getResultsRoute route', () => { [resultDocument.indexName]: {}, }); - getResultsRoute(server.router, logger); + getResultsIndicesLatestRoute(server.router, logger); }); it('gets result', async () => { @@ -114,8 +114,8 @@ describe('getResultsRoute route', () => { const req = requestMock.create({ method: 'get', - path: RESULTS_ROUTE_PATH, - query: { pattern: 'logs-*' }, + path: RESULTS_INDICES_LATEST_ROUTE_PATH, + params: { pattern: 'logs-*' }, }); beforeEach(() => { @@ -132,7 +132,7 @@ describe('getResultsRoute route', () => { [resultDocument.indexName]: {}, }); - getResultsRoute(server.router, logger); + getResultsIndicesLatestRoute(server.router, logger); }); it('should authorize indices from pattern', async () => { @@ -225,14 +225,14 @@ describe('getResultsRoute route', () => { beforeEach(() => { server = serverMock.create(); logger = loggerMock.create(); - getResultsRoute(server.router, logger); + getResultsIndicesLatestRoute(server.router, logger); }); - test('disallows invalid query param', () => { + test('disallows invalid path param', () => { const req = requestMock.create({ method: 'get', - path: RESULTS_ROUTE_PATH, - query: {}, + path: RESULTS_INDICES_LATEST_ROUTE_PATH, + params: {}, }); const result = server.validate(req); diff --git a/x-pack/plugins/ecs_data_quality_dashboard/server/routes/results/get_results.ts b/x-pack/plugins/ecs_data_quality_dashboard/server/routes/results/get_results_indices_latest.ts similarity index 92% rename from x-pack/plugins/ecs_data_quality_dashboard/server/routes/results/get_results.ts rename to x-pack/plugins/ecs_data_quality_dashboard/server/routes/results/get_results_indices_latest.ts index 6c410e88f3626..a4508e1471b3b 100644 --- a/x-pack/plugins/ecs_data_quality_dashboard/server/routes/results/get_results.ts +++ b/x-pack/plugins/ecs_data_quality_dashboard/server/routes/results/get_results_indices_latest.ts @@ -7,10 +7,10 @@ import type { IRouter, Logger } from '@kbn/core/server'; -import { RESULTS_ROUTE_PATH, INTERNAL_API_VERSION } from '../../../common/constants'; +import { INTERNAL_API_VERSION, RESULTS_INDICES_LATEST_ROUTE_PATH } from '../../../common/constants'; import { buildResponse } from '../../lib/build_response'; import { buildRouteValidation } from '../../schemas/common'; -import { GetResultQuery } from '../../schemas/result'; +import { GetResultParams } from '../../schemas/result'; import type { ResultDocument } from '../../schemas/result'; import { API_DEFAULT_ERROR_MESSAGE } from '../../translations'; import type { DataQualityDashboardRequestHandlerContext } from '../../types'; @@ -33,20 +33,24 @@ export interface LatestAggResponseBucket { latest_doc: { hits: { hits: Array<{ _source: ResultDocument }> } }; } -export const getResultsRoute = ( +export const getResultsIndicesLatestRoute = ( router: IRouter, logger: Logger ) => { router.versioned .get({ - path: RESULTS_ROUTE_PATH, + path: RESULTS_INDICES_LATEST_ROUTE_PATH, access: 'internal', options: { tags: ['access:securitySolution'] }, }) .addVersion( { version: INTERNAL_API_VERSION, - validate: { request: { query: buildRouteValidation(GetResultQuery) } }, + validate: { + request: { + params: buildRouteValidation(GetResultParams), + }, + }, }, async (context, request, response) => { const services = await context.resolve(['core', 'dataQualityDashboard']); @@ -65,7 +69,7 @@ export const getResultsRoute = ( try { const { client } = services.core.elasticsearch; - const { pattern } = request.query; + const { pattern } = request.params; // Discover all indices for the pattern using internal user const indicesResponse = await client.asInternalUser.indices.get({ diff --git a/x-pack/plugins/ecs_data_quality_dashboard/server/routes/results/index.ts b/x-pack/plugins/ecs_data_quality_dashboard/server/routes/results/index.ts index 25d4a913a1946..d403ece283b1d 100644 --- a/x-pack/plugins/ecs_data_quality_dashboard/server/routes/results/index.ts +++ b/x-pack/plugins/ecs_data_quality_dashboard/server/routes/results/index.ts @@ -8,7 +8,7 @@ import type { IRouter, Logger } from '@kbn/core/server'; import { postResultsRoute } from './post_results'; -import { getResultsRoute } from './get_results'; +import { getResultsIndicesLatestRoute } from './get_results_indices_latest'; import type { DataQualityDashboardRequestHandlerContext } from '../../types'; export const resultsRoutes = ( @@ -16,5 +16,5 @@ export const resultsRoutes = ( logger: Logger ) => { postResultsRoute(router, logger); - getResultsRoute(router, logger); + getResultsIndicesLatestRoute(router, logger); }; diff --git a/x-pack/plugins/ecs_data_quality_dashboard/server/schemas/result.ts b/x-pack/plugins/ecs_data_quality_dashboard/server/schemas/result.ts index 9e8b7540bf2e5..055930d82cefb 100644 --- a/x-pack/plugins/ecs_data_quality_dashboard/server/schemas/result.ts +++ b/x-pack/plugins/ecs_data_quality_dashboard/server/schemas/result.ts @@ -39,5 +39,5 @@ export type ResultDocument = t.TypeOf; export const PostResultBody = ResultDocument; -export const GetResultQuery = t.type({ pattern: t.string }); -export type GetResultQuery = t.TypeOf; +export const GetResultParams = t.type({ pattern: t.string }); +export type GetResultParams = t.TypeOf; diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/connector/update_connector_filtering_api_logic.ts b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/connector/update_connector_filtering_api_logic.ts index 00d300c32e058..798df56b7fae3 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/connector/update_connector_filtering_api_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/api/connector/update_connector_filtering_api_logic.ts @@ -7,32 +7,21 @@ import { i18n } from '@kbn/i18n'; -import { FilteringRule, FilteringRules } from '@kbn/search-connectors'; +import { FilteringRules } from '@kbn/search-connectors'; import { createApiLogic } from '../../../shared/api_logic/create_api_logic'; import { HttpLogic } from '../../../shared/http'; export interface PutConnectorFilteringArgs { - advancedSnippet: string; connectorId: string; - filteringRules: FilteringRule[]; } export type PutConnectorFilteringResponse = FilteringRules; -export const putConnectorFiltering = async ({ - advancedSnippet, - connectorId, - filteringRules, -}: PutConnectorFilteringArgs) => { +export const putConnectorFiltering = async ({ connectorId }: PutConnectorFilteringArgs) => { const route = `/internal/enterprise_search/connectors/${connectorId}/filtering`; - return await HttpLogic.values.http.put(route, { - body: JSON.stringify({ - advanced_snippet: advancedSnippet, - filtering_rules: filteringRules, - }), - }); + return await HttpLogic.values.http.put(route); }; export const ConnectorFilteringApiLogic = createApiLogic( diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/sync_rules/connector_filtering_logic.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/sync_rules/connector_filtering_logic.tsx index 3ccdf83ce5dd8..825cea83f1510 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/sync_rules/connector_filtering_logic.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/connector/sync_rules/connector_filtering_logic.tsx @@ -149,9 +149,7 @@ export const ConnectorFilteringLogic = kea< applyDraft: () => { if (isConnectorIndex(values.index)) { actions.makeRequest({ - advancedSnippet: values.localAdvancedSnippet ?? '', connectorId: values.index.connector.id, - filteringRules: values.localFilteringRules ?? [], }); } }, diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/getting_started/panels/add_data_panel_content.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/getting_started/panels/add_data_panel_content.tsx index 5d2d8cecf8466..55420cc17895b 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/getting_started/panels/add_data_panel_content.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/shared/getting_started/panels/add_data_panel_content.tsx @@ -38,7 +38,7 @@ export const AddDataPanelContent: React.FC = ({ > = ({ children }) => { - const [isPopoverOpen, setPopoverOpen] = useState(false); - const { cloud, esConfig, navigateToUrl } = useValues(KibanaLogic); - const { makeRequest } = useActions(FetchApiKeysAPILogic); - const { data } = useValues(FetchApiKeysAPILogic); - const [isFlyoutOpen, setIsFlyoutOpen] = useState(false); - const { euiTheme } = useEuiTheme(); - - useEffect(() => makeRequest({}), []); - - const COPIED_LABEL = i18n.translate('xpack.enterpriseSearch.pageTemplate.apiKey.copied', { - defaultMessage: 'Copied', - }); - - const apiKeys = data?.api_keys || []; - const cloudId = cloud?.cloudId; - const elasticsearchEndpoint = esConfig.elasticsearch_host; - - const button = ( - setPopoverOpen(!isPopoverOpen)}> - {i18n.translate('xpack.enterpriseSearch.pageTemplate.endpointsButtonLabel', { - defaultMessage: 'Endpoints & API keys', - })} - - ); +export const EndpointsHeaderAction: React.FC = ({ children }) => { + const [open, setOpen] = React.useState(false); return ( - - - {Boolean(children) && {children}} - - {isFlyoutOpen && setIsFlyoutOpen(false)} />} - setPopoverOpen(false)} - panelPaddingSize="none" - anchorPosition="downLeft" + <> + + + {!!children && {children}} + setOpen((x) => !x)} + data-test-subj="enterpriseSearchEndpointsHeaderActionEndpointsApiKeysButton" > - - - {i18n.translate( - 'xpack.enterpriseSearch.pageTemplate.apiKey.elasticsearchEndpoint', - { - defaultMessage: 'Elasticsearch endpoint:', - } - )} - - - - - - - {elasticsearchEndpoint} - - - - - {(copy) => ( - - )} - - - - , - ...(Boolean(cloudId) - ? [ - - - {i18n.translate('xpack.enterpriseSearch.apiKey.cloudId', { - defaultMessage: 'Cloud ID:', - })} - - - - - - - {cloudId} - - - - - {(copy) => ( - - )} - - - - , - ] - : []), - - - - - 0 ? 'success' : 'warning'} - data-test-subj="api-keys-count-badge" - > - {apiKeys.length} - - ), - }} - /> - - - - - navigateToUrl('/app/management/security/api_keys', { - shouldNotCreateHref: true, - }) - } - /> - - - , - , - - { - setIsFlyoutOpen(true); - setPopoverOpen(false); - }} - data-test-subj="new-api-key-button" - fullWidth - > - - {i18n.translate('xpack.enterpriseSearch.pageTemplate.apiKey.newButtonLabel', { - defaultMessage: 'New API key', - })} - - - , - ]} - /> - - - - + {i18n.translate('xpack.enterpriseSearch.pageTemplate.endpointsButtonLabel', { + defaultMessage: 'Endpoints & API keys', + })} + + + + {open && ( + setOpen(false)} size={'s'}> + + + + + )} + ); }; diff --git a/x-pack/plugins/enterprise_search/server/routes/enterprise_search/connectors.ts b/x-pack/plugins/enterprise_search/server/routes/enterprise_search/connectors.ts index 395c114424864..66cea5b830730 100644 --- a/x-pack/plugins/enterprise_search/server/routes/enterprise_search/connectors.ts +++ b/x-pack/plugins/enterprise_search/server/routes/enterprise_search/connectors.ts @@ -472,21 +472,23 @@ export function registerConnectorRoutes({ router, log }: RouteDependencies) { { path: '/internal/enterprise_search/connectors/{connectorId}/filtering', validate: { - body: schema.object({ - advanced_snippet: schema.string(), - filtering_rules: schema.arrayOf( - schema.object({ - created_at: schema.string(), - field: schema.string(), - id: schema.string(), - order: schema.number(), - policy: schema.string(), - rule: schema.string(), - updated_at: schema.string(), - value: schema.string(), - }) - ), - }), + body: schema.maybe( + schema.object({ + advanced_snippet: schema.string(), + filtering_rules: schema.arrayOf( + schema.object({ + created_at: schema.string(), + field: schema.string(), + id: schema.string(), + order: schema.number(), + policy: schema.string(), + rule: schema.string(), + updated_at: schema.string(), + value: schema.string(), + }) + ), + }) + ), params: schema.object({ connectorId: schema.string(), }), @@ -495,13 +497,7 @@ export function registerConnectorRoutes({ router, log }: RouteDependencies) { elasticsearchErrorHandler(log, async (context, request, response) => { const { client } = (await context.core).elasticsearch; const { connectorId } = request.params; - const { advanced_snippet, filtering_rules } = request.body; - const result = await updateFiltering(client.asCurrentUser, connectorId, { - advancedSnippet: advanced_snippet, - // Have to cast here because our API schema validator doesn't know how to deal with enums - // We're relying on the schema in the validator above to flag if something goes wrong - filteringRules: filtering_rules as FilteringRule[], - }); + const result = await updateFiltering(client.asCurrentUser, connectorId); return result ? response.ok({ body: result }) : response.conflict(); }) ); diff --git a/x-pack/plugins/enterprise_search/tsconfig.json b/x-pack/plugins/enterprise_search/tsconfig.json index 6161461b48b89..56232cd73f256 100644 --- a/x-pack/plugins/enterprise_search/tsconfig.json +++ b/x-pack/plugins/enterprise_search/tsconfig.json @@ -75,6 +75,7 @@ "@kbn/deeplinks-search", "@kbn/react-kibana-context-theme", "@kbn/search-types", + "@kbn/cloud", "@kbn/try-in-console" ] } diff --git a/x-pack/plugins/fleet/common/constants/agent_policy.ts b/x-pack/plugins/fleet/common/constants/agent_policy.ts index b2cbed6bb68e9..9f1bc458ec363 100644 --- a/x-pack/plugins/fleet/common/constants/agent_policy.ts +++ b/x-pack/plugins/fleet/common/constants/agent_policy.ts @@ -39,17 +39,10 @@ export const DEFAULT_MAX_AGENT_POLICIES_WITH_INACTIVITY_TIMEOUT = 750; export const AGENTLESS_POLICY_ID = 'agentless'; // the policy id defined here: https://github.com/elastic/project-controller/blob/main/internal/project/security/security_kibana_config.go#L86 export const AGENT_LOG_LEVELS = { - ERROR: 'error', - WARNING: 'warning', - INFO: 'info', - DEBUG: 'debug', + info: 'info', + debug: 'debug', + warning: 'warning', + error: 'error', }; -export const DEFAULT_LOG_LEVEL = AGENT_LOG_LEVELS.INFO; - -export const agentLoggingLevels = { - Info: 'info', - Debug: 'debug', - Warning: 'warning', - Error: 'error', -} as const; +export const DEFAULT_LOG_LEVEL = AGENT_LOG_LEVELS.info; diff --git a/x-pack/plugins/fleet/common/openapi/bundled.json b/x-pack/plugins/fleet/common/openapi/bundled.json index f9ebd7d84653a..9a86cbe6f9fd1 100644 --- a/x-pack/plugins/fleet/common/openapi/bundled.json +++ b/x-pack/plugins/fleet/common/openapi/bundled.json @@ -7294,6 +7294,7 @@ "properties": { "log_level": { "type": "string", + "nullable": true, "enum": [ "debug", "info", diff --git a/x-pack/plugins/fleet/common/openapi/bundled.yaml b/x-pack/plugins/fleet/common/openapi/bundled.yaml index 3bf9514e08147..16137b6f8dd27 100644 --- a/x-pack/plugins/fleet/common/openapi/bundled.yaml +++ b/x-pack/plugins/fleet/common/openapi/bundled.yaml @@ -4674,6 +4674,7 @@ components: properties: log_level: type: string + nullable: true enum: - debug - info diff --git a/x-pack/plugins/fleet/common/openapi/components/schemas/agent_action.yaml b/x-pack/plugins/fleet/common/openapi/components/schemas/agent_action.yaml index e1726e438f82c..ae8734939c373 100644 --- a/x-pack/plugins/fleet/common/openapi/components/schemas/agent_action.yaml +++ b/x-pack/plugins/fleet/common/openapi/components/schemas/agent_action.yaml @@ -19,6 +19,7 @@ oneOf: properties: log_level: type: string + nullable: true enum: - debug - info diff --git a/x-pack/plugins/fleet/common/settings/agent_policy_settings.ts b/x-pack/plugins/fleet/common/settings/agent_policy_settings.tsx similarity index 89% rename from x-pack/plugins/fleet/common/settings/agent_policy_settings.ts rename to x-pack/plugins/fleet/common/settings/agent_policy_settings.tsx index 4257f47c7c33d..4ffe46b680764 100644 --- a/x-pack/plugins/fleet/common/settings/agent_policy_settings.ts +++ b/x-pack/plugins/fleet/common/settings/agent_policy_settings.tsx @@ -4,11 +4,14 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ - +import React from 'react'; import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n-react'; +import { EuiCode } from '@elastic/eui'; + import { z } from 'zod'; -import { agentLoggingLevels } from '../constants'; +import { AGENT_LOG_LEVELS, DEFAULT_LOG_LEVEL } from '../constants'; import type { SettingsConfig } from './types'; @@ -130,20 +133,19 @@ export const AGENT_POLICY_ADVANCED_SETTINGS: SettingsConfig[] = [ }, { name: 'agent.logging.level', - hidden: true, title: i18n.translate('xpack.fleet.settings.agentPolicyAdvanced.agentLoggingLevelTitle', { defaultMessage: 'Agent logging level', }), - description: i18n.translate( - 'xpack.fleet.settings.agentPolicyAdvanced.agentLoggingLevelDescription', - { - defaultMessage: - 'Sets the log level for all the agents on the policy. The default log level is "info".', - } + description: ( + {DEFAULT_LOG_LEVEL} }} + /> ), api_field: { name: 'agent_logging_level', }, - schema: z.nativeEnum(agentLoggingLevels).default(agentLoggingLevels.Info), + schema: z.nativeEnum(AGENT_LOG_LEVELS).default(DEFAULT_LOG_LEVEL), }, ]; diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/agent_logs.test.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/agent_logs.test.tsx index cf22126a7c0d4..7824b8abd2a5c 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/agent_logs.test.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/agent_logs.test.tsx @@ -65,11 +65,15 @@ describe('AgentLogsUI', () => { }, } as any); }); - const renderComponent = () => { + const renderComponent = ( + opts = { + agentVersion: '8.11.0', + } + ) => { const renderer = createFleetTestRendererMock(); const agent = { id: 'agent1', - local_metadata: { elastic: { agent: { version: '8.11' } } }, + local_metadata: { elastic: { agent: { version: opts.agentVersion, log_level: 'debug' } } }, } as any; const state = { datasets: ['elastic_agent'], @@ -125,4 +129,35 @@ describe('AgentLogsUI', () => { `http://localhost:5620/app/discover#/?_g=(filters:!(),refreshInterval:(pause:!t,value:60000),time:(from:'2023-20-04T14:00:00.340Z',to:'2023-20-04T14:20:00.340Z'))&_a=(columns:!(event.dataset,message),index:'logs-*',query:(language:kuery,query:'elastic_agent.id:agent1 and (data_stream.dataset:elastic_agent) and (log.level:info or log.level:error)'))` ); }); + + it('should show log level dropdown with correct value', () => { + mockStartServices(); + const result = renderComponent(); + const logLevelDropdown = result.getByTestId('selectAgentLogLevel'); + expect(logLevelDropdown.getElementsByTagName('option').length).toBe(4); + expect(logLevelDropdown).toHaveDisplayValue('debug'); + }); + + it('should always show apply log level changes button', () => { + mockStartServices(); + const result = renderComponent(); + const applyLogLevelBtn = result.getByTestId('applyLogLevelBtn'); + expect(applyLogLevelBtn).toBeInTheDocument(); + expect(applyLogLevelBtn).not.toHaveAttribute('disabled'); + }); + + it('should hide reset log level button for agents version < 8.15.0', () => { + mockStartServices(); + const result = renderComponent(); + const resetLogLevelBtn = result.queryByTestId('resetLogLevelBtn'); + expect(resetLogLevelBtn).not.toBeInTheDocument(); + }); + + it('should show reset log level button for agents version >= 8.15.0', () => { + mockStartServices(); + const result = renderComponent({ agentVersion: '8.15.0' }); + const resetLogLevelBtn = result.getByTestId('resetLogLevelBtn'); + expect(resetLogLevelBtn).toBeInTheDocument(); + expect(resetLogLevelBtn).not.toHaveAttribute('disabled'); + }); }); diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/agent_logs.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/agent_logs.tsx index 05efb3abfdcaa..34cc206967d62 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/agent_logs.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/agent_logs.tsx @@ -342,7 +342,10 @@ export const AgentLogsUI: React.FunctionComponent = memo( - + ); diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/select_log_level.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/select_log_level.tsx index 4c32952339347..5a38031898eb8 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/select_log_level.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_logs/select_log_level.tsx @@ -9,106 +9,175 @@ import React, { memo, useState, useCallback } from 'react'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; import { EuiSelect, EuiFormLabel, EuiButtonEmpty, EuiFlexItem, EuiFlexGroup } from '@elastic/eui'; +import semverGte from 'semver/functions/gte'; import type { Agent } from '../../../../../types'; import { sendPostAgentAction, useAuthz, useStartServices } from '../../../../../hooks'; import { AGENT_LOG_LEVELS, DEFAULT_LOG_LEVEL } from '../../../../../../../../common/constants'; -const LEVEL_VALUES = Object.values(AGENT_LOG_LEVELS); +export const SelectLogLevel: React.FC<{ agent: Agent; agentPolicyLogLevel?: string }> = memo( + ({ agent, agentPolicyLogLevel = DEFAULT_LOG_LEVEL }) => { + const authz = useAuthz(); + const { notifications } = useStartServices(); + const [isSetLevelLoading, setIsSetLevelLoading] = useState(false); + const [isResetLevelLoading, setIsResetLevelLoading] = useState(false); + const canResetLogLevel = semverGte( + agent.local_metadata?.elastic?.agent?.version, + '8.15.0', + true + ); -export const SelectLogLevel: React.FC<{ agent: Agent }> = memo(({ agent }) => { - const authz = useAuthz(); - const { notifications } = useStartServices(); - const [isLoading, setIsLoading] = useState(false); - const [agentLogLevel, setAgentLogLevel] = useState( - agent.local_metadata?.elastic?.agent?.log_level ?? DEFAULT_LOG_LEVEL - ); - const [selectedLogLevel, setSelectedLogLevel] = useState(agentLogLevel); + const [agentLogLevel, setAgentLogLevel] = useState( + agent.local_metadata?.elastic?.agent?.log_level ?? DEFAULT_LOG_LEVEL + ); + const [selectedLogLevel, setSelectedLogLevel] = useState(agentLogLevel); - const onClickApply = useCallback(() => { - setIsLoading(true); - async function send() { - try { - const res = await sendPostAgentAction(agent.id, { - action: { - type: 'SETTINGS', - data: { - log_level: selectedLogLevel, + const resetLogLevel = useCallback(() => { + setIsResetLevelLoading(true); + async function send() { + try { + const res = await sendPostAgentAction(agent.id, { + action: { + type: 'SETTINGS', + data: { + log_level: null, + }, }, - }, - }); - if (res.error) { - throw res.error; + }); + if (res.error) { + throw res.error; + } + + // TODO: reset to an empty state? + setAgentLogLevel(agentPolicyLogLevel); + setSelectedLogLevel(agentPolicyLogLevel); + + notifications.toasts.addSuccess( + i18n.translate('xpack.fleet.agentLogs.resetLogLevel.successText', { + defaultMessage: `Reset agent logging level to policy`, + }) + ); + } catch (error) { + notifications.toasts.addError(error, { + title: i18n.translate('xpack.fleet.agentLogs.resetLogLevel.errorTitleText', { + defaultMessage: 'Error resetting agent logging level', + }), + }); } - setAgentLogLevel(selectedLogLevel); - notifications.toasts.addSuccess( - i18n.translate('xpack.fleet.agentLogs.selectLogLevel.successText', { - defaultMessage: `Changed agent logging level to '{logLevel}'.`, - values: { - logLevel: selectedLogLevel, + setIsResetLevelLoading(false); + } + + send(); + }, [agent.id, agentPolicyLogLevel, notifications]); + + const onClickApply = useCallback(() => { + setIsSetLevelLoading(true); + async function send() { + try { + const res = await sendPostAgentAction(agent.id, { + action: { + type: 'SETTINGS', + data: { + log_level: selectedLogLevel, + }, }, - }) - ); - } catch (error) { - notifications.toasts.addError(error, { - title: i18n.translate('xpack.fleet.agentLogs.selectLogLevel.errorTitleText', { - defaultMessage: 'Error updating agent logging level', - }), - }); + }); + if (res.error) { + throw res.error; + } + setAgentLogLevel(selectedLogLevel); + notifications.toasts.addSuccess( + i18n.translate('xpack.fleet.agentLogs.selectLogLevel.successText', { + defaultMessage: `Changed agent logging level to '{logLevel}'`, + values: { + logLevel: selectedLogLevel, + }, + }) + ); + } catch (error) { + notifications.toasts.addError(error, { + title: i18n.translate('xpack.fleet.agentLogs.selectLogLevel.errorTitleText', { + defaultMessage: 'Error updating agent logging level', + }), + }); + } + setIsSetLevelLoading(false); } - setIsLoading(false); - } - send(); - }, [notifications, selectedLogLevel, agent.id]); + send(); + }, [notifications, selectedLogLevel, agent.id]); - return ( - - - - - - - - { - setSelectedLogLevel(event.target.value); - }} - options={LEVEL_VALUES.map((level) => ({ text: level, value: level }))} - /> - - {agentLogLevel !== selectedLogLevel && ( - - - {isLoading ? ( - - ) : ( + return ( + <> + + + - )} - - - )} - - ); -}); + + + + { + setSelectedLogLevel(event.target.value); + }} + options={Object.entries(AGENT_LOG_LEVELS).map(([key, value]) => ({ + value, + text: key, + }))} + /> + + + + {isSetLevelLoading ? ( + + ) : ( + + )} + + + {canResetLogLevel && ( + + + + + + )} + + + ); + } +); diff --git a/x-pack/plugins/fleet/server/collectors/agent_collectors.ts b/x-pack/plugins/fleet/server/collectors/agent_collectors.ts index 391114aa992b3..ad23bea85d365 100644 --- a/x-pack/plugins/fleet/server/collectors/agent_collectors.ts +++ b/x-pack/plugins/fleet/server/collectors/agent_collectors.ts @@ -69,6 +69,10 @@ export interface AgentData { error: number; degraded: number; }; + agents_per_privileges: { + root: number; + unprivileged: number; + }; agents_per_policy: number[]; agents_per_os: Array<{ name: string; @@ -89,6 +93,10 @@ const DEFAULT_AGENT_DATA = { agents_per_version: [], agents_per_os: [], upgrade_details: [], + agents_per_privileges: { + root: 0, + unprivileged: 0, + }, }; export const getAgentData = async ( @@ -159,6 +167,18 @@ export const getAgentData = async ( ], }, }, + privileges: { + filters: { + other_bucket_key: 'root', + filters: { + unprivileged: { + match: { + 'local_metadata.elastic.agent.unprivileged': true, + }, + }, + }, + }, + }, }, }, { signal: abortController.signal } @@ -176,6 +196,12 @@ export const getAgentData = async ( }) ); + const agentsPerPrivileges = { + root: (response?.aggregations?.privileges as any)?.buckets?.root?.doc_count ?? 0, + unprivileged: + (response?.aggregations?.privileges as any)?.buckets?.unprivileged?.doc_count ?? 0, + }; + const getAgentStatusesPerVersion = async (version: string) => { return await getAgentStatusForAgentPolicy( esClient, @@ -227,6 +253,7 @@ export const getAgentData = async ( agent_checkin_status: statuses, agents_per_policy: agentsPerPolicy, agents_per_version: agentsPerVersion, + agents_per_privileges: agentsPerPrivileges, agents_per_os: agentsPerOS, upgrade_details: upgradeDetails, }; diff --git a/x-pack/plugins/fleet/server/integration_tests/fleet_usage_telemetry.test.ts b/x-pack/plugins/fleet/server/integration_tests/fleet_usage_telemetry.test.ts index 430dc6f745ad9..dbce3c7f8b435 100644 --- a/x-pack/plugins/fleet/server/integration_tests/fleet_usage_telemetry.test.ts +++ b/x-pack/plugins/fleet/server/integration_tests/fleet_usage_telemetry.test.ts @@ -135,6 +135,7 @@ describe('fleet usage telemetry', () => { name: 'Ubuntu', version: '22.04.2 LTS (Jammy Jellyfish)', }, + elastic: { agent: { unprivileged: false } }, // Root agent }, components: [ { @@ -172,6 +173,7 @@ describe('fleet usage telemetry', () => { name: 'Ubuntu', version: '20.04.5 LTS (Focal Fossa)', }, + elastic: { agent: { unprivileged: true } }, // Non root agent }, components: [ { @@ -482,6 +484,10 @@ describe('fleet usage telemetry', () => { num_host_urls: 0, }, packages: [], + agents_per_privileges: { + root: 3, + unprivileged: 1, + }, agents_per_version: [ { version: '8.6.0', diff --git a/x-pack/plugins/fleet/server/saved_objects/index.ts b/x-pack/plugins/fleet/server/saved_objects/index.ts index 22b5aa3f5fddb..f74366d924c96 100644 --- a/x-pack/plugins/fleet/server/saved_objects/index.ts +++ b/x-pack/plugins/fleet/server/saved_objects/index.ts @@ -85,6 +85,7 @@ import { migratePackagePolicyEvictionsFromV81102, } from './migrations/security_solution/to_v8_11_0_2'; import { settingsV1 } from './model_versions/v1'; +import { packagePolicyV10OnWriteScanFix } from './model_versions/security_solution'; /* * Saved object types and mappings @@ -540,6 +541,14 @@ export const getSavedObjectTypes = ( }, ], }, + '10': { + changes: [ + { + type: 'data_backfill', + backfillFn: packagePolicyV10OnWriteScanFix, + }, + ], + }, }, migrations: { '7.10.0': migratePackagePolicyToV7100, diff --git a/x-pack/plugins/fleet/server/saved_objects/model_versions/security_solution/index.ts b/x-pack/plugins/fleet/server/saved_objects/model_versions/security_solution/index.ts new file mode 100644 index 0000000000000..780bc55f9cd3e --- /dev/null +++ b/x-pack/plugins/fleet/server/saved_objects/model_versions/security_solution/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 { packagePolicyV10OnWriteScanFix } from './v10_on_write_scan_fix'; diff --git a/x-pack/plugins/fleet/server/saved_objects/model_versions/security_solution/v10_on_write_scan_fix.test.ts b/x-pack/plugins/fleet/server/saved_objects/model_versions/security_solution/v10_on_write_scan_fix.test.ts new file mode 100644 index 0000000000000..37ca3dd6d4b0d --- /dev/null +++ b/x-pack/plugins/fleet/server/saved_objects/model_versions/security_solution/v10_on_write_scan_fix.test.ts @@ -0,0 +1,183 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license 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 { SavedObject } from '@kbn/core-saved-objects-api-server'; +import type { ModelVersionTestMigrator } from '@kbn/core-test-helpers-model-versions'; +import { createModelVersionTestMigrator } from '@kbn/core-test-helpers-model-versions'; + +import { getSavedObjectTypes } from '../..'; + +import type { PackagePolicy } from '../../../../common'; +import { PACKAGE_POLICY_SAVED_OBJECT_TYPE } from '../../../../common'; + +describe('backfill for modelVersion 10 - fix on_write_scan field', () => { + let migrator: ModelVersionTestMigrator; + let policyConfigSO: SavedObject; + + beforeEach(() => { + migrator = createModelVersionTestMigrator({ + type: getSavedObjectTypes()[PACKAGE_POLICY_SAVED_OBJECT_TYPE], + }); + + policyConfigSO = { + id: 'mock-saved-object-id', + attributes: { + name: 'Some Policy Name', + package: { + name: 'endpoint', + title: '', + version: '', + }, + id: 'endpoint', + policy_id: '', + enabled: true, + namespace: '', + revision: 0, + updated_at: '', + updated_by: '', + created_at: '', + created_by: '', + inputs: [ + { + type: 'endpoint', + enabled: true, + streams: [], + config: { + policy: { + value: { + windows: { + malware: { + mode: 'detect', + }, + antivirus_registration: { + enabled: true, + }, + }, + mac: { + malware: { + mode: 'detect', + }, + }, + linux: { + malware: { + mode: 'detect', + }, + }, + }, + }, + }, + }, + ], + }, + type: PACKAGE_POLICY_SAVED_OBJECT_TYPE, + references: [], + }; + }); + + describe('when updating to model version 10', () => { + it('should change `on_write_scan` from `true` to `false` if Malware is off', () => { + setMalwareMode(policyConfigSO, 'off'); + setOnWriteScan(policyConfigSO, true); + + const migratedPolicyConfigSO = migrator.migrate({ + document: policyConfigSO, + fromVersion: 9, + toVersion: 10, + }); + + expectOnWriteScanToBe(false, migratedPolicyConfigSO); + }); + + it('should not change `on_write_scan` if Malware is detect', () => { + setMalwareMode(policyConfigSO, 'detect'); + setOnWriteScan(policyConfigSO, true); + + const migratedPolicyConfigSO = migrator.migrate({ + document: policyConfigSO, + fromVersion: 9, + toVersion: 10, + }); + + expectOnWriteScanToBe(true, migratedPolicyConfigSO); + }); + + it('should not change `on_write_scan` if Malware is prevent', () => { + setMalwareMode(policyConfigSO, 'prevent'); + setOnWriteScan(policyConfigSO, true); + + const migratedPolicyConfigSO = migrator.migrate({ + document: policyConfigSO, + fromVersion: 9, + toVersion: 10, + }); + + expectOnWriteScanToBe(true, migratedPolicyConfigSO); + }); + }); + + describe('additional test: when updating from model version 5 to model version 10', () => { + it('should add `on_write_scan=false` if Malware is off', () => { + setMalwareMode(policyConfigSO, 'off'); + + const migratedPolicyConfigSO = migrator.migrate({ + document: policyConfigSO, + fromVersion: 5, + toVersion: 10, + }); + + expectOnWriteScanToBe(false, migratedPolicyConfigSO); + }); + + it('should add `on_write_scan=true` if Malware is detect', () => { + setMalwareMode(policyConfigSO, 'detect'); + + const migratedPolicyConfigSO = migrator.migrate({ + document: policyConfigSO, + fromVersion: 5, + toVersion: 10, + }); + + expectOnWriteScanToBe(true, migratedPolicyConfigSO); + }); + + it('should add `on_write_scan=true` if Malware is prevent', () => { + setMalwareMode(policyConfigSO, 'prevent'); + + const migratedPolicyConfigSO = migrator.migrate({ + document: policyConfigSO, + fromVersion: 5, + toVersion: 10, + }); + + expectOnWriteScanToBe(true, migratedPolicyConfigSO); + }); + }); + + const setMalwareMode = (so: SavedObject, level: 'off' | 'detect' | 'prevent') => { + const config = so.attributes.inputs[0].config?.policy.value; + + config.windows.malware.mode = level; + config.mac.malware.mode = level; + config.linux.malware.mode = level; + }; + + const setOnWriteScan = (so: SavedObject, value: boolean) => { + const config = so.attributes.inputs[0].config?.policy.value; + + config.windows.malware.on_write_scan = value; + config.mac.malware.on_write_scan = value; + config.linux.malware.on_write_scan = value; + }; + + const expectOnWriteScanToBe = (expectedValue: boolean, so: SavedObject) => { + const config = so.attributes.inputs[0].config?.policy.value; + + expect(config.windows.malware.on_write_scan).toBe(expectedValue); + expect(config.mac.malware.on_write_scan).toBe(expectedValue); + expect(config.linux.malware.on_write_scan).toBe(expectedValue); + }; +}); diff --git a/x-pack/plugins/fleet/server/saved_objects/model_versions/security_solution/v10_on_write_scan_fix.ts b/x-pack/plugins/fleet/server/saved_objects/model_versions/security_solution/v10_on_write_scan_fix.ts new file mode 100644 index 0000000000000..7f793f7980164 --- /dev/null +++ b/x-pack/plugins/fleet/server/saved_objects/model_versions/security_solution/v10_on_write_scan_fix.ts @@ -0,0 +1,42 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { + SavedObjectModelDataBackfillFn, + SavedObjectUnsanitizedDoc, +} from '@kbn/core-saved-objects-server'; + +import type { PackagePolicy } from '../../../../common'; + +export const packagePolicyV10OnWriteScanFix: SavedObjectModelDataBackfillFn< + PackagePolicy, + PackagePolicy +> = (packagePolicyDoc) => { + if (packagePolicyDoc.attributes.package?.name !== 'endpoint') { + return { attributes: packagePolicyDoc.attributes }; + } + + const updatedPackagePolicyDoc: SavedObjectUnsanitizedDoc = packagePolicyDoc; + + const input = updatedPackagePolicyDoc.attributes.inputs[0]; + + if (input && input.config) { + const policy = input.config.policy.value; + + if (policy.windows.malware.mode === 'off') { + policy.windows.malware.on_write_scan = false; + } + if (policy.mac.malware.mode === 'off') { + policy.mac.malware.on_write_scan = false; + } + if (policy.linux.malware.mode === 'off') { + policy.linux.malware.on_write_scan = false; + } + } + + return { attributes: updatedPackagePolicyDoc.attributes }; +}; diff --git a/x-pack/plugins/fleet/server/services/metrics/fetch_agent_metrics.ts b/x-pack/plugins/fleet/server/services/metrics/fetch_agent_metrics.ts index 5662a1a8fa1c8..ac5e692b9023e 100644 --- a/x-pack/plugins/fleet/server/services/metrics/fetch_agent_metrics.ts +++ b/x-pack/plugins/fleet/server/services/metrics/fetch_agent_metrics.ts @@ -64,6 +64,7 @@ export const fetchAgentMetrics = async ( upgrading_step: await getUpgradingSteps(esClient, abortController), unhealthy_reason: await getUnhealthyReason(esClient, abortController), }; + return usage; }; diff --git a/x-pack/plugins/fleet/server/services/metrics/fleet_metrics_task.ts b/x-pack/plugins/fleet/server/services/metrics/fleet_metrics_task.ts index 6b58decb4d109..0d1c0bd142169 100644 --- a/x-pack/plugins/fleet/server/services/metrics/fleet_metrics_task.ts +++ b/x-pack/plugins/fleet/server/services/metrics/fleet_metrics_task.ts @@ -186,7 +186,7 @@ export class FleetMetricsTask { this.wasStarted = true; try { - appContextService.getLogger().info(`Task ${this.taskId} scheduled with interval 1h`); + appContextService.getLogger().info(`Task ${this.taskId} scheduled with interval ${INTERVAL}`); await this.taskManager.ensureScheduled({ id: this.taskId, diff --git a/x-pack/plugins/fleet/server/services/telemetry/fleet_usage_sender.ts b/x-pack/plugins/fleet/server/services/telemetry/fleet_usage_sender.ts index f0a79a2633036..367d7f0ce0ff9 100644 --- a/x-pack/plugins/fleet/server/services/telemetry/fleet_usage_sender.ts +++ b/x-pack/plugins/fleet/server/services/telemetry/fleet_usage_sender.ts @@ -83,6 +83,7 @@ export class FleetUsageSender { const { agents_per_version: agentsPerVersion, agents_per_output_type: agentsPerOutputType, + agents_per_privileges: agentsPerPrivileges, upgrade_details: upgradeDetails, ...fleetUsageData } = usageData; @@ -92,6 +93,13 @@ export class FleetUsageSender { core.analytics.reportEvent(FLEET_USAGES_EVENT_TYPE, fleetUsageData); + appContextService + .getLogger() + .debug('Agents per privileges telemetry: ' + JSON.stringify(agentsPerPrivileges)); + core.analytics.reportEvent(FLEET_AGENTS_EVENT_TYPE, { + agents_per_privileges: agentsPerPrivileges, + }); + appContextService .getLogger() .debug('Agents per version telemetry: ' + JSON.stringify(agentsPerVersion)); diff --git a/x-pack/plugins/fleet/server/services/telemetry/fleet_usages_schema.ts b/x-pack/plugins/fleet/server/services/telemetry/fleet_usages_schema.ts index 5deaa97b02f3f..574c5dac1ad6a 100644 --- a/x-pack/plugins/fleet/server/services/telemetry/fleet_usages_schema.ts +++ b/x-pack/plugins/fleet/server/services/telemetry/fleet_usages_schema.ts @@ -135,6 +135,26 @@ export const fleetAgentsSchema: RootSchema = { }, }, }, + agents_per_privileges: { + _meta: { + description: 'Agents per privileges telemetry', + optional: true, + }, + properties: { + root: { + type: 'long', + _meta: { + description: 'Number of agents running with root privilege', + }, + }, + unprivileged: { + type: 'long', + _meta: { + description: 'Number of agents running without root privilege', + }, + }, + }, + }, upgrade_details: { _meta: { description: 'Agent upgrade details telemetry', diff --git a/x-pack/plugins/fleet/server/types/models/agent.ts b/x-pack/plugins/fleet/server/types/models/agent.ts index aed1632929e3a..b8fd7ed8bf82f 100644 --- a/x-pack/plugins/fleet/server/types/models/agent.ts +++ b/x-pack/plugins/fleet/server/types/models/agent.ts @@ -32,12 +32,14 @@ export const NewAgentActionSchema = schema.oneOf([ schema.object({ type: schema.oneOf([schema.literal('SETTINGS')]), data: schema.object({ - log_level: schema.oneOf([ - schema.literal('debug'), - schema.literal('info'), - schema.literal('warning'), - schema.literal('error'), - ]), + log_level: schema.nullable( + schema.oneOf([ + schema.literal('debug'), + schema.literal('info'), + schema.literal('warning'), + schema.literal('error'), + ]) + ), }), }), ]); diff --git a/x-pack/plugins/index_management/server/routes/api/inference_models/register_get_route.ts b/x-pack/plugins/index_management/server/routes/api/inference_models/register_get_route.ts index 68f385228f776..4709abadc3345 100644 --- a/x-pack/plugins/index_management/server/routes/api/inference_models/register_get_route.ts +++ b/x-pack/plugins/index_management/server/routes/api/inference_models/register_get_route.ts @@ -21,15 +21,15 @@ export function registerGetAllRoute({ router, lib: { handleEsError } }: RouteDep // TODO: Use the client's built-in function rather than the transport when it's available try { - const { models } = await client.asCurrentUser.transport.request<{ - models: InferenceAPIConfigResponse[]; + const { endpoints } = await client.asCurrentUser.transport.request<{ + endpoints: InferenceAPIConfigResponse[]; }>({ method: 'GET', path: `/_inference/_all`, }); return response.ok({ - body: models, + body: endpoints, }); } catch (error) { return handleEsError({ error, response }); diff --git a/x-pack/plugins/observability_solution/apm/public/components/app/transaction_details/waterfall_with_summary/waterfall_container/waterfall/waterfall_item.tsx b/x-pack/plugins/observability_solution/apm/public/components/app/transaction_details/waterfall_with_summary/waterfall_container/waterfall/waterfall_item.tsx index ed21a170c6a90..6260c37ffdc5a 100644 --- a/x-pack/plugins/observability_solution/apm/public/components/app/transaction_details/waterfall_with_summary/waterfall_container/waterfall/waterfall_item.tsx +++ b/x-pack/plugins/observability_solution/apm/public/components/app/transaction_details/waterfall_with_summary/waterfall_container/waterfall/waterfall_item.tsx @@ -125,8 +125,10 @@ interface IWaterfallItemProps { function PrefixIcon({ item }: { item: IWaterfallSpanOrTransaction }) { switch (item.docType) { case 'span': { + const spanType = item.doc.span.type || ''; + // icon for database spans - const isDbType = item.doc.span.type.startsWith('db'); + const isDbType = spanType.startsWith('db'); if (isDbType) { return ; } diff --git a/x-pack/plugins/observability_solution/apm/server/assistant_functions/get_apm_dataset_info.ts b/x-pack/plugins/observability_solution/apm/server/assistant_functions/get_apm_dataset_info.ts index e0f3f82128ddd..72fb4c8c7d200 100644 --- a/x-pack/plugins/observability_solution/apm/server/assistant_functions/get_apm_dataset_info.ts +++ b/x-pack/plugins/observability_solution/apm/server/assistant_functions/get_apm_dataset_info.ts @@ -24,7 +24,6 @@ export function registerGetApmDatasetInfoFunction({ description: `Use this function to get information about APM data.`, parameters: { type: 'object', - additionalProperties: false, properties: { start: { type: 'string', @@ -96,6 +95,15 @@ export function registerGetApmDatasetInfoFunction({ ); }); + if (!Object.values(availableIndices).flat().length) { + return { + content: { + fields: [], + description: 'There is no APM data available', + }, + }; + } + return { content: { fields: [ diff --git a/x-pack/plugins/observability_solution/apm/server/lib/apm_telemetry/collect_data_telemetry/tasks.ts b/x-pack/plugins/observability_solution/apm/server/lib/apm_telemetry/collect_data_telemetry/tasks.ts index 570328da84ea0..7bf03245d039e 100644 --- a/x-pack/plugins/observability_solution/apm/server/lib/apm_telemetry/collect_data_telemetry/tasks.ts +++ b/x-pack/plugins/observability_solution/apm/server/lib/apm_telemetry/collect_data_telemetry/tasks.ts @@ -230,10 +230,9 @@ export const tasks: TelemetryTask[] = [ { terms: { script: ` - if (doc['transaction.type'].value == 'page-load' && doc['user_agent.name'].size() > 0) { - return doc['user_agent.name'].value; + if ($('transaction.type', '') == 'page-load') { + return $('user_agent.name', null); } - return null; `, missing_bucket: true, @@ -242,7 +241,7 @@ export const tasks: TelemetryTask[] = [ // transaction.root { terms: { - script: `return doc['parent.id'].size() == 0`, + script: `return $('parent.id', '') == ''`, missing_bucket: true, }, }, @@ -259,8 +258,8 @@ export const tasks: TelemetryTask[] = [ { terms: { script: ` - if (doc['transaction.type'].value == 'page-load' && doc['client.geo.country_iso_code'].size() > 0) { - return doc['client.geo.country_iso_code'].value; + if ($('transaction.type', '') == 'page-load') { + return $('client.geo.country_iso_code', null); } return null; `, diff --git a/x-pack/plugins/observability_solution/apm/server/lib/helpers/create_es_client/create_apm_event_client/index.test.ts b/x-pack/plugins/observability_solution/apm/server/lib/helpers/create_es_client/create_apm_event_client/index.test.ts index 43b31c588f422..9cab31e30af64 100644 --- a/x-pack/plugins/observability_solution/apm/server/lib/helpers/create_es_client/create_apm_event_client/index.test.ts +++ b/x-pack/plugins/observability_solution/apm/server/lib/helpers/create_es_client/create_apm_event_client/index.test.ts @@ -74,7 +74,7 @@ describe('APMEventClient', () => { resolve(undefined); }, 100); }); - incomingRequest.abort(); + void incomingRequest.abort(); }, 100); }); diff --git a/x-pack/plugins/observability_solution/apm/server/routes/metrics/__snapshots__/queries.test.ts.snap b/x-pack/plugins/observability_solution/apm/server/routes/metrics/__snapshots__/queries.test.ts.snap index 44e4c6335ec7c..3fac4d595a274 100644 --- a/x-pack/plugins/observability_solution/apm/server/routes/metrics/__snapshots__/queries.test.ts.snap +++ b/x-pack/plugins/observability_solution/apm/server/routes/metrics/__snapshots__/queries.test.ts.snap @@ -206,15 +206,14 @@ Object { */ double CGROUP_LIMIT_MAX_VALUE = 9223372036854771712L; - String limitKey = 'system.process.cgroup.memory.mem.limit.bytes'; - - //Should use cgropLimit when value is not empty and not equals to the max limit value. - boolean useCgroupLimit = doc.containsKey(limitKey) && !doc[limitKey].empty && doc[limitKey].value != CGROUP_LIMIT_MAX_VALUE; - - double total = useCgroupLimit ? doc[limitKey].value : doc['system.memory.total'].value; - - double used = doc['system.process.cgroup.memory.mem.usage.bytes'].value; - + //Should use cgroupLimit when value is not empty and not equals to the max limit value. + double cgroupLimit = $('system.process.cgroup.memory.mem.limit.bytes', 0); + double total = (double)((cgroupLimit != 0 && cgroupLimit != CGROUP_LIMIT_MAX_VALUE) ? cgroupLimit : $('system.memory.total', 0)); + if (total <= 0) { + return null; + } + + double used = (double)$('system.process.cgroup.memory.mem.usage.bytes', 0); return used / total; ", }, @@ -231,15 +230,14 @@ Object { */ double CGROUP_LIMIT_MAX_VALUE = 9223372036854771712L; - String limitKey = 'system.process.cgroup.memory.mem.limit.bytes'; - - //Should use cgropLimit when value is not empty and not equals to the max limit value. - boolean useCgroupLimit = doc.containsKey(limitKey) && !doc[limitKey].empty && doc[limitKey].value != CGROUP_LIMIT_MAX_VALUE; - - double total = useCgroupLimit ? doc[limitKey].value : doc['system.memory.total'].value; - - double used = doc['system.process.cgroup.memory.mem.usage.bytes'].value; + //Should use cgroupLimit when value is not empty and not equals to the max limit value. + double cgroupLimit = $('system.process.cgroup.memory.mem.limit.bytes', 0); + double total = (double)((cgroupLimit != 0 && cgroupLimit != CGROUP_LIMIT_MAX_VALUE) ? cgroupLimit : $('system.memory.total', 0)); + if (total <= 0) { + return null; + } + double used = (double)$('system.process.cgroup.memory.mem.usage.bytes', 0); return used / total; ", }, @@ -258,15 +256,14 @@ Object { */ double CGROUP_LIMIT_MAX_VALUE = 9223372036854771712L; - String limitKey = 'system.process.cgroup.memory.mem.limit.bytes'; - - //Should use cgropLimit when value is not empty and not equals to the max limit value. - boolean useCgroupLimit = doc.containsKey(limitKey) && !doc[limitKey].empty && doc[limitKey].value != CGROUP_LIMIT_MAX_VALUE; - - double total = useCgroupLimit ? doc[limitKey].value : doc['system.memory.total'].value; - - double used = doc['system.process.cgroup.memory.mem.usage.bytes'].value; + //Should use cgroupLimit when value is not empty and not equals to the max limit value. + double cgroupLimit = $('system.process.cgroup.memory.mem.limit.bytes', 0); + double total = (double)((cgroupLimit != 0 && cgroupLimit != CGROUP_LIMIT_MAX_VALUE) ? cgroupLimit : $('system.memory.total', 0)); + if (total <= 0) { + return null; + } + double used = (double)$('system.process.cgroup.memory.mem.usage.bytes', 0); return used / total; ", }, @@ -283,15 +280,14 @@ Object { */ double CGROUP_LIMIT_MAX_VALUE = 9223372036854771712L; - String limitKey = 'system.process.cgroup.memory.mem.limit.bytes'; - - //Should use cgropLimit when value is not empty and not equals to the max limit value. - boolean useCgroupLimit = doc.containsKey(limitKey) && !doc[limitKey].empty && doc[limitKey].value != CGROUP_LIMIT_MAX_VALUE; - - double total = useCgroupLimit ? doc[limitKey].value : doc['system.memory.total'].value; - - double used = doc['system.process.cgroup.memory.mem.usage.bytes'].value; + //Should use cgroupLimit when value is not empty and not equals to the max limit value. + double cgroupLimit = $('system.process.cgroup.memory.mem.limit.bytes', 0); + double total = (double)((cgroupLimit != 0 && cgroupLimit != CGROUP_LIMIT_MAX_VALUE) ? cgroupLimit : $('system.memory.total', 0)); + if (total <= 0) { + return null; + } + double used = (double)$('system.process.cgroup.memory.mem.usage.bytes', 0); return used / total; ", }, @@ -756,15 +752,14 @@ Object { */ double CGROUP_LIMIT_MAX_VALUE = 9223372036854771712L; - String limitKey = 'system.process.cgroup.memory.mem.limit.bytes'; - - //Should use cgropLimit when value is not empty and not equals to the max limit value. - boolean useCgroupLimit = doc.containsKey(limitKey) && !doc[limitKey].empty && doc[limitKey].value != CGROUP_LIMIT_MAX_VALUE; - - double total = useCgroupLimit ? doc[limitKey].value : doc['system.memory.total'].value; - - double used = doc['system.process.cgroup.memory.mem.usage.bytes'].value; + //Should use cgroupLimit when value is not empty and not equals to the max limit value. + double cgroupLimit = $('system.process.cgroup.memory.mem.limit.bytes', 0); + double total = (double)((cgroupLimit != 0 && cgroupLimit != CGROUP_LIMIT_MAX_VALUE) ? cgroupLimit : $('system.memory.total', 0)); + if (total <= 0) { + return null; + } + double used = (double)$('system.process.cgroup.memory.mem.usage.bytes', 0); return used / total; ", }, @@ -781,15 +776,14 @@ Object { */ double CGROUP_LIMIT_MAX_VALUE = 9223372036854771712L; - String limitKey = 'system.process.cgroup.memory.mem.limit.bytes'; - - //Should use cgropLimit when value is not empty and not equals to the max limit value. - boolean useCgroupLimit = doc.containsKey(limitKey) && !doc[limitKey].empty && doc[limitKey].value != CGROUP_LIMIT_MAX_VALUE; - - double total = useCgroupLimit ? doc[limitKey].value : doc['system.memory.total'].value; - - double used = doc['system.process.cgroup.memory.mem.usage.bytes'].value; + //Should use cgroupLimit when value is not empty and not equals to the max limit value. + double cgroupLimit = $('system.process.cgroup.memory.mem.limit.bytes', 0); + double total = (double)((cgroupLimit != 0 && cgroupLimit != CGROUP_LIMIT_MAX_VALUE) ? cgroupLimit : $('system.memory.total', 0)); + if (total <= 0) { + return null; + } + double used = (double)$('system.process.cgroup.memory.mem.usage.bytes', 0); return used / total; ", }, @@ -808,15 +802,14 @@ Object { */ double CGROUP_LIMIT_MAX_VALUE = 9223372036854771712L; - String limitKey = 'system.process.cgroup.memory.mem.limit.bytes'; - - //Should use cgropLimit when value is not empty and not equals to the max limit value. - boolean useCgroupLimit = doc.containsKey(limitKey) && !doc[limitKey].empty && doc[limitKey].value != CGROUP_LIMIT_MAX_VALUE; - - double total = useCgroupLimit ? doc[limitKey].value : doc['system.memory.total'].value; - - double used = doc['system.process.cgroup.memory.mem.usage.bytes'].value; + //Should use cgroupLimit when value is not empty and not equals to the max limit value. + double cgroupLimit = $('system.process.cgroup.memory.mem.limit.bytes', 0); + double total = (double)((cgroupLimit != 0 && cgroupLimit != CGROUP_LIMIT_MAX_VALUE) ? cgroupLimit : $('system.memory.total', 0)); + if (total <= 0) { + return null; + } + double used = (double)$('system.process.cgroup.memory.mem.usage.bytes', 0); return used / total; ", }, @@ -833,15 +826,14 @@ Object { */ double CGROUP_LIMIT_MAX_VALUE = 9223372036854771712L; - String limitKey = 'system.process.cgroup.memory.mem.limit.bytes'; - - //Should use cgropLimit when value is not empty and not equals to the max limit value. - boolean useCgroupLimit = doc.containsKey(limitKey) && !doc[limitKey].empty && doc[limitKey].value != CGROUP_LIMIT_MAX_VALUE; - - double total = useCgroupLimit ? doc[limitKey].value : doc['system.memory.total'].value; - - double used = doc['system.process.cgroup.memory.mem.usage.bytes'].value; + //Should use cgroupLimit when value is not empty and not equals to the max limit value. + double cgroupLimit = $('system.process.cgroup.memory.mem.limit.bytes', 0); + double total = (double)((cgroupLimit != 0 && cgroupLimit != CGROUP_LIMIT_MAX_VALUE) ? cgroupLimit : $('system.memory.total', 0)); + if (total <= 0) { + return null; + } + double used = (double)$('system.process.cgroup.memory.mem.usage.bytes', 0); return used / total; ", }, @@ -1302,15 +1294,14 @@ Object { */ double CGROUP_LIMIT_MAX_VALUE = 9223372036854771712L; - String limitKey = 'system.process.cgroup.memory.mem.limit.bytes'; - - //Should use cgropLimit when value is not empty and not equals to the max limit value. - boolean useCgroupLimit = doc.containsKey(limitKey) && !doc[limitKey].empty && doc[limitKey].value != CGROUP_LIMIT_MAX_VALUE; - - double total = useCgroupLimit ? doc[limitKey].value : doc['system.memory.total'].value; - - double used = doc['system.process.cgroup.memory.mem.usage.bytes'].value; + //Should use cgroupLimit when value is not empty and not equals to the max limit value. + double cgroupLimit = $('system.process.cgroup.memory.mem.limit.bytes', 0); + double total = (double)((cgroupLimit != 0 && cgroupLimit != CGROUP_LIMIT_MAX_VALUE) ? cgroupLimit : $('system.memory.total', 0)); + if (total <= 0) { + return null; + } + double used = (double)$('system.process.cgroup.memory.mem.usage.bytes', 0); return used / total; ", }, @@ -1327,15 +1318,14 @@ Object { */ double CGROUP_LIMIT_MAX_VALUE = 9223372036854771712L; - String limitKey = 'system.process.cgroup.memory.mem.limit.bytes'; - - //Should use cgropLimit when value is not empty and not equals to the max limit value. - boolean useCgroupLimit = doc.containsKey(limitKey) && !doc[limitKey].empty && doc[limitKey].value != CGROUP_LIMIT_MAX_VALUE; - - double total = useCgroupLimit ? doc[limitKey].value : doc['system.memory.total'].value; - - double used = doc['system.process.cgroup.memory.mem.usage.bytes'].value; + //Should use cgroupLimit when value is not empty and not equals to the max limit value. + double cgroupLimit = $('system.process.cgroup.memory.mem.limit.bytes', 0); + double total = (double)((cgroupLimit != 0 && cgroupLimit != CGROUP_LIMIT_MAX_VALUE) ? cgroupLimit : $('system.memory.total', 0)); + if (total <= 0) { + return null; + } + double used = (double)$('system.process.cgroup.memory.mem.usage.bytes', 0); return used / total; ", }, @@ -1354,15 +1344,14 @@ Object { */ double CGROUP_LIMIT_MAX_VALUE = 9223372036854771712L; - String limitKey = 'system.process.cgroup.memory.mem.limit.bytes'; - - //Should use cgropLimit when value is not empty and not equals to the max limit value. - boolean useCgroupLimit = doc.containsKey(limitKey) && !doc[limitKey].empty && doc[limitKey].value != CGROUP_LIMIT_MAX_VALUE; - - double total = useCgroupLimit ? doc[limitKey].value : doc['system.memory.total'].value; - - double used = doc['system.process.cgroup.memory.mem.usage.bytes'].value; + //Should use cgroupLimit when value is not empty and not equals to the max limit value. + double cgroupLimit = $('system.process.cgroup.memory.mem.limit.bytes', 0); + double total = (double)((cgroupLimit != 0 && cgroupLimit != CGROUP_LIMIT_MAX_VALUE) ? cgroupLimit : $('system.memory.total', 0)); + if (total <= 0) { + return null; + } + double used = (double)$('system.process.cgroup.memory.mem.usage.bytes', 0); return used / total; ", }, @@ -1379,15 +1368,14 @@ Object { */ double CGROUP_LIMIT_MAX_VALUE = 9223372036854771712L; - String limitKey = 'system.process.cgroup.memory.mem.limit.bytes'; - - //Should use cgropLimit when value is not empty and not equals to the max limit value. - boolean useCgroupLimit = doc.containsKey(limitKey) && !doc[limitKey].empty && doc[limitKey].value != CGROUP_LIMIT_MAX_VALUE; - - double total = useCgroupLimit ? doc[limitKey].value : doc['system.memory.total'].value; - - double used = doc['system.process.cgroup.memory.mem.usage.bytes'].value; + //Should use cgroupLimit when value is not empty and not equals to the max limit value. + double cgroupLimit = $('system.process.cgroup.memory.mem.limit.bytes', 0); + double total = (double)((cgroupLimit != 0 && cgroupLimit != CGROUP_LIMIT_MAX_VALUE) ? cgroupLimit : $('system.memory.total', 0)); + if (total <= 0) { + return null; + } + double used = (double)$('system.process.cgroup.memory.mem.usage.bytes', 0); return used / total; ", }, diff --git a/x-pack/plugins/observability_solution/apm/server/routes/metrics/by_agent/shared/memory/index.ts b/x-pack/plugins/observability_solution/apm/server/routes/metrics/by_agent/shared/memory/index.ts index 6fe3475abec84..af3e7301f8e61 100644 --- a/x-pack/plugins/observability_solution/apm/server/routes/metrics/by_agent/shared/memory/index.ts +++ b/x-pack/plugins/observability_solution/apm/server/routes/metrics/by_agent/shared/memory/index.ts @@ -56,12 +56,11 @@ export const systemMemory = { script: { lang: 'painless', source: ` - if(doc.containsKey('${METRIC_SYSTEM_FREE_MEMORY}') && doc.containsKey('${METRIC_SYSTEM_TOTAL_MEMORY}')){ - double freeMemoryValue = doc['${METRIC_SYSTEM_FREE_MEMORY}'].value; - double totalMemoryValue = doc['${METRIC_SYSTEM_TOTAL_MEMORY}'].value; - return 1 - freeMemoryValue / totalMemoryValue + def freeMemory = (double)$('${METRIC_SYSTEM_FREE_MEMORY}', 0); + def totalMemory = (double)$('${METRIC_SYSTEM_TOTAL_MEMORY}', -1); + if (freeMemory >= 0 && totalMemory > 0) { + return 1 - freeMemory / totalMemory; } - return null; `, }, @@ -87,15 +86,14 @@ export const cgroupMemory = { */ double CGROUP_LIMIT_MAX_VALUE = 9223372036854771712L; - String limitKey = '${METRIC_CGROUP_MEMORY_LIMIT_BYTES}'; - - //Should use cgropLimit when value is not empty and not equals to the max limit value. - boolean useCgroupLimit = doc.containsKey(limitKey) && !doc[limitKey].empty && doc[limitKey].value != CGROUP_LIMIT_MAX_VALUE; - - double total = useCgroupLimit ? doc[limitKey].value : doc['${METRIC_SYSTEM_TOTAL_MEMORY}'].value; - - double used = doc['${METRIC_CGROUP_MEMORY_USAGE_BYTES}'].value; + //Should use cgroupLimit when value is not empty and not equals to the max limit value. + double cgroupLimit = $('${METRIC_CGROUP_MEMORY_LIMIT_BYTES}', 0); + double total = (double)((cgroupLimit != 0 && cgroupLimit != CGROUP_LIMIT_MAX_VALUE) ? cgroupLimit : $('${METRIC_SYSTEM_TOTAL_MEMORY}', 0)); + if (total <= 0) { + return null; + } + double used = (double)$('${METRIC_CGROUP_MEMORY_USAGE_BYTES}', 0); return used / total; `, }, diff --git a/x-pack/plugins/observability_solution/apm/server/routes/metrics/serverless/get_compute_usage_chart.ts b/x-pack/plugins/observability_solution/apm/server/routes/metrics/serverless/get_compute_usage_chart.ts index 60ff09131a868..3cdb1469295a9 100644 --- a/x-pack/plugins/observability_solution/apm/server/routes/metrics/serverless/get_compute_usage_chart.ts +++ b/x-pack/plugins/observability_solution/apm/server/routes/metrics/serverless/get_compute_usage_chart.ts @@ -25,7 +25,7 @@ import { convertComputeUsageToGbSec } from './helper'; export const computeUsageAvgScript = { avg: { - script: `return doc['${METRIC_SYSTEM_TOTAL_MEMORY}'].value * doc['${FAAS_BILLED_DURATION}'].value`, + script: `return $('${METRIC_SYSTEM_TOTAL_MEMORY}', 0) * $('${FAAS_BILLED_DURATION}', 0)`, }, }; diff --git a/x-pack/plugins/observability_solution/apm/server/routes/service_map/fetch_service_paths_from_trace_ids.ts b/x-pack/plugins/observability_solution/apm/server/routes/service_map/fetch_service_paths_from_trace_ids.ts index ad37caa865fb2..5467606954844 100644 --- a/x-pack/plugins/observability_solution/apm/server/routes/service_map/fetch_service_paths_from_trace_ids.ts +++ b/x-pack/plugins/observability_solution/apm/server/routes/service_map/fetch_service_paths_from_trace_ids.ts @@ -76,18 +76,18 @@ export async function fetchServicePathsFromTraceIds({ map_script: { lang: 'painless', source: `def id; - if (!doc['span.id'].empty) { - id = doc['span.id'].value; - } else { - id = doc['transaction.id'].value; + id = $('span.id', null); + if (id == null) { + id = $('transaction.id', null); } def copy = new HashMap(); copy.id = id; for(key in state.fieldsToCopy) { - if (!doc[key].empty) { - copy[key] = doc[key].value; + def value = $(key, null); + if (value != null) { + copy[key] = value; } } diff --git a/x-pack/plugins/observability_solution/apm/server/routes/traces/get_aggregated_critical_path.ts b/x-pack/plugins/observability_solution/apm/server/routes/traces/get_aggregated_critical_path.ts index f382085ad8dcc..6a3af27aa838d 100644 --- a/x-pack/plugins/observability_solution/apm/server/routes/traces/get_aggregated_critical_path.ts +++ b/x-pack/plugins/observability_solution/apm/server/routes/traces/get_aggregated_critical_path.ts @@ -123,38 +123,39 @@ export async function getAggregatedCriticalPath({ double duration; def operationMetadata = [ - "service.name": doc['service.name'].value, - "processor.event": doc['processor.event'].value, - "agent.name": doc['agent.name'].value + "service.name": $('service.name', ''), + "processor.event": $('processor.event', ''), + "agent.name": $('agent.name', '') ]; - def isSpan = !doc['span.id'].empty && !doc['span.name'].empty; - - if (isSpan) { - id = doc['span.id'].value; - operationMetadata.put('span.name', doc['span.name'].value); - if (!doc['span.type'].empty) { - operationMetadata.put('span.type', doc['span.type'].value); + def spanName = $('span.name', null); + id = $('span.id', null); + if (id != null && spanName != null) { + operationMetadata.put('span.name', spanName); + def spanType = $('span.type', ''); + if (spanType != '') { + operationMetadata.put('span.type', spanType); } - if (!doc['span.subtype'].empty) { - operationMetadata.put('span.subtype', doc['span.subtype'].value); + def spanSubtype = $('span.subtype', ''); + if (spanSubtype != '') { + operationMetadata.put('span.subtype', spanSubtype); } - duration = doc['span.duration.us'].value; + duration = $('span.duration.us', 0); } else { - id = doc['transaction.id'].value; - operationMetadata.put('transaction.name', doc['transaction.name'].value); - operationMetadata.put('transaction.type', doc['transaction.type'].value); - duration = doc['transaction.duration.us'].value; + id = $('transaction.id', ''); + operationMetadata.put('transaction.name', $('transaction.name', '')); + operationMetadata.put('transaction.type', $('transaction.type', '')); + duration = $('transaction.duration.us', 0); } String operationId = toHash(operationMetadata); def map = [ - "traceId": doc['trace.id'].value, + "traceId": $('trace.id', ''), "id": id, - "parentId": doc['parent.id'].empty ? null : doc['parent.id'].value, + "parentId": $('parent.id', null), "operationId": operationId, - "timestamp": doc['timestamp.us'].value, + "timestamp": $('timestamp.us', 0), "duration": duration ]; diff --git a/x-pack/plugins/observability_solution/apm/server/routes/traces/get_trace_items.ts b/x-pack/plugins/observability_solution/apm/server/routes/traces/get_trace_items.ts index da84cc208eddf..d38a49745653a 100644 --- a/x-pack/plugins/observability_solution/apm/server/routes/traces/get_trace_items.ts +++ b/x-pack/plugins/observability_solution/apm/server/routes/traces/get_trace_items.ts @@ -273,7 +273,7 @@ async function getTraceDocsPerPage({ type: 'number', script: { lang: 'painless', - source: `if (doc['${TRANSACTION_DURATION}'].size() > 0) { return doc['${TRANSACTION_DURATION}'].value } else { return doc['${SPAN_DURATION}'].value }`, + source: `$('${TRANSACTION_DURATION}', $('${SPAN_DURATION}', 0))`, }, order: 'desc', }, diff --git a/x-pack/plugins/observability_solution/asset_manager/common/constants_entities.ts b/x-pack/plugins/observability_solution/asset_manager/common/constants_entities.ts new file mode 100644 index 0000000000000..aeeea398220a0 --- /dev/null +++ b/x-pack/plugins/observability_solution/asset_manager/common/constants_entities.ts @@ -0,0 +1,13 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export const ENTITY_VERSION = 'v1'; +export const ENTITY_BASE_PREFIX = `.entities-observability.summary-${ENTITY_VERSION}`; +export const ENTITY_TRANSFORM_PREFIX = `entities-observability-summary-${ENTITY_VERSION}`; +export const ENTITY_DEFAULT_FREQUENCY = '1m'; +export const ENTITY_DEFAULT_SYNC_DELAY = '60s'; +export const ENTITY_API_PREFIX = '/api/entities'; diff --git a/x-pack/plugins/observability_solution/asset_manager/server/lib/entities/create_and_install_ingest_pipeline.ts b/x-pack/plugins/observability_solution/asset_manager/server/lib/entities/create_and_install_ingest_pipeline.ts new file mode 100644 index 0000000000000..e4d7116b95562 --- /dev/null +++ b/x-pack/plugins/observability_solution/asset_manager/server/lib/entities/create_and_install_ingest_pipeline.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 { ElasticsearchClient, Logger } from '@kbn/core/server'; +import { EntityDefinition } from '@kbn/entities-schema'; +import { generateProcessors } from './ingest_pipeline/generate_processors'; +import { retryTransientEsErrors } from './helpers/retry'; +import { EntitySecurityException } from './errors/entity_security_exception'; +import { generateIngestPipelineId } from './ingest_pipeline/generate_ingest_pipeline_id'; + +export async function createAndInstallIngestPipeline( + esClient: ElasticsearchClient, + definition: EntityDefinition, + logger: Logger +) { + const processors = generateProcessors(definition); + const id = generateIngestPipelineId(definition); + try { + await retryTransientEsErrors( + () => + esClient.ingest.putPipeline({ + id, + processors, + }), + { logger } + ); + } catch (e) { + logger.error(`Cannot create entity ingest pipeline for [${definition.id}] entity defintion`); + if (e.meta?.body?.error?.type === 'security_exception') { + throw new EntitySecurityException(e.meta.body.error.reason, definition); + } + throw e; + } + return id; +} diff --git a/x-pack/plugins/observability_solution/asset_manager/server/lib/entities/create_and_install_transform.ts b/x-pack/plugins/observability_solution/asset_manager/server/lib/entities/create_and_install_transform.ts new file mode 100644 index 0000000000000..f8cd02250d898 --- /dev/null +++ b/x-pack/plugins/observability_solution/asset_manager/server/lib/entities/create_and_install_transform.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 { ElasticsearchClient, Logger } from '@kbn/core/server'; +import { EntityDefinition } from '@kbn/entities-schema'; +import { generateTransform } from './transform/generate_transform'; +import { retryTransientEsErrors } from './helpers/retry'; +import { EntitySecurityException } from './errors/entity_security_exception'; + +export async function createAndInstallTransform( + esClient: ElasticsearchClient, + definition: EntityDefinition, + logger: Logger +) { + const transform = generateTransform(definition); + try { + await retryTransientEsErrors(() => esClient.transform.putTransform(transform), { logger }); + } catch (e) { + logger.error(`Cannot create entity transform for [${definition.id}] entity definition`); + if (e.meta?.body?.error?.type === 'security_exception') { + throw new EntitySecurityException(e.meta.body.error.reason, definition); + } + throw e; + } + return transform.transform_id; +} diff --git a/x-pack/plugins/observability_solution/asset_manager/server/lib/entities/delete_entity_definition.ts b/x-pack/plugins/observability_solution/asset_manager/server/lib/entities/delete_entity_definition.ts new file mode 100644 index 0000000000000..1067f33abaca3 --- /dev/null +++ b/x-pack/plugins/observability_solution/asset_manager/server/lib/entities/delete_entity_definition.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 { Logger, SavedObjectsClientContract } from '@kbn/core/server'; +import { EntityDefinition } from '@kbn/entities-schema'; +import { SO_ENTITY_DEFINITION_TYPE } from '../../saved_objects'; +import { EntityDefinitionNotFound } from './errors/entity_not_found'; + +export async function deleteEntityDefinition( + soClient: SavedObjectsClientContract, + definition: EntityDefinition, + logger: Logger +) { + const response = await soClient.find({ + type: SO_ENTITY_DEFINITION_TYPE, + page: 1, + perPage: 1, + filter: `${SO_ENTITY_DEFINITION_TYPE}.attributes.id:(${definition.id})`, + }); + + if (response.total === 0) { + logger.error(`Unable to delete entity definition [${definition.id}] because it doesn't exist.`); + throw new EntityDefinitionNotFound(`Entity defintion with [${definition.id}] not found.`); + } + + await soClient.delete(SO_ENTITY_DEFINITION_TYPE, response.saved_objects[0].id); +} diff --git a/x-pack/plugins/observability_solution/asset_manager/server/lib/entities/delete_index.ts b/x-pack/plugins/observability_solution/asset_manager/server/lib/entities/delete_index.ts new file mode 100644 index 0000000000000..7df6867115bbe --- /dev/null +++ b/x-pack/plugins/observability_solution/asset_manager/server/lib/entities/delete_index.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 { ElasticsearchClient, Logger } from '@kbn/core/server'; +import { EntityDefinition } from '@kbn/entities-schema'; +import { generateIndexName } from './helpers/generate_index_name'; + +export async function deleteIndex( + esClient: ElasticsearchClient, + definition: EntityDefinition, + logger: Logger +) { + const indexName = generateIndexName(definition); + try { + await esClient.indices.delete({ index: indexName, ignore_unavailable: true }); + } catch (e) { + logger.error(`Unable to remove entity defintion index [${definition.id}}]`); + throw e; + } +} diff --git a/x-pack/plugins/observability_solution/asset_manager/server/lib/entities/delete_ingest_pipeline.ts b/x-pack/plugins/observability_solution/asset_manager/server/lib/entities/delete_ingest_pipeline.ts new file mode 100644 index 0000000000000..1e42282369ef3 --- /dev/null +++ b/x-pack/plugins/observability_solution/asset_manager/server/lib/entities/delete_ingest_pipeline.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 { ElasticsearchClient, Logger } from '@kbn/core/server'; +import { EntityDefinition } from '@kbn/entities-schema'; +import { generateIngestPipelineId } from './ingest_pipeline/generate_ingest_pipeline_id'; +import { retryTransientEsErrors } from './helpers/retry'; + +export async function deleteIngestPipeline( + esClient: ElasticsearchClient, + definition: EntityDefinition, + logger: Logger +) { + const pipelineId = generateIngestPipelineId(definition); + try { + await retryTransientEsErrors(() => + esClient.ingest.deletePipeline({ id: pipelineId }, { ignore: [404] }) + ); + } catch (e) { + logger.error(`Unable to delete ingest pipeline [${pipelineId}]`); + throw e; + } +} diff --git a/x-pack/plugins/observability_solution/asset_manager/server/lib/entities/errors/entity_id_conflict_error.ts b/x-pack/plugins/observability_solution/asset_manager/server/lib/entities/errors/entity_id_conflict_error.ts new file mode 100644 index 0000000000000..5108ca31ed548 --- /dev/null +++ b/x-pack/plugins/observability_solution/asset_manager/server/lib/entities/errors/entity_id_conflict_error.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 { EntityDefinition } from '@kbn/entities-schema'; + +export class EntityIdConflict extends Error { + public defintion: EntityDefinition; + + constructor(message: string, def: EntityDefinition) { + super(message); + this.name = 'EntityIdConflict'; + this.defintion = def; + } +} diff --git a/x-pack/plugins/observability_solution/asset_manager/server/lib/entities/errors/entity_not_found.ts b/x-pack/plugins/observability_solution/asset_manager/server/lib/entities/errors/entity_not_found.ts new file mode 100644 index 0000000000000..d81cd3322cae6 --- /dev/null +++ b/x-pack/plugins/observability_solution/asset_manager/server/lib/entities/errors/entity_not_found.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 class EntityDefinitionNotFound extends Error { + constructor(message: string) { + super(message); + this.name = 'EntityDefinitionNotFound'; + } +} diff --git a/x-pack/plugins/observability_solution/asset_manager/server/lib/entities/errors/entity_security_exception.ts b/x-pack/plugins/observability_solution/asset_manager/server/lib/entities/errors/entity_security_exception.ts new file mode 100644 index 0000000000000..6e2f721d4de14 --- /dev/null +++ b/x-pack/plugins/observability_solution/asset_manager/server/lib/entities/errors/entity_security_exception.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 { EntityDefinition } from '@kbn/entities-schema'; + +export class EntitySecurityException extends Error { + public defintion: EntityDefinition; + + constructor(message: string, def: EntityDefinition) { + super(message); + this.name = 'EntitySecurityException'; + this.defintion = def; + } +} diff --git a/x-pack/plugins/observability_solution/asset_manager/server/lib/entities/errors/invalid_transform_error.ts b/x-pack/plugins/observability_solution/asset_manager/server/lib/entities/errors/invalid_transform_error.ts new file mode 100644 index 0000000000000..5d1c98d5dc3ae --- /dev/null +++ b/x-pack/plugins/observability_solution/asset_manager/server/lib/entities/errors/invalid_transform_error.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 class InvalidTransformError extends Error { + constructor(message: string) { + super(message); + this.name = 'InvalidTransformError'; + } +} diff --git a/x-pack/plugins/observability_solution/asset_manager/server/lib/entities/helpers/fixtures/entity_definition.ts b/x-pack/plugins/observability_solution/asset_manager/server/lib/entities/helpers/fixtures/entity_definition.ts new file mode 100644 index 0000000000000..fdb808466ba83 --- /dev/null +++ b/x-pack/plugins/observability_solution/asset_manager/server/lib/entities/helpers/fixtures/entity_definition.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 { entityDefinitionSchema } from '@kbn/entities-schema'; +export const entityDefinition = entityDefinitionSchema.parse({ + id: 'admin-console-logs-service', + name: 'Services for Admin Console', + type: 'service', + indexPatterns: ['kbn-data-forge-fake_stack.*'], + timestampField: '@timestamp', + identityFields: ['log.logger'], + identityTemplate: 'service:{{log.logger}}', + metadata: ['tags', 'host.name', 'kubernetes.pod.name'], + staticFields: { + projectId: '1234', + }, + lookback: '5m', + metrics: [ + { + name: 'logRate', + equation: 'A / 5', + metrics: [ + { + name: 'A', + aggregation: 'doc_count', + filter: 'log.level: *', + }, + ], + }, + { + name: 'errorRate', + equation: 'A / 5', + metrics: [ + { + name: 'A', + aggregation: 'doc_count', + filter: 'log.level: error', + }, + ], + }, + ], +}); diff --git a/x-pack/plugins/observability_solution/asset_manager/server/lib/entities/helpers/generate_index_name.ts b/x-pack/plugins/observability_solution/asset_manager/server/lib/entities/helpers/generate_index_name.ts new file mode 100644 index 0000000000000..365104f3571eb --- /dev/null +++ b/x-pack/plugins/observability_solution/asset_manager/server/lib/entities/helpers/generate_index_name.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 { EntityDefinition } from '@kbn/entities-schema'; +import { ENTITY_BASE_PREFIX } from '../../../../common/constants_entities'; + +export function generateIndexName(definition: EntityDefinition) { + return `${ENTITY_BASE_PREFIX}.${definition.id}`; +} diff --git a/x-pack/plugins/observability_solution/asset_manager/server/lib/entities/helpers/get_elasticsearch_query_or_throw.ts b/x-pack/plugins/observability_solution/asset_manager/server/lib/entities/helpers/get_elasticsearch_query_or_throw.ts new file mode 100644 index 0000000000000..3b24344efd83b --- /dev/null +++ b/x-pack/plugins/observability_solution/asset_manager/server/lib/entities/helpers/get_elasticsearch_query_or_throw.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 { fromKueryExpression, toElasticsearchQuery } from '@kbn/es-query'; +import { InvalidTransformError } from '../errors/invalid_transform_error'; + +export function getElasticsearchQueryOrThrow(kuery: string) { + try { + return toElasticsearchQuery(fromKueryExpression(kuery)); + } catch (err) { + throw new InvalidTransformError(`Invalid KQL: ${kuery}`); + } +} diff --git a/x-pack/plugins/observability_solution/asset_manager/server/lib/entities/helpers/retry.ts b/x-pack/plugins/observability_solution/asset_manager/server/lib/entities/helpers/retry.ts new file mode 100644 index 0000000000000..421289d1c0479 --- /dev/null +++ b/x-pack/plugins/observability_solution/asset_manager/server/lib/entities/helpers/retry.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 { setTimeout } from 'timers/promises'; +import { errors as EsErrors } from '@elastic/elasticsearch'; +import type { Logger } from '@kbn/logging'; + +const MAX_ATTEMPTS = 5; + +const retryResponseStatuses = [ + 503, // ServiceUnavailable + 408, // RequestTimeout + 410, // Gone +]; + +const isRetryableError = (e: any) => + e instanceof EsErrors.NoLivingConnectionsError || + e instanceof EsErrors.ConnectionError || + e instanceof EsErrors.TimeoutError || + (e instanceof EsErrors.ResponseError && retryResponseStatuses.includes(e?.statusCode!)); + +/** + * Retries any transient network or configuration issues encountered from Elasticsearch with an exponential backoff. + * Should only be used to wrap operations that are idempotent and can be safely executed more than once. + */ +export const retryTransientEsErrors = async ( + esCall: () => Promise, + { logger, attempt = 0 }: { logger?: Logger; attempt?: number } = {} +): Promise => { + try { + return await esCall(); + } catch (e) { + if (attempt < MAX_ATTEMPTS && isRetryableError(e)) { + const retryCount = attempt + 1; + const retryDelaySec = Math.min(Math.pow(2, retryCount), 64); // 2s, 4s, 8s, 16s, 32s, 64s, 64s, 64s ... + + logger?.warn( + `Retrying Elasticsearch operation after [${retryDelaySec}s] due to error: ${e.toString()} ${ + e.stack + }` + ); + + await setTimeout(retryDelaySec * 1000); + return retryTransientEsErrors(esCall, { logger, attempt: retryCount }); + } + + throw e; + } +}; diff --git a/x-pack/plugins/observability_solution/asset_manager/server/lib/entities/ingest_pipeline/__snapshots__/generate_processors.test.ts.snap b/x-pack/plugins/observability_solution/asset_manager/server/lib/entities/ingest_pipeline/__snapshots__/generate_processors.test.ts.snap new file mode 100644 index 0000000000000..443063d70db60 --- /dev/null +++ b/x-pack/plugins/observability_solution/asset_manager/server/lib/entities/ingest_pipeline/__snapshots__/generate_processors.test.ts.snap @@ -0,0 +1,70 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`generateProcessors(definition) should genearte a valid pipeline 1`] = ` +Array [ + Object { + "set": Object { + "field": "event.ingested", + "value": "{{{_ingest.timestamp}}}", + }, + }, + Object { + "set": Object { + "field": "entity.definitionId", + "value": "admin-console-logs-service", + }, + }, + Object { + "set": Object { + "field": "entity.indexPatterns", + "value": "[\\"kbn-data-forge-fake_stack.*\\"]", + }, + }, + Object { + "json": Object { + "field": "entity.indexPatterns", + }, + }, + Object { + "set": Object { + "field": "entity.id", + "value": "service:{{entity.identity.log.logger}}", + }, + }, + Object { + "set": Object { + "field": "projectId", + "value": "1234", + }, + }, + Object { + "script": Object { + "source": "if (ctx.entity?.metadata?.tags != null) { + ctx[\\"tags\\"] = ctx.entity.metadata.tags.keySet(); +} +if (ctx.entity?.metadata?.host?.name != null) { + ctx[\\"host\\"] = new HashMap(); + ctx[\\"host\\"][\\"name\\"] = ctx.entity.metadata.host.name.keySet(); +} +if (ctx.entity?.metadata?.kubernetes?.pod?.name != null) { + ctx[\\"kubernetes\\"] = new HashMap(); + ctx[\\"kubernetes\\"][\\"pod\\"] = new HashMap(); + ctx[\\"kubernetes\\"][\\"pod\\"][\\"name\\"] = ctx.entity.metadata.kubernetes.pod.name.keySet(); +} +", + }, + }, + Object { + "remove": Object { + "field": "entity.metadata", + "ignore_missing": true, + }, + }, + Object { + "set": Object { + "field": "_index", + "value": ".entities-observability.summary-v1.admin-console-logs-service", + }, + }, +] +`; diff --git a/x-pack/plugins/observability_solution/asset_manager/server/lib/entities/ingest_pipeline/generate_ingest_pipeline_id.ts b/x-pack/plugins/observability_solution/asset_manager/server/lib/entities/ingest_pipeline/generate_ingest_pipeline_id.ts new file mode 100644 index 0000000000000..c772e198e64fd --- /dev/null +++ b/x-pack/plugins/observability_solution/asset_manager/server/lib/entities/ingest_pipeline/generate_ingest_pipeline_id.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 { EntityDefinition } from '@kbn/entities-schema'; +import { ENTITY_BASE_PREFIX } from '../../../../common/constants_entities'; + +export function generateIngestPipelineId(definition: EntityDefinition) { + return `${ENTITY_BASE_PREFIX}.${definition.id}`; +} diff --git a/x-pack/plugins/observability_solution/asset_manager/server/lib/entities/ingest_pipeline/generate_processors.test.ts b/x-pack/plugins/observability_solution/asset_manager/server/lib/entities/ingest_pipeline/generate_processors.test.ts new file mode 100644 index 0000000000000..33919ec678dcf --- /dev/null +++ b/x-pack/plugins/observability_solution/asset_manager/server/lib/entities/ingest_pipeline/generate_processors.test.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 { generateProcessors } from './generate_processors'; +import { entityDefinition } from '../helpers/fixtures/entity_definition'; + +describe('generateProcessors(definition)', () => { + it('should genearte a valid pipeline', () => { + const processors = generateProcessors(entityDefinition); + expect(processors).toMatchSnapshot(); + }); +}); diff --git a/x-pack/plugins/observability_solution/asset_manager/server/lib/entities/ingest_pipeline/generate_processors.ts b/x-pack/plugins/observability_solution/asset_manager/server/lib/entities/ingest_pipeline/generate_processors.ts new file mode 100644 index 0000000000000..33f27cc5daf71 --- /dev/null +++ b/x-pack/plugins/observability_solution/asset_manager/server/lib/entities/ingest_pipeline/generate_processors.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 { EntityDefinition } from '@kbn/entities-schema'; +import { generateIndexName } from '../helpers/generate_index_name'; + +function createIdTemplate(definition: EntityDefinition) { + return definition.identityFields.reduce((template, id) => { + return template.replaceAll(id.field, `entity.identity.${id.field}`); + }, definition.identityTemplate); +} + +function mapDesitnationToPainless(destination: string, source: string) { + const fieldParts = destination.split('.'); + return fieldParts.reduce((acc, _part, currentIndex, parts) => { + if (currentIndex + 1 === parts.length) { + return `${acc}\n ctx${parts + .map((s) => `["${s}"]`) + .join('')} = ctx.entity.metadata.${source}.keySet();`; + } + return `${acc}\n ctx${parts + .slice(0, currentIndex + 1) + .map((s) => `["${s}"]`) + .join('')} = new HashMap();`; + }, ''); +} + +function createMetadataPainlessScript(definition: EntityDefinition) { + if (!definition.metadata) { + return ''; + } + return definition.metadata.reduce((script, def) => { + const source = def.source; + const destination = def.destination || def.source; + return `${script}if (ctx.entity?.metadata?.${source.replaceAll( + '.', + '?.' + )} != null) {${mapDesitnationToPainless(destination, source)}\n}\n`; + }, ''); +} + +export function generateProcessors(definition: EntityDefinition) { + return [ + { + set: { + field: 'event.ingested', + value: '{{{_ingest.timestamp}}}', + }, + }, + { + set: { + field: 'entity.definitionId', + value: definition.id, + }, + }, + { + set: { + field: 'entity.indexPatterns', + value: JSON.stringify(definition.indexPatterns), + }, + }, + { + json: { + field: 'entity.indexPatterns', + }, + }, + { + set: { + field: 'entity.id', + value: createIdTemplate(definition), + }, + }, + ...(definition.staticFields != null + ? Object.keys(definition.staticFields).map((field) => ({ + set: { field, value: definition.staticFields![field] }, + })) + : []), + ...(definition.metadata != null + ? [{ script: { source: createMetadataPainlessScript(definition) } }] + : []), + { + remove: { + field: 'entity.metadata', + ignore_missing: true, + }, + }, + { + set: { + field: '_index', + value: generateIndexName(definition), + }, + }, + ]; +} diff --git a/x-pack/plugins/observability_solution/asset_manager/server/lib/entities/read_entity_definition.ts b/x-pack/plugins/observability_solution/asset_manager/server/lib/entities/read_entity_definition.ts new file mode 100644 index 0000000000000..e6817ab63f2af --- /dev/null +++ b/x-pack/plugins/observability_solution/asset_manager/server/lib/entities/read_entity_definition.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 { Logger, SavedObjectsClientContract } from '@kbn/core/server'; +import { EntityDefinition, entityDefinitionSchema } from '@kbn/entities-schema'; +import { SO_ENTITY_DEFINITION_TYPE } from '../../saved_objects'; +import { EntityDefinitionNotFound } from './errors/entity_not_found'; + +export async function readEntityDefinition( + soClient: SavedObjectsClientContract, + id: string, + logger: Logger +) { + const response = await soClient.find({ + type: SO_ENTITY_DEFINITION_TYPE, + page: 1, + perPage: 1, + filter: `${SO_ENTITY_DEFINITION_TYPE}.attributes.id:(${id})`, + }); + if (response.total === 0) { + const message = `Unable to find entity defintion with [${id}]`; + logger.error(message); + throw new EntityDefinitionNotFound(message); + } + + try { + return entityDefinitionSchema.parse(response.saved_objects[0].attributes); + } catch (e) { + logger.error(`Unable to parse entity defintion with [${id}]`); + throw e; + } +} diff --git a/x-pack/plugins/observability_solution/asset_manager/server/lib/entities/save_entity_definition.ts b/x-pack/plugins/observability_solution/asset_manager/server/lib/entities/save_entity_definition.ts new file mode 100644 index 0000000000000..f79f88c50ac58 --- /dev/null +++ b/x-pack/plugins/observability_solution/asset_manager/server/lib/entities/save_entity_definition.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 { SavedObjectsClientContract } from '@kbn/core/server'; +import { EntityDefinition } from '@kbn/entities-schema'; +import { SO_ENTITY_DEFINITION_TYPE } from '../../saved_objects'; +import { EntityIdConflict } from './errors/entity_id_conflict_error'; + +export async function saveEntityDefinition( + soClient: SavedObjectsClientContract, + definition: EntityDefinition +): Promise { + const response = await soClient.find({ + type: SO_ENTITY_DEFINITION_TYPE, + page: 1, + perPage: 1, + filter: `${SO_ENTITY_DEFINITION_TYPE}.attributes.id:(${definition.id})`, + }); + + if (response.total === 1) { + throw new EntityIdConflict( + `Entity defintion with [${definition.id}] already exists.`, + definition + ); + } + + await soClient.create(SO_ENTITY_DEFINITION_TYPE, definition, { + id: definition.id, + overwrite: true, + }); + + return definition; +} diff --git a/x-pack/plugins/observability_solution/asset_manager/server/lib/entities/start_transform.ts b/x-pack/plugins/observability_solution/asset_manager/server/lib/entities/start_transform.ts new file mode 100644 index 0000000000000..766bbb10b1d67 --- /dev/null +++ b/x-pack/plugins/observability_solution/asset_manager/server/lib/entities/start_transform.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 { ElasticsearchClient, Logger } from '@kbn/core/server'; +import { EntityDefinition } from '@kbn/entities-schema'; +import { retryTransientEsErrors } from './helpers/retry'; +import { generateTransformId } from './transform/generate_transform_id'; + +export async function startTransform( + esClient: ElasticsearchClient, + definition: EntityDefinition, + logger: Logger +) { + const transformId = generateTransformId(definition); + try { + await retryTransientEsErrors( + () => esClient.transform.startTransform({ transform_id: transformId }, { ignore: [409] }), + { logger } + ); + } catch (err) { + logger.error(`Cannot start entity transform [${transformId}]`); + throw err; + } +} diff --git a/x-pack/plugins/observability_solution/asset_manager/server/lib/entities/stop_and_delete_transform.ts b/x-pack/plugins/observability_solution/asset_manager/server/lib/entities/stop_and_delete_transform.ts new file mode 100644 index 0000000000000..60a250a33f0d9 --- /dev/null +++ b/x-pack/plugins/observability_solution/asset_manager/server/lib/entities/stop_and_delete_transform.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 { ElasticsearchClient, Logger } from '@kbn/core/server'; +import { EntityDefinition } from '@kbn/entities-schema'; +import { generateTransformId } from './transform/generate_transform_id'; +import { retryTransientEsErrors } from './helpers/retry'; + +export async function stopAndDeleteTransform( + esClient: ElasticsearchClient, + definition: EntityDefinition, + logger: Logger +) { + const transformId = generateTransformId(definition); + try { + await retryTransientEsErrors( + async () => { + await esClient.transform.stopTransform( + { transform_id: transformId, wait_for_completion: true, force: true }, + { ignore: [409] } + ); + await esClient.transform.deleteTransform( + { transform_id: transformId, force: true }, + { ignore: [404] } + ); + }, + { logger } + ); + } catch (e) { + logger.error(`Cannot stop or delete entity transform [${transformId}]`); + throw e; + } +} diff --git a/x-pack/plugins/observability_solution/asset_manager/server/lib/entities/transform/__snapshots__/generate_transform.test.ts.snap b/x-pack/plugins/observability_solution/asset_manager/server/lib/entities/transform/__snapshots__/generate_transform.test.ts.snap new file mode 100644 index 0000000000000..e692f2068eafd --- /dev/null +++ b/x-pack/plugins/observability_solution/asset_manager/server/lib/entities/transform/__snapshots__/generate_transform.test.ts.snap @@ -0,0 +1,126 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`generateTransform(definition) should generate a valid summary transform 1`] = ` +Object { + "defer_validation": true, + "dest": Object { + "index": ".entities-observability.summary-v1.noop", + "pipeline": ".entities-observability.summary-v1.admin-console-logs-service", + }, + "frequency": "1m", + "pivot": Object { + "aggs": Object { + "_errorRate_A": Object { + "filter": Object { + "bool": Object { + "minimum_should_match": 1, + "should": Array [ + Object { + "match": Object { + "log.level": "error", + }, + }, + ], + }, + }, + }, + "_logRate_A": Object { + "filter": Object { + "bool": Object { + "minimum_should_match": 1, + "should": Array [ + Object { + "exists": Object { + "field": "log.level", + }, + }, + ], + }, + }, + }, + "entity.latestTimestamp": Object { + "max": Object { + "field": "@timestamp", + }, + }, + "entity.metadata.host.name": Object { + "terms": Object { + "field": "host.name", + "size": 1000, + }, + }, + "entity.metadata.kubernetes.pod.name": Object { + "terms": Object { + "field": "kubernetes.pod.name", + "size": 1000, + }, + }, + "entity.metadata.tags": Object { + "terms": Object { + "field": "tags", + "size": 1000, + }, + }, + "entity.metric.errorRate": Object { + "bucket_script": Object { + "buckets_path": Object { + "A": "_errorRate_A>_count", + }, + "script": Object { + "lang": "painless", + "source": "params.A / 5", + }, + }, + }, + "entity.metric.logRate": Object { + "bucket_script": Object { + "buckets_path": Object { + "A": "_logRate_A>_count", + }, + "script": Object { + "lang": "painless", + "source": "params.A / 5", + }, + }, + }, + }, + "group_by": Object { + "entity.identity.log.logger": Object { + "terms": Object { + "field": "log.logger", + "missing_bucket": false, + }, + }, + }, + }, + "settings": Object { + "deduce_mappings": false, + "unattended": true, + }, + "source": Object { + "index": Array [ + "kbn-data-forge-fake_stack.*", + ], + "query": Object { + "bool": Object { + "filter": Array [ + Object { + "range": Object { + "@timestamp": Object { + "gte": "now-5m", + }, + }, + }, + ], + }, + }, + }, + "sync": Object { + "time": Object { + "delay": "60s", + "field": "@timestamp", + }, + }, + "transform_id": "entities-observability-summary-v1-admin-console-logs-service", +} +`; diff --git a/x-pack/plugins/observability_solution/asset_manager/server/lib/entities/transform/generate_metadata_aggregations.ts b/x-pack/plugins/observability_solution/asset_manager/server/lib/entities/transform/generate_metadata_aggregations.ts new file mode 100644 index 0000000000000..8c11aea138519 --- /dev/null +++ b/x-pack/plugins/observability_solution/asset_manager/server/lib/entities/transform/generate_metadata_aggregations.ts @@ -0,0 +1,26 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { EntityDefinition } from '@kbn/entities-schema'; + +export function generateMetadataAggregations(definition: EntityDefinition) { + if (!definition.metadata) { + return {}; + } + return definition.metadata.reduce( + (aggs, metadata) => ({ + ...aggs, + [`entity.metadata.${metadata.destination ?? metadata.source}`]: { + terms: { + field: metadata.source, + size: metadata.limit ?? 1000, + }, + }, + }), + {} + ); +} diff --git a/x-pack/plugins/observability_solution/asset_manager/server/lib/entities/transform/generate_metric_aggregations.ts b/x-pack/plugins/observability_solution/asset_manager/server/lib/entities/transform/generate_metric_aggregations.ts new file mode 100644 index 0000000000000..9527671768e35 --- /dev/null +++ b/x-pack/plugins/observability_solution/asset_manager/server/lib/entities/transform/generate_metric_aggregations.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 { KeyMetric, Metric, EntityDefinition } from '@kbn/entities-schema'; +import { getElasticsearchQueryOrThrow } from '../helpers/get_elasticsearch_query_or_throw'; +import { InvalidTransformError } from '../errors/invalid_transform_error'; + +function buildAggregation(metric: Metric, timestampField: string) { + const { aggregation } = metric; + switch (aggregation) { + case 'doc_count': + return {}; + case 'std_deviation': + return { + extended_stats: { field: metric.field }, + }; + case 'percentile': + if (metric.percentile == null) { + throw new InvalidTransformError( + 'You must provide a percentile value for percentile aggregations.' + ); + } + return { + percentiles: { + field: metric.field, + percents: [metric.percentile], + keyed: true, + }, + }; + case 'last_value': + return { + top_metrics: { + metrics: { field: metric.field }, + sort: { [timestampField]: 'desc' }, + }, + }; + default: + if (metric.field == null) { + throw new InvalidTransformError('You must provide a field for basic metric aggregations.'); + } + return { + [aggregation]: { field: metric.field }, + }; + } +} + +function buildMetricAggregations(keyMetric: KeyMetric, timestampField: string) { + return keyMetric.metrics.reduce((acc, metric) => { + const filter = metric.filter ? getElasticsearchQueryOrThrow(metric.filter) : { match_all: {} }; + const aggs = { metric: buildAggregation(metric, timestampField) }; + return { + ...acc, + [`_${keyMetric.name}_${metric.name}`]: { + filter, + ...(metric.aggregation !== 'doc_count' ? { aggs } : {}), + }, + }; + }, {}); +} + +function buildBucketPath(prefix: string, metric: Metric) { + const { aggregation } = metric; + switch (aggregation) { + case 'doc_count': + return `${prefix}>_count`; + case 'std_deviation': + return `${prefix}>metric[std_deviation]`; + case 'percentile': + return `${prefix}>metric[${metric.percentile}]`; + case 'last_value': + return `${prefix}>metric[${metric.field}]`; + default: + return `${prefix}>metric`; + } +} + +function convertEquationToPainless(bucketsPath: Record, equation: string) { + const workingEquation = equation || Object.keys(bucketsPath).join(' + '); + return Object.keys(bucketsPath).reduce((acc, key) => { + return acc.replaceAll(key, `params.${key}`); + }, workingEquation); +} + +function buildMetricEquation(keyMetric: KeyMetric) { + const bucketsPath = keyMetric.metrics.reduce( + (acc, metric) => ({ + ...acc, + [metric.name]: buildBucketPath(`_${keyMetric.name}_${metric.name}`, metric), + }), + {} + ); + return { + bucket_script: { + buckets_path: bucketsPath, + script: { + source: convertEquationToPainless(bucketsPath, keyMetric.equation), + lang: 'painless', + }, + }, + }; +} + +export function generateMetricAggregations(definition: EntityDefinition) { + if (!definition.metrics) { + return {}; + } + return definition.metrics.reduce((aggs, keyMetric) => { + return { + ...aggs, + ...buildMetricAggregations(keyMetric, definition.timestampField), + [`entity.metric.${keyMetric.name}`]: buildMetricEquation(keyMetric), + }; + }, {}); +} diff --git a/x-pack/plugins/observability_solution/asset_manager/server/lib/entities/transform/generate_transform.test.ts b/x-pack/plugins/observability_solution/asset_manager/server/lib/entities/transform/generate_transform.test.ts new file mode 100644 index 0000000000000..e97293b77dd4f --- /dev/null +++ b/x-pack/plugins/observability_solution/asset_manager/server/lib/entities/transform/generate_transform.test.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 { entityDefinition } from '../helpers/fixtures/entity_definition'; +import { generateTransform } from './generate_transform'; + +describe('generateTransform(definition)', () => { + it('should generate a valid summary transform', () => { + const transform = generateTransform(entityDefinition); + expect(transform).toMatchSnapshot(); + }); +}); diff --git a/x-pack/plugins/observability_solution/asset_manager/server/lib/entities/transform/generate_transform.ts b/x-pack/plugins/observability_solution/asset_manager/server/lib/entities/transform/generate_transform.ts new file mode 100644 index 0000000000000..6a8c0bd637715 --- /dev/null +++ b/x-pack/plugins/observability_solution/asset_manager/server/lib/entities/transform/generate_transform.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 { EntityDefinition } from '@kbn/entities-schema'; +import { + QueryDslQueryContainer, + TransformPutTransformRequest, +} from '@elastic/elasticsearch/lib/api/types'; +import { getElasticsearchQueryOrThrow } from '../helpers/get_elasticsearch_query_or_throw'; +import { generateMetricAggregations } from './generate_metric_aggregations'; +import { + ENTITY_BASE_PREFIX, + ENTITY_DEFAULT_FREQUENCY, + ENTITY_DEFAULT_SYNC_DELAY, +} from '../../../../common/constants_entities'; +import { generateMetadataAggregations } from './generate_metadata_aggregations'; +import { generateTransformId } from './generate_transform_id'; +import { generateIngestPipelineId } from '../ingest_pipeline/generate_ingest_pipeline_id'; + +export function generateTransform(definition: EntityDefinition): TransformPutTransformRequest { + const filter: QueryDslQueryContainer[] = [ + { + range: { + [definition.timestampField]: { + gte: `now-${definition.lookback.toJSON()}`, + }, + }, + }, + ]; + + if (definition.filter) { + filter.push(getElasticsearchQueryOrThrow(definition.filter)); + } + + return { + transform_id: generateTransformId(definition), + defer_validation: true, + source: { + index: definition.indexPatterns, + query: { + bool: { + filter, + }, + }, + }, + dest: { + index: `${ENTITY_BASE_PREFIX}.noop`, + pipeline: generateIngestPipelineId(definition), + }, + frequency: definition.settings?.frequency || ENTITY_DEFAULT_FREQUENCY, + sync: { + time: { + field: definition.settings?.syncField ?? definition.timestampField, + delay: definition.settings?.syncDelay ?? ENTITY_DEFAULT_SYNC_DELAY, + }, + }, + settings: { + deduce_mappings: false, + unattended: true, + }, + pivot: { + group_by: definition.identityFields.reduce( + (acc, id) => ({ + ...acc, + [`entity.identity.${id.field}`]: { + terms: { field: id.field, missing_bucket: id.optional }, + }, + }), + {} + ), + aggs: { + ...generateMetricAggregations(definition), + ...generateMetadataAggregations(definition), + 'entity.latestTimestamp': { + max: { + field: definition.timestampField, + }, + }, + }, + }, + }; +} diff --git a/x-pack/plugins/observability_solution/asset_manager/server/lib/entities/transform/generate_transform_id.ts b/x-pack/plugins/observability_solution/asset_manager/server/lib/entities/transform/generate_transform_id.ts new file mode 100644 index 0000000000000..06faedb916774 --- /dev/null +++ b/x-pack/plugins/observability_solution/asset_manager/server/lib/entities/transform/generate_transform_id.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 { EntityDefinition } from '@kbn/entities-schema'; +import { ENTITY_TRANSFORM_PREFIX } from '../../../../common/constants_entities'; + +export function generateTransformId(definition: EntityDefinition) { + return `${ENTITY_TRANSFORM_PREFIX}-${definition.id}`; +} diff --git a/x-pack/plugins/observability_solution/asset_manager/server/lib/manage_index_templates.ts b/x-pack/plugins/observability_solution/asset_manager/server/lib/manage_index_templates.ts index b853d7a360e1d..b364e63ff9a1f 100644 --- a/x-pack/plugins/observability_solution/asset_manager/server/lib/manage_index_templates.ts +++ b/x-pack/plugins/observability_solution/asset_manager/server/lib/manage_index_templates.ts @@ -6,6 +6,7 @@ */ import { + ClusterPutComponentTemplateRequest, IndicesGetIndexTemplateResponse, IndicesPutIndexTemplateRequest, } from '@elastic/elasticsearch/lib/api/types'; @@ -47,21 +48,18 @@ function templateExists( }); } -// interface IndexPatternJson { -// index_patterns: string[]; -// name: string; -// template: { -// mappings: Record; -// settings: Record; -// }; -// } - interface TemplateManagementOptions { esClient: ElasticsearchClient; template: IndicesPutIndexTemplateRequest; logger: Logger; } +interface ComponentManagementOptions { + esClient: ElasticsearchClient; + component: ClusterPutComponentTemplateRequest; + logger: Logger; +} + export async function maybeCreateTemplate({ esClient, template, @@ -93,9 +91,6 @@ export async function maybeCreateTemplate({ } export async function upsertTemplate({ esClient, template, logger }: TemplateManagementOptions) { - const pattern = ASSETS_INDEX_PREFIX + '*'; - template.index_patterns = [pattern]; - try { await esClient.indices.putIndexTemplate(template); } catch (error: any) { @@ -108,3 +103,17 @@ export async function upsertTemplate({ esClient, template, logger }: TemplateMan ); logger.debug(`Asset manager index template: ${JSON.stringify(template)}`); } + +export async function upsertComponent({ esClient, component, logger }: ComponentManagementOptions) { + try { + await esClient.cluster.putComponentTemplate(component); + } catch (error: any) { + logger.error(`Error updating asset manager component template: ${error.message}`); + return; + } + + logger.info( + `Asset manager component template is up to date (use debug logging to see what was installed)` + ); + logger.debug(`Asset manager component template: ${JSON.stringify(component)}`); +} diff --git a/x-pack/plugins/observability_solution/asset_manager/server/plugin.ts b/x-pack/plugins/observability_solution/asset_manager/server/plugin.ts index 73b2cbe87c138..4c947926cf571 100644 --- a/x-pack/plugins/observability_solution/asset_manager/server/plugin.ts +++ b/x-pack/plugins/observability_solution/asset_manager/server/plugin.ts @@ -15,12 +15,17 @@ import { Logger, } from '@kbn/core/server'; -import { upsertTemplate } from './lib/manage_index_templates'; +import { upsertComponent, upsertTemplate } from './lib/manage_index_templates'; import { setupRoutes } from './routes'; import { assetsIndexTemplateConfig } from './templates/assets_template'; import { AssetClient } from './lib/asset_client'; import { AssetManagerPluginSetupDependencies, AssetManagerPluginStartDependencies } from './types'; import { AssetManagerConfig, configSchema, exposeToBrowserConfig } from '../common/config'; +import { entitiesBaseComponentTemplateConfig } from './templates/components/base'; +import { entitiesEventComponentTemplateConfig } from './templates/components/event'; +import { entitiesIndexTemplateConfig } from './templates/entities_template'; +import { entityDefinition } from './saved_objects'; +import { entitiesEntityComponentTemplateConfig } from './templates/components/entity'; export type AssetManagerServerPluginSetup = ReturnType; export type AssetManagerServerPluginStart = ReturnType; @@ -56,6 +61,8 @@ export class AssetManagerServerPlugin this.logger.info('Server is enabled'); + core.savedObjects.registerType(entityDefinition); + const assetClient = new AssetClient({ sourceIndices: this.config.sourceIndices, getApmIndices: plugins.apmDataAccess.getApmIndices, @@ -63,7 +70,7 @@ export class AssetManagerServerPlugin }); const router = core.http.createRouter(); - setupRoutes({ router, assetClient }); + setupRoutes({ router, assetClient, logger: this.logger }); return { assetClient, @@ -76,12 +83,36 @@ export class AssetManagerServerPlugin return; } + const esClient = core.elasticsearch.client.asInternalUser; upsertTemplate({ - esClient: core.elasticsearch.client.asInternalUser, + esClient, template: assetsIndexTemplateConfig, logger: this.logger, }).catch(() => {}); // it shouldn't reject, but just in case + // Install entities compoent templates and index template + Promise.all([ + upsertComponent({ + esClient, + logger: this.logger, + component: entitiesBaseComponentTemplateConfig, + }), + upsertComponent({ + esClient, + logger: this.logger, + component: entitiesEventComponentTemplateConfig, + }), + upsertComponent({ + esClient, + logger: this.logger, + component: entitiesEntityComponentTemplateConfig, + }), + ]) + .then(() => + upsertTemplate({ esClient, logger: this.logger, template: entitiesIndexTemplateConfig }) + ) + .catch(() => {}); + return {}; } diff --git a/x-pack/plugins/observability_solution/asset_manager/server/routes/entities/create.ts b/x-pack/plugins/observability_solution/asset_manager/server/routes/entities/create.ts new file mode 100644 index 0000000000000..d403c39ae0ed1 --- /dev/null +++ b/x-pack/plugins/observability_solution/asset_manager/server/routes/entities/create.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 { RequestHandlerContext } from '@kbn/core/server'; +import { EntityDefinition, entityDefinitionSchema } from '@kbn/entities-schema'; +import { stringifyZodError } from '@kbn/zod-helpers'; +import { SetupRouteOptions } from '../types'; +import { saveEntityDefinition } from '../../lib/entities/save_entity_definition'; +import { createAndInstallIngestPipeline } from '../../lib/entities/create_and_install_ingest_pipeline'; +import { EntityIdConflict } from '../../lib/entities/errors/entity_id_conflict_error'; +import { createAndInstallTransform } from '../../lib/entities/create_and_install_transform'; +import { EntitySecurityException } from '../../lib/entities/errors/entity_security_exception'; +import { InvalidTransformError } from '../../lib/entities/errors/invalid_transform_error'; +import { startTransform } from '../../lib/entities/start_transform'; +import { deleteEntityDefinition } from '../../lib/entities/delete_entity_definition'; +import { deleteIngestPipeline } from '../../lib/entities/delete_ingest_pipeline'; +import { stopAndDeleteTransform } from '../../lib/entities/stop_and_delete_transform'; +import { ENTITY_API_PREFIX } from '../../../common/constants_entities'; + +export function createEntityDefinitionRoute({ + router, + logger, +}: SetupRouteOptions) { + router.post( + { + path: `${ENTITY_API_PREFIX}/definition`, + validate: { + body: (body, res) => { + try { + return res.ok(entityDefinitionSchema.parse(body)); + } catch (e) { + return res.badRequest(stringifyZodError(e)); + } + }, + }, + }, + async (context, req, res) => { + let definitionCreated = false; + let ingestPipelineCreated = false; + let transformCreated = false; + const soClient = (await context.core).savedObjects.client; + const esClient = (await context.core).elasticsearch.client.asCurrentUser; + try { + const definition = await saveEntityDefinition(soClient, req.body); + definitionCreated = true; + await createAndInstallIngestPipeline(esClient, definition, logger); + ingestPipelineCreated = true; + await createAndInstallTransform(esClient, definition, logger); + transformCreated = true; + await startTransform(esClient, definition, logger); + + return res.ok({ body: definition }); + } catch (e) { + // Clean up anything that was successful. + if (definitionCreated) { + await deleteEntityDefinition(soClient, req.body, logger); + } + if (ingestPipelineCreated) { + await deleteIngestPipeline(esClient, req.body, logger); + } + if (transformCreated) { + await stopAndDeleteTransform(esClient, req.body, logger); + } + if (e instanceof EntityIdConflict) { + return res.conflict({ body: e }); + } + if (e instanceof EntitySecurityException || e instanceof InvalidTransformError) { + return res.customError({ body: e, statusCode: 400 }); + } + return res.customError({ body: e, statusCode: 500 }); + } + } + ); +} diff --git a/x-pack/plugins/observability_solution/asset_manager/server/routes/entities/delete.ts b/x-pack/plugins/observability_solution/asset_manager/server/routes/entities/delete.ts new file mode 100644 index 0000000000000..e1b273780a64f --- /dev/null +++ b/x-pack/plugins/observability_solution/asset_manager/server/routes/entities/delete.ts @@ -0,0 +1,55 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { RequestHandlerContext } from '@kbn/core/server'; +import { schema } from '@kbn/config-schema'; +import { SetupRouteOptions } from '../types'; +import { EntitySecurityException } from '../../lib/entities/errors/entity_security_exception'; +import { InvalidTransformError } from '../../lib/entities/errors/invalid_transform_error'; +import { readEntityDefinition } from '../../lib/entities/read_entity_definition'; +import { stopAndDeleteTransform } from '../../lib/entities/stop_and_delete_transform'; +import { deleteIngestPipeline } from '../../lib/entities/delete_ingest_pipeline'; +import { deleteEntityDefinition } from '../../lib/entities/delete_entity_definition'; +import { EntityDefinitionNotFound } from '../../lib/entities/errors/entity_not_found'; +import { ENTITY_API_PREFIX } from '../../../common/constants_entities'; + +export function deleteEntityDefinitionRoute({ + router, + logger, +}: SetupRouteOptions) { + router.delete<{ id: string }, unknown, unknown>( + { + path: `${ENTITY_API_PREFIX}/definition/{id}`, + validate: { + params: schema.object({ + id: schema.string(), + }), + }, + }, + async (context, req, res) => { + try { + const soClient = (await context.core).savedObjects.client; + const esClient = (await context.core).elasticsearch.client.asCurrentUser; + + const definition = await readEntityDefinition(soClient, req.params.id, logger); + await stopAndDeleteTransform(esClient, definition, logger); + await deleteIngestPipeline(esClient, definition, logger); + await deleteEntityDefinition(soClient, definition, logger); + + return res.ok({ body: { acknowledged: true } }); + } catch (e) { + if (e instanceof EntityDefinitionNotFound) { + return res.notFound({ body: e }); + } + if (e instanceof EntitySecurityException || e instanceof InvalidTransformError) { + return res.customError({ body: e, statusCode: 400 }); + } + return res.customError({ body: e, statusCode: 500 }); + } + } + ); +} diff --git a/x-pack/plugins/observability_solution/asset_manager/server/routes/entities/reset.ts b/x-pack/plugins/observability_solution/asset_manager/server/routes/entities/reset.ts new file mode 100644 index 0000000000000..3109ffc44520f --- /dev/null +++ b/x-pack/plugins/observability_solution/asset_manager/server/routes/entities/reset.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 { RequestHandlerContext } from '@kbn/core/server'; +import { schema } from '@kbn/config-schema'; +import { SetupRouteOptions } from '../types'; +import { EntitySecurityException } from '../../lib/entities/errors/entity_security_exception'; +import { InvalidTransformError } from '../../lib/entities/errors/invalid_transform_error'; +import { readEntityDefinition } from '../../lib/entities/read_entity_definition'; +import { stopAndDeleteTransform } from '../../lib/entities/stop_and_delete_transform'; +import { deleteIngestPipeline } from '../../lib/entities/delete_ingest_pipeline'; +import { deleteIndex } from '../../lib/entities/delete_index'; +import { createAndInstallIngestPipeline } from '../../lib/entities/create_and_install_ingest_pipeline'; +import { createAndInstallTransform } from '../../lib/entities/create_and_install_transform'; +import { startTransform } from '../../lib/entities/start_transform'; +import { EntityDefinitionNotFound } from '../../lib/entities/errors/entity_not_found'; +import { ENTITY_API_PREFIX } from '../../../common/constants_entities'; + +export function resetEntityDefinitionRoute({ + router, + logger, +}: SetupRouteOptions) { + router.post<{ id: string }, unknown, unknown>( + { + path: `${ENTITY_API_PREFIX}/definition/{id}/_reset`, + validate: { + params: schema.object({ + id: schema.string(), + }), + }, + }, + async (context, req, res) => { + try { + const soClient = (await context.core).savedObjects.client; + const esClient = (await context.core).elasticsearch.client.asCurrentUser; + + const definition = await readEntityDefinition(soClient, req.params.id, logger); + + // Delete the transform and ingest pipeline + await stopAndDeleteTransform(esClient, definition, logger); + await deleteIngestPipeline(esClient, definition, logger); + await deleteIndex(esClient, definition, logger); + + // Recreate everything + await createAndInstallIngestPipeline(esClient, definition, logger); + await createAndInstallTransform(esClient, definition, logger); + await startTransform(esClient, definition, logger); + + return res.ok({ body: { acknowledged: true } }); + } catch (e) { + if (e instanceof EntityDefinitionNotFound) { + return res.notFound({ body: e }); + } + if (e instanceof EntitySecurityException || e instanceof InvalidTransformError) { + return res.customError({ body: e, statusCode: 400 }); + } + return res.customError({ body: e, statusCode: 500 }); + } + } + ); +} diff --git a/x-pack/plugins/observability_solution/asset_manager/server/routes/index.ts b/x-pack/plugins/observability_solution/asset_manager/server/routes/index.ts index 52d3198bb8a9f..d0b6c9f7ff0f1 100644 --- a/x-pack/plugins/observability_solution/asset_manager/server/routes/index.ts +++ b/x-pack/plugins/observability_solution/asset_manager/server/routes/index.ts @@ -14,16 +14,23 @@ import { hostsRoutes } from './assets/hosts'; import { servicesRoutes } from './assets/services'; import { containersRoutes } from './assets/containers'; import { podsRoutes } from './assets/pods'; +import { createEntityDefinitionRoute } from './entities/create'; +import { deleteEntityDefinitionRoute } from './entities/delete'; +import { resetEntityDefinitionRoute } from './entities/reset'; export function setupRoutes({ router, assetClient, + logger, }: SetupRouteOptions) { - pingRoute({ router, assetClient }); - sampleAssetsRoutes({ router, assetClient }); - assetsRoutes({ router, assetClient }); - hostsRoutes({ router, assetClient }); - servicesRoutes({ router, assetClient }); - containersRoutes({ router, assetClient }); - podsRoutes({ router, assetClient }); + pingRoute({ router, assetClient, logger }); + sampleAssetsRoutes({ router, assetClient, logger }); + assetsRoutes({ router, assetClient, logger }); + hostsRoutes({ router, assetClient, logger }); + servicesRoutes({ router, assetClient, logger }); + containersRoutes({ router, assetClient, logger }); + podsRoutes({ router, assetClient, logger }); + createEntityDefinitionRoute({ router, assetClient, logger }); + deleteEntityDefinitionRoute({ router, assetClient, logger }); + resetEntityDefinitionRoute({ router, assetClient, logger }); } diff --git a/x-pack/plugins/observability_solution/asset_manager/server/routes/types.ts b/x-pack/plugins/observability_solution/asset_manager/server/routes/types.ts index ae1b967a5b596..561819d18cdae 100644 --- a/x-pack/plugins/observability_solution/asset_manager/server/routes/types.ts +++ b/x-pack/plugins/observability_solution/asset_manager/server/routes/types.ts @@ -6,9 +6,11 @@ */ import { IRouter, RequestHandlerContextBase } from '@kbn/core-http-server'; +import { Logger } from '@kbn/core/server'; import { AssetClient } from '../lib/asset_client'; export interface SetupRouteOptions { router: IRouter; assetClient: AssetClient; + logger: Logger; } diff --git a/x-pack/plugins/observability_solution/asset_manager/server/saved_objects/entity_definition.ts b/x-pack/plugins/observability_solution/asset_manager/server/saved_objects/entity_definition.ts new file mode 100644 index 0000000000000..5a63444974ad7 --- /dev/null +++ b/x-pack/plugins/observability_solution/asset_manager/server/saved_objects/entity_definition.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 { SavedObject, SavedObjectsType } from '@kbn/core/server'; +import { EntityDefinition } from '@kbn/entities-schema'; + +export const SO_ENTITY_DEFINITION_TYPE = 'entity-definition'; + +export const entityDefinition: SavedObjectsType = { + name: SO_ENTITY_DEFINITION_TYPE, + hidden: false, + namespaceType: 'multiple-isolated', + mappings: { + dynamic: false, + properties: { + id: { type: 'keyword' }, + name: { type: 'text' }, + description: { type: 'text' }, + type: { type: 'keyword' }, + filter: { type: 'keyword' }, + indexPatterns: { type: 'keyword' }, + identityFields: { type: 'object' }, + categories: { type: 'keyword' }, + metadata: { type: 'object' }, + metrics: { type: 'object' }, + staticFields: { type: 'object' }, + }, + }, + management: { + displayName: 'Entity Definition', + importableAndExportable: false, + getTitle(sloSavedObject: SavedObject) { + return `EntityDefinition: [${sloSavedObject.attributes.name}]`; + }, + }, +}; diff --git a/x-pack/plugins/observability_solution/asset_manager/server/saved_objects/index.ts b/x-pack/plugins/observability_solution/asset_manager/server/saved_objects/index.ts new file mode 100644 index 0000000000000..6145b05438bb2 --- /dev/null +++ b/x-pack/plugins/observability_solution/asset_manager/server/saved_objects/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 { entityDefinition, SO_ENTITY_DEFINITION_TYPE } from './entity_definition'; diff --git a/x-pack/plugins/observability_solution/asset_manager/server/templates/assets_template.ts b/x-pack/plugins/observability_solution/asset_manager/server/templates/assets_template.ts index 71d4058eba4c0..b99ecc4559187 100644 --- a/x-pack/plugins/observability_solution/asset_manager/server/templates/assets_template.ts +++ b/x-pack/plugins/observability_solution/asset_manager/server/templates/assets_template.ts @@ -6,11 +6,13 @@ */ import { IndicesPutIndexTemplateRequest } from '@elastic/elasticsearch/lib/api/types'; +import { ASSETS_INDEX_PREFIX } from '../constants'; export const assetsIndexTemplateConfig: IndicesPutIndexTemplateRequest = { name: 'assets', priority: 100, data_stream: {}, + index_patterns: [`${ASSETS_INDEX_PREFIX}*`], template: { settings: {}, mappings: { diff --git a/x-pack/plugins/observability_solution/asset_manager/server/templates/components/base.ts b/x-pack/plugins/observability_solution/asset_manager/server/templates/components/base.ts new file mode 100644 index 0000000000000..adf527d653d9c --- /dev/null +++ b/x-pack/plugins/observability_solution/asset_manager/server/templates/components/base.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 { ClusterPutComponentTemplateRequest } from '@elastic/elasticsearch/lib/api/types'; + +export const entitiesBaseComponentTemplateConfig: ClusterPutComponentTemplateRequest = { + name: 'entities_v1_base', + _meta: { + documentation: 'https://www.elastic.co/guide/en/ecs/current/ecs-base.html', + ecs_version: '8.0.0', + }, + template: { + mappings: { + properties: { + '@timestamp': { + type: 'date', + }, + labels: { + type: 'object', + }, + tags: { + ignore_above: 1024, + type: 'keyword', + }, + }, + }, + }, +}; diff --git a/x-pack/plugins/observability_solution/asset_manager/server/templates/components/entity.ts b/x-pack/plugins/observability_solution/asset_manager/server/templates/components/entity.ts new file mode 100644 index 0000000000000..e696d32e0dfb2 --- /dev/null +++ b/x-pack/plugins/observability_solution/asset_manager/server/templates/components/entity.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 { ClusterPutComponentTemplateRequest } from '@elastic/elasticsearch/lib/api/types'; + +export const entitiesEntityComponentTemplateConfig: ClusterPutComponentTemplateRequest = { + name: 'entities_v1_entity', + _meta: { + ecs_version: '8.0.0', + }, + template: { + mappings: { + properties: { + entity: { + properties: { + id: { + ignore_above: 1024, + type: 'keyword', + }, + indexPatterns: { + ignore_above: 1024, + type: 'keyword', + }, + defintionId: { + ignore_above: 1024, + type: 'keyword', + }, + latestTimestamp: { + type: 'date', + }, + }, + }, + }, + }, + }, +}; diff --git a/x-pack/plugins/observability_solution/asset_manager/server/templates/components/event.ts b/x-pack/plugins/observability_solution/asset_manager/server/templates/components/event.ts new file mode 100644 index 0000000000000..6ad4b628fdf36 --- /dev/null +++ b/x-pack/plugins/observability_solution/asset_manager/server/templates/components/event.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 { ClusterPutComponentTemplateRequest } from '@elastic/elasticsearch/lib/api/types'; + +export const entitiesEventComponentTemplateConfig: ClusterPutComponentTemplateRequest = { + name: 'entities_v1_event', + _meta: { + documentation: 'https://www.elastic.co/guide/en/ecs/current/ecs-event.html', + ecs_version: '8.0.0', + }, + template: { + mappings: { + properties: { + event: { + properties: { + ingested: { + type: 'date', + }, + }, + }, + }, + }, + }, +}; diff --git a/x-pack/plugins/observability_solution/asset_manager/server/templates/entities_template.ts b/x-pack/plugins/observability_solution/asset_manager/server/templates/entities_template.ts new file mode 100644 index 0000000000000..d3934b24ea82c --- /dev/null +++ b/x-pack/plugins/observability_solution/asset_manager/server/templates/entities_template.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 { IndicesPutIndexTemplateRequest } from '@elastic/elasticsearch/lib/api/types'; +import { ENTITY_BASE_PREFIX } from '../../common/constants_entities'; + +export const entitiesIndexTemplateConfig: IndicesPutIndexTemplateRequest = { + name: 'entities_v1_index_template', + _meta: { + description: 'The entities index template', + ecs_version: '8.0.0', + }, + composed_of: ['entities_v1_base', 'entities_v1_event', 'entities_v1_entity'], + index_patterns: [`${ENTITY_BASE_PREFIX}.*`], + priority: 1, + template: { + mappings: { + _meta: { + version: '1.6.0', + }, + date_detection: false, + dynamic_templates: [ + { + strings_as_keyword: { + mapping: { + ignore_above: 1024, + type: 'keyword', + }, + match_mapping_type: 'string', + }, + }, + { + entity_metrics: { + mapping: { + // @ts-expect-error this should work per: https://www.elastic.co/guide/en/elasticsearch/reference/current/dynamic-templates.html#match-mapping-type + type: '{dynamic_type}', + }, + // @ts-expect-error this should work per: https://www.elastic.co/guide/en/elasticsearch/reference/current/dynamic-templates.html#match-mapping-type + match_mapping_type: ['long', 'double'], + path_match: 'entity.metric.*', + }, + }, + ], + }, + settings: { + index: { + codec: 'best_compression', + mapping: { + total_fields: { + limit: 2000, + }, + }, + }, + }, + }, +}; diff --git a/x-pack/plugins/observability_solution/asset_manager/tsconfig.json b/x-pack/plugins/observability_solution/asset_manager/tsconfig.json index da1095d989afb..dbbc36252bfb1 100644 --- a/x-pack/plugins/observability_solution/asset_manager/tsconfig.json +++ b/x-pack/plugins/observability_solution/asset_manager/tsconfig.json @@ -26,6 +26,9 @@ "@kbn/metrics-data-access-plugin", "@kbn/core-elasticsearch-server", "@kbn/core-saved-objects-api-server", - "@kbn/core-saved-objects-api-server-mocks" + "@kbn/core-saved-objects-api-server-mocks", + "@kbn/entities-schema", + "@kbn/es-query", + "@kbn/zod-helpers" ] } diff --git a/x-pack/plugins/observability_solution/infra/common/alerting/metrics/alert_link.ts b/x-pack/plugins/observability_solution/infra/common/alerting/metrics/alert_link.ts index ff6b6d2c752ce..a1f0da3531215 100644 --- a/x-pack/plugins/observability_solution/infra/common/alerting/metrics/alert_link.ts +++ b/x-pack/plugins/observability_solution/infra/common/alerting/metrics/alert_link.ts @@ -9,7 +9,7 @@ import { ALERT_RULE_PARAMETERS, TIMESTAMP } from '@kbn/rule-data-utils'; import { encode } from '@kbn/rison'; import { stringify } from 'query-string'; import { ParsedTechnicalFields } from '@kbn/rule-registry-plugin/common/parse_technical_fields'; -import { InventoryItemType } from '@kbn/metrics-data-access-plugin/common'; +import type { InventoryItemType } from '@kbn/metrics-data-access-plugin/common'; import { fifteenMinutesInMilliseconds, HOST_FIELD, @@ -59,37 +59,36 @@ export const getInventoryViewInAppUrl = ( if (nodeType) { if (hostName) { return getLinkToHostDetails({ hostName, timestamp: inventoryFields[TIMESTAMP] }); - } else { - const linkToParams = { - nodeType: inventoryFields[nodeTypeField][0], - timestamp: Date.parse(inventoryFields[TIMESTAMP]), - customMetric: '', - metric: '', - }; + } + const linkToParams = { + nodeType: inventoryFields[nodeTypeField][0], + timestamp: Date.parse(inventoryFields[TIMESTAMP]), + customMetric: '', + metric: '', + }; - // We always pick the first criteria metric for the URL - const criteriaMetric = inventoryFields[`${ALERT_RULE_PARAMETERS}.criteria.metric`][0]; - if (criteriaMetric === 'custom') { - const criteriaCustomMetricId = - inventoryFields[`${ALERT_RULE_PARAMETERS}.criteria.customMetric.id`][0]; - const criteriaCustomMetricAggregation = - inventoryFields[`${ALERT_RULE_PARAMETERS}.criteria.customMetric.aggregation`][0]; - const criteriaCustomMetricField = - inventoryFields[`${ALERT_RULE_PARAMETERS}.criteria.customMetric.field`][0]; + // We always pick the first criteria metric for the URL + const criteriaMetric = inventoryFields[`${ALERT_RULE_PARAMETERS}.criteria.metric`][0]; + if (criteriaMetric === 'custom') { + const criteriaCustomMetricId = + inventoryFields[`${ALERT_RULE_PARAMETERS}.criteria.customMetric.id`][0]; + const criteriaCustomMetricAggregation = + inventoryFields[`${ALERT_RULE_PARAMETERS}.criteria.customMetric.aggregation`][0]; + const criteriaCustomMetricField = + inventoryFields[`${ALERT_RULE_PARAMETERS}.criteria.customMetric.field`][0]; - const customMetric = encode({ - id: criteriaCustomMetricId, - type: 'custom', - field: criteriaCustomMetricField, - aggregation: criteriaCustomMetricAggregation, - }); - linkToParams.customMetric = customMetric; - linkToParams.metric = customMetric; - } else { - linkToParams.metric = encode({ type: criteriaMetric }); - } - return `${LINK_TO_INVENTORY}?${stringify(linkToParams)}`; + const customMetric = encode({ + id: criteriaCustomMetricId, + type: 'custom', + field: criteriaCustomMetricField, + aggregation: criteriaCustomMetricAggregation, + }); + linkToParams.customMetric = customMetric; + linkToParams.metric = customMetric; + } else { + linkToParams.metric = encode({ type: criteriaMetric }); } + return `${LINK_TO_INVENTORY}?${stringify(linkToParams)}`; } return LINK_TO_INVENTORY; diff --git a/x-pack/plugins/observability_solution/infra/public/common/asset_details_config/asset_details_tabs.tsx b/x-pack/plugins/observability_solution/infra/public/common/asset_details_config/asset_details_tabs.tsx index d43ab65832271..1383e1c49915e 100644 --- a/x-pack/plugins/observability_solution/infra/public/common/asset_details_config/asset_details_tabs.tsx +++ b/x-pack/plugins/observability_solution/infra/public/common/asset_details_config/asset_details_tabs.tsx @@ -10,76 +10,107 @@ import { i18n } from '@kbn/i18n'; import React from 'react'; import { ContentTabIds, type Tab } from '../../components/asset_details/types'; -export const commonFlyoutTabs: Tab[] = [ - { - id: ContentTabIds.OVERVIEW, - name: i18n.translate('xpack.infra.assetDetails.tabs.overview', { - defaultMessage: 'Overview', - }), - }, - { - id: ContentTabIds.METADATA, - name: i18n.translate('xpack.infra.assetDetails.tabs.metadata', { - defaultMessage: 'Metadata', - }), - }, - { - id: ContentTabIds.METRICS, - name: i18n.translate('xpack.infra.assetDetails.tabs.metrics', { - defaultMessage: 'Metrics', - }), - }, - { - id: ContentTabIds.PROCESSES, - name: i18n.translate('xpack.infra.assetDetails.tabs.processes', { - defaultMessage: 'Processes', - }), - }, - { - id: ContentTabIds.PROFILING, - name: i18n.translate('xpack.infra.assetDetails.tabs.profiling', { - defaultMessage: 'Universal Profiling', - }), - }, - { - id: ContentTabIds.LOGS, - name: i18n.translate('xpack.infra.assetDetails.tabs.logs', { - defaultMessage: 'Logs', - }), - }, - { - id: ContentTabIds.ANOMALIES, - name: i18n.translate('xpack.infra.assetDetails.tabs.anomalies', { - defaultMessage: 'Anomalies', - }), - }, - { - id: ContentTabIds.OSQUERY, - name: i18n.translate('xpack.infra.assetDetails.tabs.osquery', { - defaultMessage: 'Osquery', - }), - }, - { - id: ContentTabIds.DASHBOARDS, - name: i18n.translate('xpack.infra.infra.nodeDetails.tabs.dashboards', { - defaultMessage: 'Dashboards', - }), - append: ( - - ), - }, +const overviewTab: Tab = { + id: ContentTabIds.OVERVIEW, + name: i18n.translate('xpack.infra.nodeDetails.tabs.overview.title', { + defaultMessage: 'Overview', + }), +}; + +const metadataTab: Tab = { + id: ContentTabIds.METADATA, + name: i18n.translate('xpack.infra.nodeDetails.tabs.metadata.title', { + defaultMessage: 'Metadata', + }), +}; + +const metricsTab: Tab = { + id: ContentTabIds.METRICS, + name: i18n.translate('xpack.infra.nodeDetails.tabs.metrics.title', { + defaultMessage: 'Metrics', + }), +}; + +const processesTab: Tab = { + id: ContentTabIds.PROCESSES, + name: i18n.translate('xpack.infra.metrics.nodeDetails.tabs.processes', { + defaultMessage: 'Processes', + }), +}; + +const profilingTab: Tab = { + id: ContentTabIds.PROFILING, + name: i18n.translate('xpack.infra.metrics.nodeDetails.tabs.profiling', { + defaultMessage: 'Universal Profiling', + }), +}; + +const logsTab: Tab = { + id: ContentTabIds.LOGS, + name: i18n.translate('xpack.infra.nodeDetails.tabs.logs.title', { + defaultMessage: 'Logs', + }), +}; + +const anomaliesTab: Tab = { + id: ContentTabIds.ANOMALIES, + name: i18n.translate('xpack.infra.nodeDetails.tabs.anomalies', { + defaultMessage: 'Anomalies', + }), +}; + +const osqueryTab: Tab = { + id: ContentTabIds.OSQUERY, + name: i18n.translate('xpack.infra.nodeDetails.tabs.osquery', { + defaultMessage: 'Osquery', + }), +}; + +const dashboardsTab: Tab = { + id: ContentTabIds.DASHBOARDS, + name: i18n.translate('xpack.infra.infra.nodeDetails.tabs.dashboards', { + defaultMessage: 'Dashboards', + }), + append: ( + + ), +}; + +export const hostDetailsTabs: Tab[] = [ + overviewTab, + metadataTab, + metricsTab, + processesTab, + profilingTab, + logsTab, + anomaliesTab, + osqueryTab, + dashboardsTab, ]; +// Profiling and Logs tab would be added in next iteration +export const containerDetailsTabs: Tab[] = [overviewTab, metadataTab]; + +export const getAssetDetailsTabs = (type: string): Tab[] => { + switch (type) { + case 'host': + return hostDetailsTabs; + case 'container': + return containerDetailsTabs; + default: + return []; + } +}; diff --git a/x-pack/plugins/observability_solution/infra/public/common/visualizations/constants.ts b/x-pack/plugins/observability_solution/infra/public/common/visualizations/constants.ts index 76b2eb7c3d70f..959ff1145f7d4 100644 --- a/x-pack/plugins/observability_solution/infra/public/common/visualizations/constants.ts +++ b/x-pack/plugins/observability_solution/infra/public/common/visualizations/constants.ts @@ -7,6 +7,7 @@ export const HOST_METRICS_DOC_HREF = 'https://ela.st/docs-infra-host-metrics'; export const HOST_METRICS_DOTTED_LINES_DOC_HREF = 'https://ela.st/docs-infra-why-dotted'; +export const CONTAINER_METRICS_DOC_HREF = 'https://ela.st/docs-infra-docker-container-metrics'; export const KPI_CHART_HEIGHT = 150; export const METRIC_CHART_HEIGHT = 300; diff --git a/x-pack/plugins/observability_solution/infra/public/components/asset_details/charts/chart.tsx b/x-pack/plugins/observability_solution/infra/public/components/asset_details/charts/chart.tsx index a1edbfa327a4b..f1ccf0ef31b2b 100644 --- a/x-pack/plugins/observability_solution/infra/public/components/asset_details/charts/chart.tsx +++ b/x-pack/plugins/observability_solution/infra/public/components/asset_details/charts/chart.tsx @@ -10,7 +10,7 @@ import type { LensConfig, LensDataviewDataset } from '@kbn/lens-embeddable-utils import type { TimeRange } from '@kbn/es-query'; import { useDataView } from '../../../hooks/use_data_view'; import { METRIC_CHART_HEIGHT } from '../../../common/visualizations/constants'; -import { buildCombinedHostsFilter } from '../../../utils/filters/build'; +import { buildCombinedAssetFilter } from '../../../utils/filters/build'; import { type BrushEndArgs, LensChart, type OnFilterEvent, LensChartProps } from '../../lens'; import { useDatePickerContext } from '../hooks/use_date_picker'; import { extractRangeFromChartFilterEvent } from './chart_utils'; @@ -31,7 +31,7 @@ export const Chart = ({ id, queryField, overrides, dateRange, assetId, ...props const filters = useMemo(() => { return [ - buildCombinedHostsFilter({ + buildCombinedAssetFilter({ field: queryField, values: [assetId], dataView, diff --git a/x-pack/plugins/observability_solution/infra/public/components/asset_details/charts/docker_charts.tsx b/x-pack/plugins/observability_solution/infra/public/components/asset_details/charts/docker_charts.tsx new file mode 100644 index 0000000000000..795a66b5a2e80 --- /dev/null +++ b/x-pack/plugins/observability_solution/infra/public/components/asset_details/charts/docker_charts.tsx @@ -0,0 +1,87 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { findInventoryFields } from '@kbn/metrics-data-access-plugin/common'; +import { FormattedMessage } from '@kbn/i18n-react'; +import { css, cx } from '@emotion/css'; +import { EuiText, EuiLink } from '@elastic/eui'; +import { useDockerContainerPageViewMetricsCharts } from '../hooks/use_container_metrics_charts'; +import { Section } from '../components/section'; +import { ChartsGrid } from '../charts_grid/charts_grid'; +import { Chart } from './chart'; +import { TitleWithTooltip } from '../components/section_title'; +import { CONTAINER_METRIC_GROUP_TITLES } from '../translations'; +import { CONTAINER_METRICS_DOC_HREF } from '../../../common/visualizations/constants'; +import { MetricsChartsFields, ContainerMetricTypes } from './types'; + +interface Props extends MetricsChartsFields { + metric: ContainerMetricTypes; +} + +const FRAGMENT_BASE = 'key-metrics'; + +export const DockerCharts = React.forwardRef( + ({ assetId, dataView, dateRange, metric }, ref) => { + const { charts } = useDockerContainerPageViewMetricsCharts({ + metric, + metricsDataViewId: dataView?.id, + }); + return ( +
+ + + + ), + }} + /> + + } + /> + } + data-test-subj={`infraAssetDetailsDockerChartsSection${metric}`} + id="dockerContainerCharts" + ref={ref} + > + + {charts.map((chart) => ( + + ))} + +
+ ); + } +); diff --git a/x-pack/plugins/observability_solution/infra/public/components/asset_details/charts/host_charts.tsx b/x-pack/plugins/observability_solution/infra/public/components/asset_details/charts/host_charts.tsx index 79d225cd02882..d8d60deb81efb 100644 --- a/x-pack/plugins/observability_solution/infra/public/components/asset_details/charts/host_charts.tsx +++ b/x-pack/plugins/observability_solution/infra/public/components/asset_details/charts/host_charts.tsx @@ -5,8 +5,6 @@ * 2.0. */ import React from 'react'; -import type { DataView } from '@kbn/data-views-plugin/public'; -import type { TimeRange } from '@kbn/es-query'; import { EuiText, EuiLink, EuiButtonEmpty } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; import { findInventoryFields } from '@kbn/metrics-data-access-plugin/common'; @@ -16,16 +14,12 @@ import { HOST_METRIC_GROUP_TITLES } from '../translations'; import { Section } from '../components/section'; import { ChartsGrid } from '../charts_grid/charts_grid'; import { Chart } from './chart'; -import { type HostMetricTypes, useHostCharts } from '../hooks/use_metrics_charts'; +import { useHostCharts } from '../hooks/use_host_metrics_charts'; import { TitleWithTooltip } from '../components/section_title'; +import { MetricsChartsFields, HostMetricTypes } from './types'; -interface Props { - assetId: string; - dateRange: TimeRange; - dataView?: DataView; - overview?: boolean; +interface Props extends MetricsChartsFields { metric: Exclude; - onShowAll?: (metric: string) => void; } const FRAGMENT_BASE = 'key-metrics'; diff --git a/x-pack/plugins/observability_solution/infra/public/components/asset_details/charts/index.tsx b/x-pack/plugins/observability_solution/infra/public/components/asset_details/charts/index.tsx index 180a5558e29bd..c242cccdf952a 100644 --- a/x-pack/plugins/observability_solution/infra/public/components/asset_details/charts/index.tsx +++ b/x-pack/plugins/observability_solution/infra/public/components/asset_details/charts/index.tsx @@ -6,4 +6,5 @@ */ export { HostCharts } from './host_charts'; -export { KubernetesCharts } from './kubernetes_charts'; +export { KubernetesNodeCharts, KubernetesContainerCharts } from './kubernetes_charts'; +export { DockerCharts } from './docker_charts'; diff --git a/x-pack/plugins/observability_solution/infra/public/components/asset_details/charts/kubernetes_charts.tsx b/x-pack/plugins/observability_solution/infra/public/components/asset_details/charts/kubernetes_charts.tsx index 8791b351bf7e7..b386b1e9d8cbc 100644 --- a/x-pack/plugins/observability_solution/infra/public/components/asset_details/charts/kubernetes_charts.tsx +++ b/x-pack/plugins/observability_solution/infra/public/components/asset_details/charts/kubernetes_charts.tsx @@ -5,66 +5,124 @@ * 2.0. */ import React from 'react'; -import { EuiButtonEmpty } from '@elastic/eui'; +import { EuiButtonEmpty, EuiText, EuiLink } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; -import type { TimeRange } from '@kbn/es-query'; -import type { DataView } from '@kbn/data-views-plugin/public'; +import { css, cx } from '@emotion/css'; import { findInventoryFields } from '@kbn/metrics-data-access-plugin/common'; -import { useKubernetesCharts } from '../hooks/use_metrics_charts'; +import { useKubernetesCharts } from '../hooks/use_host_metrics_charts'; import { Section } from '../components/section'; -import { SectionTitle } from '../components/section_title'; -import { HOST_METRIC_GROUP_TITLES } from '../translations'; +import { SectionTitle, TitleWithTooltip } from '../components/section_title'; +import { CONTAINER_METRIC_GROUP_TITLES, HOST_METRIC_GROUP_TITLES } from '../translations'; import { INTEGRATIONS } from '../constants'; import { ChartsGrid } from '../charts_grid/charts_grid'; import { Chart } from './chart'; import { useIntegrationCheck } from '../hooks/use_integration_check'; +import { useK8sContainerPageViewMetricsCharts } from '../hooks/use_container_metrics_charts'; +import { CONTAINER_METRICS_DOC_HREF } from '../../../common/visualizations/constants'; +import { ContainerMetricTypes, MetricsChartsFields } from './types'; -interface Props { - assetId: string; - dateRange: TimeRange; - dataView?: DataView; - overview?: boolean; - onShowAll?: (metric: string) => void; -} +const FRAGMENT_BASE = 'key-metrics'; -export const KubernetesCharts = React.forwardRef< - HTMLDivElement, - Props & { onShowAll?: (metric: string) => void } ->(({ assetId, dataView, dateRange, onShowAll, overview }, ref) => { - const { charts } = useKubernetesCharts({ - dataViewId: dataView?.id, - options: { overview }, - }); +export const KubernetesNodeCharts = React.forwardRef( + ({ assetId, dataView, dateRange, onShowAll, overview }, ref) => { + const { charts } = useKubernetesCharts({ + dataViewId: dataView?.id, + options: { overview }, + }); + + const hasIntegration = useIntegrationCheck({ dependsOn: INTEGRATIONS.kubernetesNode }); - const hasIntegration = useIntegrationCheck({ dependsOn: INTEGRATIONS.kubernetes }); + if (!hasIntegration) { + return null; + } - if (!hasIntegration) { - return null; + return ( +
} + data-test-subj="infraAssetDetailsKubernetesChartsSection" + id="kubernetes" + ref={ref} + extraAction={ + onShowAll ? ( + onShowAll('kubernetes')} + size="xs" + flush="both" + iconSide="right" + iconType="sortRight" + > + + + ) : null + } + > + + {charts.map((chart) => ( + + ))} + +
+ ); } +); +export const KubernetesContainerCharts = React.forwardRef< + HTMLDivElement, + MetricsChartsFields & { metric: ContainerMetricTypes } +>(({ assetId, dataView, dateRange, metric }, ref) => { + const { charts } = useK8sContainerPageViewMetricsCharts({ + metric, + metricsDataViewId: dataView?.id, + }); return (
} - data-test-subj="infraAssetDetailsKubernetesChartsSection" - id="kubernetes" - ref={ref} - extraAction={ - onShowAll ? ( - onShowAll('kubernetes')} - size="xs" - flush="both" - iconSide="right" - iconType="sortRight" - > - - - ) : null + title={ + + + + + ), + }} + /> + + } + /> } + data-test-subj="infraAssetDetailsK8ContainerChartsSection" + id="k8sContainerCharts" + ref={ref} > {charts.map((chart) => ( @@ -73,7 +131,7 @@ export const KubernetesCharts = React.forwardRef< {...chart} assetId={assetId} dateRange={dateRange} - queryField={findInventoryFields('host').id} + queryField={findInventoryFields('container').id} /> ))} diff --git a/x-pack/plugins/observability_solution/infra/public/components/asset_details/charts/types.ts b/x-pack/plugins/observability_solution/infra/public/components/asset_details/charts/types.ts new file mode 100644 index 0000000000000..a01a5c7f7ced2 --- /dev/null +++ b/x-pack/plugins/observability_solution/infra/public/components/asset_details/charts/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 { DataView } from '@kbn/data-views-plugin/public'; +import type { TimeRange } from '@kbn/es-query'; + +export type HostMetricTypes = 'cpu' | 'memory' | 'network' | 'disk' | 'log' | 'kpi'; +export type KubernetesContainerMetrics = 'cpu' | 'memory'; +export type DockerContainerMetrics = 'cpu' | 'memory' | 'network' | 'disk'; +export type ContainerMetricTypes = KubernetesContainerMetrics | DockerContainerMetrics; + +export interface MetricsChartsFields { + assetId: string; + dateRange: TimeRange; + dataView?: DataView; + overview?: boolean; + onShowAll?: (metric: string) => void; +} diff --git a/x-pack/plugins/observability_solution/infra/public/components/asset_details/components/kpis/container_kpi_charts.tsx b/x-pack/plugins/observability_solution/infra/public/components/asset_details/components/kpis/container_kpi_charts.tsx new file mode 100644 index 0000000000000..8e4a67526f72c --- /dev/null +++ b/x-pack/plugins/observability_solution/infra/public/components/asset_details/components/kpis/container_kpi_charts.tsx @@ -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 React from 'react'; +import { EuiFlexItem, useEuiTheme } from '@elastic/eui'; +import type { DataView } from '@kbn/data-views-plugin/public'; +import type { Filter, Query, TimeRange } from '@kbn/es-query'; +import { Kpi } from './kpi'; +import { + useK8sContainerKpiCharts, + useDockerContainerKpiCharts, +} from '../../hooks/use_container_metrics_charts'; +import { useIntegrationCheck } from '../../hooks/use_integration_check'; +import { INTEGRATIONS } from '../../constants'; + +export interface ContainerKpiChartsProps { + dataView?: DataView; + dateRange: TimeRange; + query?: Query; + filters?: Filter[]; + searchSessionId?: string; + options?: { + getSubtitle?: (formulaValue: string) => string; + }; + loading?: boolean; +} + +export const ContainerKpiCharts = ({ + dateRange, + dataView, + filters, + options, + query, + searchSessionId, + loading = false, +}: ContainerKpiChartsProps) => { + const isK8Container = useIntegrationCheck({ dependsOn: INTEGRATIONS.kubernetesContainer }); + + return isK8Container ? ( + + ) : ( + + ); +}; + +const DockerKpiCharts = ({ + dateRange, + dataView, + filters, + options, + query, + searchSessionId, + loading = false, +}: ContainerKpiChartsProps) => { + const { euiTheme } = useEuiTheme(); + const charts = useDockerContainerKpiCharts({ + dataViewId: dataView?.id, + options: { + getSubtitle: options?.getSubtitle, + seriesColor: euiTheme.colors.lightestShade, + }, + }); + + return ( + <> + {charts.map((chartProps, index) => ( + + + + ))} + + ); +}; + +const KubernetesKpiCharts = ({ + dateRange, + dataView, + filters, + options, + query, + searchSessionId, + loading = false, +}: ContainerKpiChartsProps) => { + const { euiTheme } = useEuiTheme(); + const charts = useK8sContainerKpiCharts({ + dataViewId: dataView?.id, + options: { + getSubtitle: options?.getSubtitle, + seriesColor: euiTheme.colors.lightestShade, + }, + }); + + return ( + <> + {charts.map((chartProps, index) => ( + + + + ))} + + ); +}; diff --git a/x-pack/plugins/observability_solution/infra/public/components/asset_details/components/kpis/host_kpi_charts.tsx b/x-pack/plugins/observability_solution/infra/public/components/asset_details/components/kpis/host_kpi_charts.tsx index e73f5a6cd0656..fa11d67df90e9 100644 --- a/x-pack/plugins/observability_solution/infra/public/components/asset_details/components/kpis/host_kpi_charts.tsx +++ b/x-pack/plugins/observability_solution/infra/public/components/asset_details/components/kpis/host_kpi_charts.tsx @@ -10,7 +10,7 @@ import { EuiFlexItem, useEuiTheme } from '@elastic/eui'; import type { DataView } from '@kbn/data-views-plugin/public'; import type { Filter, Query, TimeRange } from '@kbn/es-query'; import { Kpi } from './kpi'; -import { useHostKpiCharts } from '../../hooks/use_metrics_charts'; +import { useHostKpiCharts } from '../../hooks/use_host_metrics_charts'; export interface HostKpiChartsProps { dataView?: DataView; diff --git a/x-pack/plugins/observability_solution/infra/public/components/asset_details/constants.ts b/x-pack/plugins/observability_solution/infra/public/components/asset_details/constants.ts index 4c66628324c50..81a82ecb30875 100644 --- a/x-pack/plugins/observability_solution/infra/public/components/asset_details/constants.ts +++ b/x-pack/plugins/observability_solution/infra/public/components/asset_details/constants.ts @@ -15,5 +15,7 @@ export const APM_HOST_FILTER_FIELD = 'host.hostname'; export const ASSET_DETAILS_URL_STATE_KEY = 'assetDetails'; export const INTEGRATIONS = { - [INTEGRATION_NAME.kubernetes]: 'kubernetes.node', + [INTEGRATION_NAME.kubernetesNode]: 'kubernetes.node', + [INTEGRATION_NAME.kubernetesContainer]: 'kubernetes.container', + [INTEGRATION_NAME.docker]: 'docker', }; diff --git a/x-pack/plugins/observability_solution/infra/public/components/asset_details/hooks/use_container_metrics_charts.test.ts b/x-pack/plugins/observability_solution/infra/public/components/asset_details/hooks/use_container_metrics_charts.test.ts new file mode 100644 index 0000000000000..f35c7ca63b552 --- /dev/null +++ b/x-pack/plugins/observability_solution/infra/public/components/asset_details/hooks/use_container_metrics_charts.test.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 { renderHook } from '@testing-library/react-hooks'; +import { ContainerMetricTypes } from '../charts/types'; +import { + useK8sContainerPageViewMetricsCharts, + useDockerContainerPageViewMetricsCharts, + useDockerContainerKpiCharts, + useK8sContainerKpiCharts, +} from './use_container_metrics_charts'; + +const metricsDataViewId = 'metricsDataViewId'; +const getContainerChartsExpectedOrder = (metric: ContainerMetricTypes): string[] => { + switch (metric) { + case 'cpu': + return ['cpuUsage']; + case 'memory': + return ['memoryUsage']; + default: + return []; + } +}; + +const getK8sContainerChartsExpectedOrder = (metric: ContainerMetricTypes): string[] => { + switch (metric) { + case 'cpu': + return ['k8sCpuUsage']; + case 'memory': + return ['k8sMemoryUsage']; + default: + return []; + } +}; + +describe('useDockerContainerCharts', () => { + describe.each<[ContainerMetricTypes]>([['cpu'], ['memory']])('%s', (item) => { + test.each<[ContainerMetricTypes]>([[item]])( + 'should return an array of charts with correct order for metric "%s"', + async (metric) => { + const expectedOrder = getContainerChartsExpectedOrder(metric); + + const { result, waitForNextUpdate } = renderHook(() => + useDockerContainerPageViewMetricsCharts({ metricsDataViewId, metric }) + ); + await waitForNextUpdate(); + + const { charts } = result.current; + + expect(charts).toHaveLength(expectedOrder.length); + + charts.forEach((chart, index) => { + expect(chart).toHaveProperty('id', expectedOrder[index]); + }); + } + ); + }); +}); + +describe('useDockerKPIMetricsCharts', () => { + it('should return an array of charts with correct order', async () => { + const expectedOrder = ['cpuUsage', 'memoryUsage']; + const { result, waitForNextUpdate } = renderHook(() => + useDockerContainerKpiCharts({ dataViewId: metricsDataViewId }) + ); + await waitForNextUpdate(); + expect(result.current).toHaveLength(expectedOrder.length); + result.current.forEach((chart, index) => { + expect(chart).toHaveProperty('id', expectedOrder[index]); + }); + }); +}); + +describe('useK8sContainerCharts', () => { + describe.each<[ContainerMetricTypes]>([['cpu'], ['memory']])('%s', (item) => { + test.each<[ContainerMetricTypes]>([[item]])( + 'should return an array of charts with correct order for metric "%s"', + async (metric) => { + const expectedOrder = getK8sContainerChartsExpectedOrder(metric); + + const { result, waitForNextUpdate } = renderHook(() => + useK8sContainerPageViewMetricsCharts({ metricsDataViewId, metric }) + ); + await waitForNextUpdate(); + + const { charts } = result.current; + + expect(charts).toHaveLength(expectedOrder.length); + + charts.forEach((chart, index) => { + expect(chart).toHaveProperty('id', expectedOrder[index]); + }); + } + ); + }); +}); + +describe('useK8sContainerKPIMetricsCharts', () => { + it('should return an array of charts with correct order', async () => { + const expectedOrder = ['k8sCpuUsage', 'k8sMemoryUsage']; + const { result, waitForNextUpdate } = renderHook(() => + useK8sContainerKpiCharts({ dataViewId: metricsDataViewId }) + ); + await waitForNextUpdate(); + expect(result.current).toHaveLength(expectedOrder.length); + result.current.forEach((chart, index) => { + expect(chart).toHaveProperty('id', expectedOrder[index]); + }); + }); +}); diff --git a/x-pack/plugins/observability_solution/infra/public/components/asset_details/hooks/use_container_metrics_charts.ts b/x-pack/plugins/observability_solution/infra/public/components/asset_details/hooks/use_container_metrics_charts.ts new file mode 100644 index 0000000000000..08710378643d5 --- /dev/null +++ b/x-pack/plugins/observability_solution/infra/public/components/asset_details/hooks/use_container_metrics_charts.ts @@ -0,0 +1,163 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { i18n } from '@kbn/i18n'; +import { findInventoryModel } from '@kbn/metrics-data-access-plugin/common'; +import useAsync from 'react-use/lib/useAsync'; +import { ContainerMetricTypes } from '../charts/types'; + +const getSubtitleFromFormula = (value: string) => + value.startsWith('max') + ? i18n.translate('xpack.infra.containerViewPage.kpi.subtitle.max', { defaultMessage: 'Max' }) + : i18n.translate('xpack.infra.assetDetails.kpi.subtitle.average', { + defaultMessage: 'Average', + }); + +export const useDockerContainerPageViewMetricsCharts = ({ + metric, + metricsDataViewId, +}: { + metric: ContainerMetricTypes; + metricsDataViewId?: string; +}) => { + const { value: charts = [], error } = useAsync(async () => { + const containerCharts = await getDockerContainerCharts(metric); + + return containerCharts.map((chart) => { + return { + ...chart, + ...(metricsDataViewId && { + dataset: { + index: metricsDataViewId, + }, + }), + }; + }); + }, [metricsDataViewId]); + + return { charts, error }; +}; + +const getDockerContainerCharts = async (metric: ContainerMetricTypes) => { + const model = findInventoryModel('container'); + const { cpu, memory } = await model.metrics.getCharts(); + + switch (metric) { + case 'cpu': + return [cpu.xy.dockerContainerCpuUsage]; + case 'memory': + return [memory.xy.dockerContainerMemoryUsage]; + default: + return []; + } +}; + +export const useK8sContainerPageViewMetricsCharts = ({ + metric, + metricsDataViewId, +}: { + metric: ContainerMetricTypes; + metricsDataViewId?: string; +}) => { + const { value: charts = [], error } = useAsync(async () => { + const containerK8sCharts = await getK8sContainerCharts(metric); + + return containerK8sCharts.map((chart) => { + return { + ...chart, + ...(metricsDataViewId && { + dataset: { + index: metricsDataViewId, + }, + }), + }; + }); + }, [metricsDataViewId]); + + return { charts, error }; +}; + +const getK8sContainerCharts = async (metric: ContainerMetricTypes) => { + const model = findInventoryModel('container'); + const { cpu, memory } = await model.metrics.getCharts(); + + switch (metric) { + case 'cpu': + return [cpu.xy.k8sContainerCpuUsage]; + case 'memory': + return [memory.xy.k8sContainerMemoryUsage]; + default: + return []; + } +}; + +export const useDockerContainerKpiCharts = ({ + dataViewId, + options, +}: { + dataViewId?: string; + options?: { seriesColor: string; getSubtitle?: (formulaValue: string) => string }; +}) => { + const { value: charts = [] } = useAsync(async () => { + const model = findInventoryModel('container'); + const { cpu, memory } = await model.metrics.getCharts(); + + return [cpu.metric.dockerContainerCpuUsage, memory.metric.dockerContainerMemoryUsage].map( + (chart) => ({ + ...chart, + seriesColor: options?.seriesColor, + decimals: 1, + subtitle: getSubtitle(options, chart), + ...(dataViewId && { + dataset: { + index: dataViewId, + }, + }), + }) + ); + }, [dataViewId, options?.seriesColor, options?.getSubtitle]); + + return charts; +}; + +export const useK8sContainerKpiCharts = ({ + dataViewId, + options, +}: { + dataViewId?: string; + options?: { seriesColor: string; getSubtitle?: (formulaValue: string) => string }; +}) => { + const { value: charts = [] } = useAsync(async () => { + const model = findInventoryModel('container'); + const { cpu, memory } = await model.metrics.getCharts(); + + return [cpu.metric.k8sContainerCpuUsage, memory.metric.k8sContainerMemoryUsage].map( + (chart) => ({ + ...chart, + seriesColor: options?.seriesColor, + decimals: 1, + subtitle: getSubtitle(options, chart), + ...(dataViewId && { + dataset: { + index: dataViewId, + }, + }), + }) + ); + }, [dataViewId, options?.seriesColor, options?.getSubtitle]); + + return charts; +}; + +function getSubtitle( + options: { getSubtitle?: ((formulaValue: string) => string) | undefined } | undefined, + chart: { value: string } +) { + return options?.getSubtitle + ? options?.getSubtitle(chart.value) + : getSubtitleFromFormula(chart.value); +} diff --git a/x-pack/plugins/observability_solution/infra/public/components/asset_details/hooks/use_metrics_charts.test.ts b/x-pack/plugins/observability_solution/infra/public/components/asset_details/hooks/use_host_metrics_charts.test.ts similarity index 97% rename from x-pack/plugins/observability_solution/infra/public/components/asset_details/hooks/use_metrics_charts.test.ts rename to x-pack/plugins/observability_solution/infra/public/components/asset_details/hooks/use_host_metrics_charts.test.ts index 1e0573e187074..c4e3815f5e0f8 100644 --- a/x-pack/plugins/observability_solution/infra/public/components/asset_details/hooks/use_metrics_charts.test.ts +++ b/x-pack/plugins/observability_solution/infra/public/components/asset_details/hooks/use_host_metrics_charts.test.ts @@ -6,12 +6,8 @@ */ import { renderHook } from '@testing-library/react-hooks'; -import { - useHostKpiCharts, - useHostCharts, - useKubernetesCharts, - type HostMetricTypes, -} from './use_metrics_charts'; +import { HostMetricTypes } from '../charts/types'; +import { useHostKpiCharts, useHostCharts, useKubernetesCharts } from './use_host_metrics_charts'; const dataViewId = 'metricsDataViewId'; const getHostChartsExpectedOrder = (metric: HostMetricTypes, overview: boolean): string[] => { diff --git a/x-pack/plugins/observability_solution/infra/public/components/asset_details/hooks/use_metrics_charts.ts b/x-pack/plugins/observability_solution/infra/public/components/asset_details/hooks/use_host_metrics_charts.ts similarity index 91% rename from x-pack/plugins/observability_solution/infra/public/components/asset_details/hooks/use_metrics_charts.ts rename to x-pack/plugins/observability_solution/infra/public/components/asset_details/hooks/use_host_metrics_charts.ts index 5450e86029670..6d5381caf6187 100644 --- a/x-pack/plugins/observability_solution/infra/public/components/asset_details/hooks/use_metrics_charts.ts +++ b/x-pack/plugins/observability_solution/infra/public/components/asset_details/hooks/use_host_metrics_charts.ts @@ -8,8 +8,8 @@ import { i18n } from '@kbn/i18n'; import { findInventoryModel } from '@kbn/metrics-data-access-plugin/common'; import useAsync from 'react-use/lib/useAsync'; +import { HostMetricTypes } from '../charts/types'; -export type HostMetricTypes = 'cpu' | 'memory' | 'network' | 'disk' | 'log' | 'kpi'; interface UseChartsOptions { overview?: boolean; } @@ -101,9 +101,7 @@ export const useHostKpiCharts = ({ ...chart, seriesColor: options?.seriesColor, decimals: 1, - subtitle: options?.getSubtitle - ? options?.getSubtitle(chart.value) - : getSubtitleFromFormula(chart.value), + subtitle: getSubtitle(options, chart), ...(dataViewId && { dataset: { index: dataViewId, @@ -151,3 +149,12 @@ const getHostsCharts = async ({ return []; } }; + +function getSubtitle( + options: { getSubtitle?: ((formulaValue: string) => string) | undefined } | undefined, + chart: { value: string } +) { + return options?.getSubtitle + ? options?.getSubtitle(chart.value) + : getSubtitleFromFormula(chart.value); +} diff --git a/x-pack/plugins/observability_solution/infra/public/components/asset_details/tabs/metrics/host_metrics.tsx b/x-pack/plugins/observability_solution/infra/public/components/asset_details/tabs/metrics/host_metrics.tsx index 3246d452399cb..9d08a628aec5f 100644 --- a/x-pack/plugins/observability_solution/infra/public/components/asset_details/tabs/metrics/host_metrics.tsx +++ b/x-pack/plugins/observability_solution/infra/public/components/asset_details/tabs/metrics/host_metrics.tsx @@ -6,13 +6,13 @@ */ import React, { useRef } from 'react'; -import { HostMetricTypes } from '../../hooks/use_metrics_charts'; import { useDatePickerContext } from '../../hooks/use_date_picker'; import { useAssetDetailsRenderPropsContext } from '../../hooks/use_asset_details_render_props'; import { useDataViewsContext } from '../../hooks/use_data_views'; import { useIntersectingState } from '../../hooks/use_intersecting_state'; import { MetricsTemplate } from './metrics_template'; -import { HostCharts, KubernetesCharts } from '../../charts'; +import { HostCharts, KubernetesNodeCharts } from '../../charts'; +import { HostMetricTypes } from '../../charts/types'; const METRIC_TYPES: Array> = [ 'cpu', @@ -41,7 +41,7 @@ export const HostMetrics = () => { metric={metric} /> ))} - { +export const KPIGrid = ({ assetId, assetType, dataView, dateRange }: Props) => { const { searchSessionId } = useLoadingStateContext(); const filters = useMemo(() => { return [ - buildCombinedHostsFilter({ - field: findInventoryFields('host').id, + buildCombinedAssetFilter({ + field: findInventoryFields(assetType).id, values: [assetId], dataView, }), ]; - }, [dataView, assetId]); + }, [dataView, assetId, assetType]); return ( - + {assetType === 'host' ? ( + + ) : ( + + )} ); }; diff --git a/x-pack/plugins/observability_solution/infra/public/components/asset_details/tabs/overview/metrics/container_metrics.tsx b/x-pack/plugins/observability_solution/infra/public/components/asset_details/tabs/overview/metrics/container_metrics.tsx new file mode 100644 index 0000000000000..f14619005eadb --- /dev/null +++ b/x-pack/plugins/observability_solution/infra/public/components/asset_details/tabs/overview/metrics/container_metrics.tsx @@ -0,0 +1,42 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import React from 'react'; +import { EuiFlexGroup, EuiFlexGrid } from '@elastic/eui'; +import type { TimeRange } from '@kbn/es-query'; +import type { DataView } from '@kbn/data-views-plugin/public'; +import { DockerCharts } from '../../../charts/docker_charts'; +import { INTEGRATIONS } from '../../../constants'; +import { useIntegrationCheck } from '../../../hooks/use_integration_check'; +import { KubernetesContainerCharts } from '../../../charts/kubernetes_charts'; + +interface Props { + assetId: string; + dateRange: TimeRange; + dataView?: DataView; +} + +export const ContainerMetrics = (props: Props) => { + const isK8sContainer = useIntegrationCheck({ dependsOn: INTEGRATIONS.kubernetesContainer }); + + return ( + + + {isK8sContainer ? ( + <> + + + + ) : ( + <> + + + + )} + + + ); +}; diff --git a/x-pack/plugins/observability_solution/infra/public/components/asset_details/tabs/overview/metrics/host_metrics.tsx b/x-pack/plugins/observability_solution/infra/public/components/asset_details/tabs/overview/metrics/host_metrics.tsx index e7fe8bf795b47..6ac962570ebc6 100644 --- a/x-pack/plugins/observability_solution/infra/public/components/asset_details/tabs/overview/metrics/host_metrics.tsx +++ b/x-pack/plugins/observability_solution/infra/public/components/asset_details/tabs/overview/metrics/host_metrics.tsx @@ -9,7 +9,7 @@ import { EuiFlexGroup, EuiFlexGrid } from '@elastic/eui'; import type { TimeRange } from '@kbn/es-query'; import type { DataView } from '@kbn/data-views-plugin/public'; import { useTabSwitcherContext } from '../../../hooks/use_tab_switcher'; -import { HostCharts, KubernetesCharts } from '../../../charts'; +import { HostCharts, KubernetesNodeCharts } from '../../../charts'; import { ContentTabIds } from '../../../types'; interface Props { @@ -33,7 +33,7 @@ export const HostMetrics = (props: Props) => { - + ); }; diff --git a/x-pack/plugins/observability_solution/infra/public/components/asset_details/tabs/overview/metrics/metrics.tsx b/x-pack/plugins/observability_solution/infra/public/components/asset_details/tabs/overview/metrics/metrics.tsx index b5cdac6bd4a74..f3ad7da1b99f5 100644 --- a/x-pack/plugins/observability_solution/infra/public/components/asset_details/tabs/overview/metrics/metrics.tsx +++ b/x-pack/plugins/observability_solution/infra/public/components/asset_details/tabs/overview/metrics/metrics.tsx @@ -9,6 +9,7 @@ import type { TimeRange } from '@kbn/es-query'; import type { DataView } from '@kbn/data-views-plugin/public'; import { InventoryItemType } from '@kbn/metrics-data-access-plugin/common'; import { HostMetrics } from './host_metrics'; +import { ContainerMetrics } from './container_metrics'; import { Section } from '../../../components/section'; import { MetricsSectionTitle } from '../section_titles'; @@ -24,6 +25,8 @@ export const MetricsContent = ({ assetType, ...props }: Props) => { switch (assetType) { case 'host': return ; + case 'container': + return ; default: return null; } @@ -31,7 +34,7 @@ export const MetricsContent = ({ assetType, ...props }: Props) => { return (
} + title={} data-test-subj="infraAssetDetailsMetricsCollapsible" id="metrics" collapsible diff --git a/x-pack/plugins/observability_solution/infra/public/components/asset_details/tabs/overview/overview.tsx b/x-pack/plugins/observability_solution/infra/public/components/asset_details/tabs/overview/overview.tsx index c67347a765d69..99723fce587ba 100644 --- a/x-pack/plugins/observability_solution/infra/public/components/asset_details/tabs/overview/overview.tsx +++ b/x-pack/plugins/observability_solution/infra/public/components/asset_details/tabs/overview/overview.tsx @@ -48,21 +48,29 @@ export const Overview = () => { return ( - - - - - {fetchMetadataError && !metadataLoading ? : metadataSummarySection} - - - - + {asset.type === 'host' ? : null} + + + + {fetchMetadataError && !metadataLoading ? : metadataSummarySection} + {asset.type === 'host' ? ( + + + + + ) : null} {asset.type === 'host' ? ( diff --git a/x-pack/plugins/observability_solution/infra/public/components/asset_details/tabs/overview/section_titles.tsx b/x-pack/plugins/observability_solution/infra/public/components/asset_details/tabs/overview/section_titles.tsx index c330944ffbcdc..d7a718939056a 100644 --- a/x-pack/plugins/observability_solution/infra/public/components/asset_details/tabs/overview/section_titles.tsx +++ b/x-pack/plugins/observability_solution/infra/public/components/asset_details/tabs/overview/section_titles.tsx @@ -6,12 +6,14 @@ */ import React from 'react'; import { i18n } from '@kbn/i18n'; +import type { InventoryItemType } from '@kbn/metrics-data-access-plugin/common'; import { HostMetricsExplanationContent } from '../../../lens'; import { TitleWithTooltip } from '../../components/section_title'; import { AlertsTooltipContent } from '../../components/alerts_tooltip_content'; import { ServicesTooltipContent } from '../../components/services_tooltip_content'; +import { ContainerMetricsExplanationContent } from '../../../lens/metric_explanation/container_metrics_explanation_content'; -export const MetricsSectionTitle = () => { +export const MetricsSectionTitle = ({ assetType }: { assetType: InventoryItemType }) => { return ( { })} data-test-subj="infraAssetDetailsMetricsTitle" tooltipTestSubj="infraAssetDetailsMetricsPopoverButton" - tooltipContent={} + tooltipContent={getTooltipContent(assetType)} /> ); }; @@ -47,3 +49,12 @@ export const ServicesSectionTitle = () => ( tooltipContent={} /> ); + +function getTooltipContent(assetType: InventoryItemType) { + switch (assetType) { + case 'host': + return ; + default: + return ; + } +} diff --git a/x-pack/plugins/observability_solution/infra/public/components/asset_details/translations.ts b/x-pack/plugins/observability_solution/infra/public/components/asset_details/translations.ts index 1313e655f6b6f..0f313dc445d69 100644 --- a/x-pack/plugins/observability_solution/infra/public/components/asset_details/translations.ts +++ b/x-pack/plugins/observability_solution/infra/public/components/asset_details/translations.ts @@ -31,3 +31,18 @@ export const HOST_METRIC_GROUP_TITLES = { defaultMessage: 'Kubernetes', }), }; + +export const CONTAINER_METRIC_GROUP_TITLES = { + cpu: i18n.translate('xpack.infra.metricsGroup.containerCpu', { + defaultMessage: 'CPU', + }), + memory: i18n.translate('xpack.infra.metricsGroup.containerMemory', { + defaultMessage: 'Memory', + }), + network: i18n.translate('xpack.infra.metricsGroup.containerNetwork', { + defaultMessage: 'Network', + }), + disk: i18n.translate('xpack.infra.metricsGroup.containerDisk', { + defaultMessage: 'Disk', + }), +}; diff --git a/x-pack/plugins/observability_solution/infra/public/components/asset_details/types.ts b/x-pack/plugins/observability_solution/infra/public/components/asset_details/types.ts index 0299bd3582c8b..e51a7b53bda7d 100644 --- a/x-pack/plugins/observability_solution/infra/public/components/asset_details/types.ts +++ b/x-pack/plugins/observability_solution/infra/public/components/asset_details/types.ts @@ -98,5 +98,7 @@ export interface RouteState { export type DataViewOrigin = 'logs' | 'metrics'; export enum INTEGRATION_NAME { - kubernetes = 'kubernetes', + kubernetesNode = 'kubernetesNode', + kubernetesContainer = 'kubernetesContainer', + docker = 'docker', } diff --git a/x-pack/plugins/observability_solution/infra/public/components/lens/metric_explanation/container_metrics_explanation_content.tsx b/x-pack/plugins/observability_solution/infra/public/components/lens/metric_explanation/container_metrics_explanation_content.tsx new file mode 100644 index 0000000000000..637db2e6388ef --- /dev/null +++ b/x-pack/plugins/observability_solution/infra/public/components/lens/metric_explanation/container_metrics_explanation_content.tsx @@ -0,0 +1,54 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { EuiText, EuiLink } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n-react'; +import { + CONTAINER_METRICS_DOC_HREF, + HOST_METRICS_DOTTED_LINES_DOC_HREF, +} from '../../../common/visualizations/constants'; + +export const ContainerMetricsExplanationContent = () => { + return ( + +

+ +

+

+ + + {i18n.translate('xpack.infra.containerViewPage.tooltip.whatAreTheseMetricsLink', { + defaultMessage: 'What are these metrics?', + })} + + +

+

+ + + {i18n.translate('xpack.infra.hostsViewPage.tooltip.whyAmISeeingDottedLines', { + defaultMessage: 'Why am I seeing dotted lines?', + })} + + +

+
+ ); +}; diff --git a/x-pack/plugins/observability_solution/infra/public/pages/link_to/redirect_to_inventory.tsx b/x-pack/plugins/observability_solution/infra/public/pages/link_to/redirect_to_inventory.tsx index 37ddbacf72488..c6d0bed51ed9c 100644 --- a/x-pack/plugins/observability_solution/infra/public/pages/link_to/redirect_to_inventory.tsx +++ b/x-pack/plugins/observability_solution/infra/public/pages/link_to/redirect_to_inventory.tsx @@ -5,43 +5,32 @@ * 2.0. */ -import React from 'react'; +import React, { useEffect } from 'react'; import { parse } from 'query-string'; -import { Redirect, RouteComponentProps } from 'react-router-dom'; - -// FIXME what would be the right way to build this query string? -const QUERY_STRING_TEMPLATE = - "?waffleFilter=(expression:'',kind:kuery)&waffleTime=(currentTime:{timestamp},isAutoReloading:!f)&waffleOptions=(accountId:'',autoBounds:!t,boundsOverride:(max:1,min:0),customMetrics:!({customMetric}),customOptions:!(),groupBy:!(),legend:(palette:cool,reverseColors:!f,steps:10),metric:{metric},nodeType:{nodeType},region:'',sort:(by:name,direction:desc),timelineOpen:!f,view:map)"; +import { RouteComponentProps } from 'react-router-dom'; +import type { SerializableRecord } from '@kbn/utility-types'; +import { INVENTORY_LOCATOR_ID } from '@kbn/observability-shared-plugin/public'; +import { useKibanaContextForPlugin } from '../../hooks/use_kibana'; export const RedirectToInventory: React.FC = ({ location }) => { - const parsedQueryString = parseQueryString(location.search); - - const inventoryQueryString = QUERY_STRING_TEMPLATE.replace( - /{(\w+)}/g, - (_, key) => parsedQueryString[key] || '' - ); - - return ; + const { + services: { share }, + } = useKibanaContextForPlugin(); + const baseLocator = share.url.locators.get(INVENTORY_LOCATOR_ID); + + useEffect(() => { + const parsedQueryString = parse(location.search || '', { sort: false }); + const currentTime = parseFloat((parsedQueryString.timestamp ?? '') as string); + + baseLocator?.navigate({ + ...parsedQueryString, + waffleTime: { + currentTime, + isAutoReloading: false, + }, + state: location.state as SerializableRecord, + }); + }, [baseLocator, location.search, location.state]); + + return null; }; - -function parseQueryString(search: string): Record { - if (search.length === 0) { - return {}; - } - - const obj = parse(search.substring(1)); - - // Force all values into string. If they are empty don't create the keys - for (const key in obj) { - if (Object.hasOwnProperty.call(obj, key)) { - if (!obj[key]) { - delete obj[key]; - } - if (Array.isArray(obj.key)) { - obj[key] = obj[key]![0]; - } - } - } - - return obj as Record; -} diff --git a/x-pack/plugins/observability_solution/infra/public/pages/metrics/hosts/components/host_details_flyout/flyout_wrapper.tsx b/x-pack/plugins/observability_solution/infra/public/pages/metrics/hosts/components/host_details_flyout/flyout_wrapper.tsx index 6177518b3a8fe..d7e36d950d4ca 100644 --- a/x-pack/plugins/observability_solution/infra/public/pages/metrics/hosts/components/host_details_flyout/flyout_wrapper.tsx +++ b/x-pack/plugins/observability_solution/infra/public/pages/metrics/hosts/components/host_details_flyout/flyout_wrapper.tsx @@ -10,7 +10,7 @@ import { useSourceContext } from '../../../../../containers/metrics_source'; import { useUnifiedSearchContext } from '../../hooks/use_unified_search'; import type { HostNodeRow } from '../../hooks/use_hosts_table'; import { AssetDetails } from '../../../../../components/asset_details'; -import { commonFlyoutTabs } from '../../../../../common/asset_details_config/asset_details_tabs'; +import { hostDetailsTabs } from '../../../../../common/asset_details_config/asset_details_tabs'; export interface Props { node: HostNodeRow; @@ -32,7 +32,7 @@ export const FlyoutWrapper = ({ node: { name }, closeFlyout }: Props) => { showActionsColumn: true, }, }} - tabs={commonFlyoutTabs} + tabs={hostDetailsTabs} links={['nodeDetails']} renderMode={{ mode: 'flyout', diff --git a/x-pack/plugins/observability_solution/infra/public/pages/metrics/hosts/components/kpis/kpi_charts.tsx b/x-pack/plugins/observability_solution/infra/public/pages/metrics/hosts/components/kpis/kpi_charts.tsx index 9c43581df8a9d..9fd8f40fa08c7 100644 --- a/x-pack/plugins/observability_solution/infra/public/pages/metrics/hosts/components/kpis/kpi_charts.tsx +++ b/x-pack/plugins/observability_solution/infra/public/pages/metrics/hosts/components/kpis/kpi_charts.tsx @@ -7,7 +7,7 @@ import React from 'react'; import { i18n } from '@kbn/i18n'; import { HostKpiCharts } from '../../../../../components/asset_details'; -import { buildCombinedHostsFilter } from '../../../../../utils/filters/build'; +import { buildCombinedAssetFilter } from '../../../../../utils/filters/build'; import { useUnifiedSearchContext } from '../../hooks/use_unified_search'; import { useHostsViewContext } from '../../hooks/use_hosts_view'; import { useHostCountContext } from '../../hooks/use_host_count'; @@ -26,7 +26,7 @@ export const KpiCharts = () => { const filters = shouldUseSearchCriteria ? [...searchCriteria.filters, ...(searchCriteria.panelFilters ?? [])] : [ - buildCombinedHostsFilter({ + buildCombinedAssetFilter({ field: 'host.name', values: hostNodes.map((p) => p.name), dataView, diff --git a/x-pack/plugins/observability_solution/infra/public/pages/metrics/hosts/components/tabs/logs/logs_tab_content.tsx b/x-pack/plugins/observability_solution/infra/public/pages/metrics/hosts/components/tabs/logs/logs_tab_content.tsx index c977c1fde37a9..27344ccd1f108 100644 --- a/x-pack/plugins/observability_solution/infra/public/pages/metrics/hosts/components/tabs/logs/logs_tab_content.tsx +++ b/x-pack/plugins/observability_solution/infra/public/pages/metrics/hosts/components/tabs/logs/logs_tab_content.tsx @@ -16,7 +16,7 @@ import { useUnifiedSearchContext } from '../../../hooks/use_unified_search'; import { useLogsSearchUrlState } from '../../../hooks/use_logs_search_url_state'; import { LogsLinkToStream } from './logs_link_to_stream'; import { LogsSearchBar } from './logs_search_bar'; -import { buildCombinedHostsFilter } from '../../../../../../utils/filters/build'; +import { buildCombinedAssetFilter } from '../../../../../../utils/filters/build'; import { useLogViewReference } from '../../../../../../hooks/use_log_view_reference'; export const LogsTabContent = () => { @@ -27,7 +27,7 @@ export const LogsTabContent = () => { const hostsFilterQuery = useMemo( () => - buildCombinedHostsFilter({ + buildCombinedAssetFilter({ field: 'host.name', values: hostNodes.map((p) => p.name), }), diff --git a/x-pack/plugins/observability_solution/infra/public/pages/metrics/hosts/components/tabs/metrics/chart.tsx b/x-pack/plugins/observability_solution/infra/public/pages/metrics/hosts/components/tabs/metrics/chart.tsx index 88846924c15e2..79a4b610dd7a0 100644 --- a/x-pack/plugins/observability_solution/infra/public/pages/metrics/hosts/components/tabs/metrics/chart.tsx +++ b/x-pack/plugins/observability_solution/infra/public/pages/metrics/hosts/components/tabs/metrics/chart.tsx @@ -11,7 +11,7 @@ import { METRIC_CHART_HEIGHT } from '../../../../../../common/visualizations/con import { LensChart } from '../../../../../../components/lens'; import { useUnifiedSearchContext } from '../../../hooks/use_unified_search'; import { useHostsViewContext } from '../../../hooks/use_hosts_view'; -import { buildCombinedHostsFilter } from '../../../../../../utils/filters/build'; +import { buildCombinedAssetFilter } from '../../../../../../utils/filters/build'; import { useHostsTableContext } from '../../../hooks/use_hosts_table'; import { useAfterLoadedState } from '../../../hooks/use_after_loaded_state'; @@ -40,7 +40,7 @@ export const Chart = ({ id, ...chartProps }: ChartProps) => { return shouldUseSearchCriteria ? [...searchCriteria.filters, ...(searchCriteria.panelFilters ?? [])] : [ - buildCombinedHostsFilter({ + buildCombinedAssetFilter({ field: 'host.name', values: currentPage.map((p) => p.name), dataView, diff --git a/x-pack/plugins/observability_solution/infra/public/pages/metrics/hosts/hooks/use_hosts_table.tsx b/x-pack/plugins/observability_solution/infra/public/pages/metrics/hosts/hooks/use_hosts_table.tsx index e5bd61b9b1e19..0cf70b4b4182b 100644 --- a/x-pack/plugins/observability_solution/infra/public/pages/metrics/hosts/hooks/use_hosts_table.tsx +++ b/x-pack/plugins/observability_solution/infra/public/pages/metrics/hosts/hooks/use_hosts_table.tsx @@ -29,7 +29,7 @@ import { useMetricsDataViewContext } from './use_metrics_data_view'; import { ColumnHeader } from '../components/table/column_header'; import { TABLE_COLUMN_LABEL, TABLE_CONTENT_LABEL } from '../translations'; import { METRICS_TOOLTIP } from '../../../../common/visualizations'; -import { buildCombinedHostsFilter } from '../../../../utils/filters/build'; +import { buildCombinedAssetFilter } from '../../../../utils/filters/build'; /** * Columns and items types @@ -151,7 +151,7 @@ export const useHostsTable = () => { return []; } const selectedHostNames = selectedItems.map(({ name }) => name); - const newFilter = buildCombinedHostsFilter({ + const newFilter = buildCombinedAssetFilter({ field: 'host.name', values: selectedHostNames, dataView, diff --git a/x-pack/plugins/observability_solution/infra/public/pages/metrics/inventory_view/components/waffle/asset_details_flyout.tsx b/x-pack/plugins/observability_solution/infra/public/pages/metrics/inventory_view/components/waffle/asset_details_flyout.tsx index 31b16ca70f26d..af50a277b593b 100644 --- a/x-pack/plugins/observability_solution/infra/public/pages/metrics/inventory_view/components/waffle/asset_details_flyout.tsx +++ b/x-pack/plugins/observability_solution/infra/public/pages/metrics/inventory_view/components/waffle/asset_details_flyout.tsx @@ -12,7 +12,7 @@ import type { InfraWaffleMapOptions } from '../../../../../lib/lib'; import { ContentTabIds } from '../../../../../components/asset_details/types'; import { AssetDetails } from '../../../../../components/asset_details'; import { useSourceContext } from '../../../../../containers/metrics_source'; -import { commonFlyoutTabs } from '../../../../../common/asset_details_config/asset_details_tabs'; +import { hostDetailsTabs } from '../../../../../common/asset_details_config/asset_details_tabs'; interface Props { assetName: string; @@ -25,7 +25,7 @@ interface Props { } const flyoutTabs = [ - ...commonFlyoutTabs, + ...hostDetailsTabs, { id: ContentTabIds.LINK_TO_APM, name: i18n.translate('xpack.infra.assetDetails.tabs.linkToApm', { diff --git a/x-pack/plugins/observability_solution/infra/public/pages/metrics/inventory_view/components/waffle/waffle_inventory_switcher.tsx b/x-pack/plugins/observability_solution/infra/public/pages/metrics/inventory_view/components/waffle/waffle_inventory_switcher.tsx index 29b3978573377..d7b88870b6450 100644 --- a/x-pack/plugins/observability_solution/infra/public/pages/metrics/inventory_view/components/waffle/waffle_inventory_switcher.tsx +++ b/x-pack/plugins/observability_solution/infra/public/pages/metrics/inventory_view/components/waffle/waffle_inventory_switcher.tsx @@ -57,7 +57,7 @@ export const WaffleInventorySwitcher: React.FC = () => { ); const goToHost = useCallback(() => goToNodeType('host'), [goToNodeType]); const goToK8 = useCallback(() => goToNodeType('pod'), [goToNodeType]); - const goToDocker = useCallback(() => goToNodeType('container'), [goToNodeType]); + const goToContainer = useCallback(() => goToNodeType('container'), [goToNodeType]); const goToAwsEC2 = useCallback(() => goToNodeType('awsEC2'), [goToNodeType]); const goToAwsS3 = useCallback(() => goToNodeType('awsS3'), [goToNodeType]); const goToAwsRDS = useCallback(() => goToNodeType('awsRDS'), [goToNodeType]); @@ -79,9 +79,9 @@ export const WaffleInventorySwitcher: React.FC = () => { onClick: goToK8, }, { - 'data-test-subj': 'goToDocker', + 'data-test-subj': 'goToContainer', name: getDisplayNameForType('container'), - onClick: goToDocker, + onClick: goToContainer, }, { name: 'AWS', @@ -117,7 +117,7 @@ export const WaffleInventorySwitcher: React.FC = () => { ], }, ] as EuiContextMenuPanelDescriptor[], - [goToAwsEC2, goToAwsRDS, goToAwsS3, goToAwsSQS, goToDocker, goToHost, goToK8] + [goToAwsEC2, goToAwsRDS, goToAwsS3, goToAwsSQS, goToContainer, goToHost, goToK8] ); const selectedText = useMemo(() => { diff --git a/x-pack/plugins/observability_solution/infra/public/pages/metrics/metric_detail/asset_detail_page.tsx b/x-pack/plugins/observability_solution/infra/public/pages/metrics/metric_detail/asset_detail_page.tsx index f0733ca291b37..31cbe1baae31b 100644 --- a/x-pack/plugins/observability_solution/infra/public/pages/metrics/metric_detail/asset_detail_page.tsx +++ b/x-pack/plugins/observability_solution/infra/public/pages/metrics/metric_detail/asset_detail_page.tsx @@ -14,7 +14,7 @@ import { SourceLoadingPage } from '../../../components/source_loading_page'; import { useSourceContext } from '../../../containers/metrics_source'; import { AssetDetails } from '../../../components/asset_details'; import { MetricsPageTemplate } from '../page_template'; -import { commonFlyoutTabs } from '../../../common/asset_details_config/asset_details_tabs'; +import { getAssetDetailsTabs } from '../../../common/asset_details_config/asset_details_tabs'; export const AssetDetailPage = () => { const { isLoading, loadSourceFailureMessage, loadSource, source } = useSourceContext(); @@ -43,7 +43,7 @@ export const AssetDetailPage = () => { { params: { type: nodeType }, } = useRouteMatch<{ type: InventoryItemType; node: string }>(); + const isContainerAssetViewEnabled = useUiSetting(enableInfrastructureContainerAssetView); + + const showContainerAssetDetailPage = nodeType === 'container' && isContainerAssetViewEnabled; return ( - {nodeType === 'host' ? ( + {nodeType === 'host' || showContainerAssetDetailPage ? ( ) : ( diff --git a/x-pack/plugins/observability_solution/infra/public/pages/metrics/settings/features_configuration_panel.tsx b/x-pack/plugins/observability_solution/infra/public/pages/metrics/settings/features_configuration_panel.tsx index a8f8569014c7d..f0d7e9d487277 100644 --- a/x-pack/plugins/observability_solution/infra/public/pages/metrics/settings/features_configuration_panel.tsx +++ b/x-pack/plugins/observability_solution/infra/public/pages/metrics/settings/features_configuration_panel.tsx @@ -13,6 +13,7 @@ import React from 'react'; import { enableInfrastructureHostsView, enableInfrastructureProfilingIntegration, + enableInfrastructureContainerAssetView, } from '@kbn/observability-plugin/common'; import { useEditableSettings } from '@kbn/observability-shared-plugin/public'; import { withSuspense } from '@kbn/shared-ux-utility'; @@ -83,6 +84,12 @@ export function FeaturesConfigurationPanel({ unsavedChange={unsavedChanges[enableInfrastructureProfilingIntegration]} /> )} + ); diff --git a/x-pack/plugins/observability_solution/infra/public/pages/metrics/settings/source_configuration_settings.tsx b/x-pack/plugins/observability_solution/infra/public/pages/metrics/settings/source_configuration_settings.tsx index cbfe09df53b2d..004a0b9e9bb55 100644 --- a/x-pack/plugins/observability_solution/infra/public/pages/metrics/settings/source_configuration_settings.tsx +++ b/x-pack/plugins/observability_solution/infra/public/pages/metrics/settings/source_configuration_settings.tsx @@ -14,6 +14,7 @@ import { useEditableSettings, } from '@kbn/observability-shared-plugin/public'; import { + enableInfrastructureContainerAssetView, enableInfrastructureHostsView, enableInfrastructureProfilingIntegration, } from '@kbn/observability-plugin/common'; @@ -90,6 +91,7 @@ export const SourceConfigurationSettings = ({ const infraUiSettings = useEditableSettings([ enableInfrastructureHostsView, enableInfrastructureProfilingIntegration, + enableInfrastructureContainerAssetView, ]); const resetAllUnsavedChanges = useCallback(() => { diff --git a/x-pack/plugins/observability_solution/infra/public/utils/filters/build.ts b/x-pack/plugins/observability_solution/infra/public/utils/filters/build.ts index b52804390bc98..0aee9c00814c6 100644 --- a/x-pack/plugins/observability_solution/infra/public/utils/filters/build.ts +++ b/x-pack/plugins/observability_solution/infra/public/utils/filters/build.ts @@ -16,7 +16,7 @@ import type { DataView } from '@kbn/data-views-plugin/common'; import { findInventoryFields } from '@kbn/metrics-data-access-plugin/common'; import type { InfraCustomDashboardAssetType } from '../../../common/custom_dashboards'; -export const buildCombinedHostsFilter = ({ +export const buildCombinedAssetFilter = ({ field, values, dataView, diff --git a/x-pack/plugins/observability_solution/infra/public/utils/filters/create_alerts_es_query.ts b/x-pack/plugins/observability_solution/infra/public/utils/filters/create_alerts_es_query.ts index a0922e794df71..e80ac2cdf9ac0 100644 --- a/x-pack/plugins/observability_solution/infra/public/utils/filters/create_alerts_es_query.ts +++ b/x-pack/plugins/observability_solution/infra/public/utils/filters/create_alerts_es_query.ts @@ -9,7 +9,7 @@ import { ALERT_TIME_RANGE } from '@kbn/rule-data-utils'; import { BoolQuery, buildEsQuery, Filter, type TimeRange } from '@kbn/es-query'; import type { AlertStatus } from '@kbn/observability-plugin/common/typings'; import { findInventoryFields } from '@kbn/metrics-data-access-plugin/common'; -import { buildCombinedHostsFilter } from './build'; +import { buildCombinedAssetFilter } from './build'; import { ALERT_STATUS_QUERY } from '../../components/shared/alerts/constants'; export interface AlertsEsQuery { @@ -28,7 +28,7 @@ export const createAlertsEsQuery = ({ const alertStatusFilter = createAlertStatusFilter(status); const dateFilter = createDateFilter(dateRange); - const hostsFilter = buildCombinedHostsFilter({ + const hostsFilter = buildCombinedAssetFilter({ field: findInventoryFields('host').id, values: assetIds, }); diff --git a/x-pack/plugins/observability_solution/logs_explorer/public/customizations/custom_cell_renderer.tsx b/x-pack/plugins/observability_solution/logs_explorer/public/customizations/custom_cell_renderer.tsx deleted file mode 100644 index 765d910ede954..0000000000000 --- a/x-pack/plugins/observability_solution/logs_explorer/public/customizations/custom_cell_renderer.tsx +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import type { DataPublicPluginStart } from '@kbn/data-plugin/public'; -import { CONTENT_FIELD, RESOURCE_FIELD } from '../../common/constants'; -import { renderCell } from '../components/virtual_columns/cell_renderer'; - -export const createCustomCellRenderer = ({ data }: { data: DataPublicPluginStart }) => { - return { - [CONTENT_FIELD]: renderCell(CONTENT_FIELD, { data }), - [RESOURCE_FIELD]: renderCell(RESOURCE_FIELD, { data }), - }; -}; diff --git a/x-pack/plugins/observability_solution/logs_explorer/public/customizations/custom_column.tsx b/x-pack/plugins/observability_solution/logs_explorer/public/customizations/custom_column.tsx deleted file mode 100644 index 1e5cba9693eb5..0000000000000 --- a/x-pack/plugins/observability_solution/logs_explorer/public/customizations/custom_column.tsx +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { CONTENT_FIELD, RESOURCE_FIELD } from '../../common/constants'; -import { renderColumn } from '../components/virtual_columns/column'; - -export const createCustomGridColumnsConfiguration = () => ({ - [CONTENT_FIELD]: renderColumn(CONTENT_FIELD), - [RESOURCE_FIELD]: renderColumn(RESOURCE_FIELD), -}); diff --git a/x-pack/plugins/observability_solution/logs_explorer/public/customizations/custom_control_column.tsx b/x-pack/plugins/observability_solution/logs_explorer/public/customizations/custom_control_column.tsx index 7fe8c0ae7aa7f..9bb71a3055a68 100644 --- a/x-pack/plugins/observability_solution/logs_explorer/public/customizations/custom_control_column.tsx +++ b/x-pack/plugins/observability_solution/logs_explorer/public/customizations/custom_control_column.tsx @@ -15,6 +15,7 @@ import { import { EuiButtonIcon, EuiDataGridCellValueElementProps, EuiToolTip } from '@elastic/eui'; import type { DataTableRecord } from '@kbn/discover-utils/src/types'; import { useActor } from '@xstate/react'; +import { LogDocument } from '@kbn/discover-utils/src'; import { LogsExplorerControllerStateService } from '../state_machines/logs_explorer_controller'; import { degradedDocButtonLabelWhenNotPresent, @@ -24,7 +25,6 @@ import { } from '../components/common/translations'; import * as constants from '../../common/constants'; import { getStacktraceFields } from '../utils/get_stack_trace'; -import { LogDocument } from '../../common/document'; import { ActionsColumnTooltip } from '../components/virtual_columns/column_tooltips/actions_column_tooltip'; const ConnectedDegradedDocs = ({ diff --git a/x-pack/plugins/observability_solution/logs_explorer/public/customizations/custom_field_list.ts b/x-pack/plugins/observability_solution/logs_explorer/public/customizations/custom_field_list.ts deleted file mode 100644 index 93a414c39367e..0000000000000 --- a/x-pack/plugins/observability_solution/logs_explorer/public/customizations/custom_field_list.ts +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { DataViewField } from '@kbn/data-views-plugin/common'; -import * as constants from '../../common/constants'; - -export const smartFields = [ - new DataViewField({ - name: constants.RESOURCE_FIELD, - type: 'smart_field', - searchable: false, - aggregatable: false, - }), - new DataViewField({ - name: constants.CONTENT_FIELD, - type: 'smart_field', - searchable: false, - aggregatable: false, - }), -]; diff --git a/x-pack/plugins/observability_solution/logs_explorer/public/customizations/logs_explorer_profile.tsx b/x-pack/plugins/observability_solution/logs_explorer/public/customizations/logs_explorer_profile.tsx index 7fcc9d6a1cb9d..42a3838311a98 100644 --- a/x-pack/plugins/observability_solution/logs_explorer/public/customizations/logs_explorer_profile.tsx +++ b/x-pack/plugins/observability_solution/logs_explorer/public/customizations/logs_explorer_profile.tsx @@ -15,9 +15,6 @@ import type { LogsExplorerController } from '../controller'; import type { LogsExplorerStartDeps } from '../types'; import { useKibanaContextForPluginProvider } from '../utils/use_kibana'; import { createCustomSearchBar } from './custom_search_bar'; -import { createCustomCellRenderer } from './custom_cell_renderer'; -import { createCustomGridColumnsConfiguration } from './custom_column'; -import { smartFields } from './custom_field_list'; import { createCustomUnifiedHistogram } from './custom_unified_histogram'; const LazyCustomDataSourceFilters = dynamic(() => import('./custom_data_source_filters')); @@ -83,8 +80,7 @@ export const createLogsExplorerProfileCustomizations = customizations.set({ id: 'data_table', - customCellRenderer: createCustomCellRenderer({ data }), - customGridColumnsConfiguration: createCustomGridColumnsConfiguration(), + logsEnabled: true, customControlColumnsConfiguration: await import('./custom_control_column').then((module) => module.createCustomControlColumnsConfiguration(service) ), @@ -92,9 +88,7 @@ export const createLogsExplorerProfileCustomizations = customizations.set({ id: 'field_list', - additionalFieldGroups: { - smartFields, - }, + logsFieldsEnabled: true, }); // Fix bug where filtering on histogram does not work diff --git a/x-pack/plugins/observability_solution/logs_explorer/public/utils/get_stack_trace.ts b/x-pack/plugins/observability_solution/logs_explorer/public/utils/get_stack_trace.ts index 58eb44a7744c9..ac264af2732aa 100644 --- a/x-pack/plugins/observability_solution/logs_explorer/public/utils/get_stack_trace.ts +++ b/x-pack/plugins/observability_solution/logs_explorer/public/utils/get_stack_trace.ts @@ -5,9 +5,8 @@ * 2.0. */ -import { LogDocument, StackTraceFields } from '../../common/document'; +import { getFieldFromDoc, LogDocument, StackTraceFields } from '@kbn/discover-utils/src'; import * as constants from '../../common/constants'; -import { getFieldFromDoc } from './get_field_from_flattened_doc'; export const getStacktraceFields = (doc: LogDocument): StackTraceFields => { const errorStackTrace = getFieldFromDoc(doc, constants.ERROR_STACK_TRACE); diff --git a/x-pack/plugins/observability_solution/logs_explorer/tsconfig.json b/x-pack/plugins/observability_solution/logs_explorer/tsconfig.json index cb04be5ccf518..b30605fd567fd 100644 --- a/x-pack/plugins/observability_solution/logs_explorer/tsconfig.json +++ b/x-pack/plugins/observability_solution/logs_explorer/tsconfig.json @@ -19,13 +19,11 @@ "@kbn/core-ui-settings-browser", "@kbn/core-ui-settings-common", "@kbn/core", - "@kbn/custom-icons", "@kbn/data-plugin", "@kbn/data-views-plugin", "@kbn/deeplinks-observability", "@kbn/discover-plugin", "@kbn/discover-utils", - "@kbn/elastic-agent-utils", "@kbn/embeddable-plugin", "@kbn/es-query", "@kbn/field-formats-plugin", diff --git a/x-pack/plugins/observability_solution/metrics_data_access/common/inventory_models/container/index.ts b/x-pack/plugins/observability_solution/metrics_data_access/common/inventory_models/container/index.ts index e50d020d1d4f7..a113c6fd1802c 100644 --- a/x-pack/plugins/observability_solution/metrics_data_access/common/inventory_models/container/index.ts +++ b/x-pack/plugins/observability_solution/metrics_data_access/common/inventory_models/container/index.ts @@ -11,7 +11,7 @@ import { InventoryModel } from '../types'; export { containerSnapshotMetricTypes } from './metrics'; -export const container: InventoryModel = { +export const container: InventoryModel = { id: 'container', displayName: i18n.translate('xpack.metricsData.inventoryModel.container.displayName', { defaultMessage: 'Docker Containers', diff --git a/x-pack/plugins/observability_solution/metrics_data_access/common/inventory_models/container/metrics/charts/cpu.ts b/x-pack/plugins/observability_solution/metrics_data_access/common/inventory_models/container/metrics/charts/cpu.ts new file mode 100644 index 0000000000000..36c5ddaf91acd --- /dev/null +++ b/x-pack/plugins/observability_solution/metrics_data_access/common/inventory_models/container/metrics/charts/cpu.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 { + CPU_USAGE_LABEL, + DEFAULT_XY_FITTING_FUNCTION, + DEFAULT_XY_HIDDEN_AXIS_TITLE, + DEFAULT_XY_HIDDEN_LEGEND, + DEFAULT_XY_YBOUNDS, +} from '../../../shared/charts/constants'; +import { LensConfigWithId } from '../../../types'; +import { formulas } from '../formulas'; + +const dockerContainerCpuUsageXY: LensConfigWithId = { + id: 'cpuUsage', + chartType: 'xy', + title: CPU_USAGE_LABEL, + layers: [ + { + seriesType: 'line', + type: 'series', + xAxis: '@timestamp', + yAxis: [formulas.dockerContainerCpuUsage], + }, + ], + ...DEFAULT_XY_FITTING_FUNCTION, + ...DEFAULT_XY_HIDDEN_LEGEND, + ...DEFAULT_XY_HIDDEN_AXIS_TITLE, + ...DEFAULT_XY_YBOUNDS, +}; + +const k8sContainerCpuUsageXY: LensConfigWithId = { + id: 'k8sCpuUsage', + chartType: 'xy', + title: CPU_USAGE_LABEL, + layers: [ + { + seriesType: 'line', + type: 'series', + xAxis: '@timestamp', + yAxis: [formulas.k8sContainerCpuUsage], + }, + ], + ...DEFAULT_XY_FITTING_FUNCTION, + ...DEFAULT_XY_HIDDEN_LEGEND, + ...DEFAULT_XY_HIDDEN_AXIS_TITLE, + ...DEFAULT_XY_YBOUNDS, +}; + +const dockerContainerCpuUsageMetric: LensConfigWithId = { + id: 'cpuUsage', + chartType: 'metric', + title: CPU_USAGE_LABEL, + trendLine: true, + ...formulas.dockerContainerCpuUsage, +}; + +const containerK8sCpuUsageMetric: LensConfigWithId = { + id: 'k8sCpuUsage', + chartType: 'metric', + title: CPU_USAGE_LABEL, + trendLine: true, + ...formulas.k8sContainerCpuUsage, +}; + +export const cpu = { + xy: { + dockerContainerCpuUsage: dockerContainerCpuUsageXY, + k8sContainerCpuUsage: k8sContainerCpuUsageXY, + }, + metric: { + dockerContainerCpuUsage: dockerContainerCpuUsageMetric, + k8sContainerCpuUsage: containerK8sCpuUsageMetric, + }, +} as const; diff --git a/x-pack/plugins/observability_solution/metrics_data_access/common/inventory_models/container/metrics/charts/index.ts b/x-pack/plugins/observability_solution/metrics_data_access/common/inventory_models/container/metrics/charts/index.ts new file mode 100644 index 0000000000000..6a83e00c9c5c8 --- /dev/null +++ b/x-pack/plugins/observability_solution/metrics_data_access/common/inventory_models/container/metrics/charts/index.ts @@ -0,0 +1,16 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { cpu } from './cpu'; +import { memory } from './memory'; + +export const charts = { + cpu, + memory, +} as const; + +export type ContainerCharts = typeof charts; diff --git a/x-pack/plugins/observability_solution/metrics_data_access/common/inventory_models/container/metrics/charts/memory.ts b/x-pack/plugins/observability_solution/metrics_data_access/common/inventory_models/container/metrics/charts/memory.ts new file mode 100644 index 0000000000000..45ce080d7f448 --- /dev/null +++ b/x-pack/plugins/observability_solution/metrics_data_access/common/inventory_models/container/metrics/charts/memory.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 { LensConfigWithId } from '../../../types'; +import { + DEFAULT_XY_FITTING_FUNCTION, + DEFAULT_XY_HIDDEN_AXIS_TITLE, + DEFAULT_XY_HIDDEN_LEGEND, + DEFAULT_XY_YBOUNDS, + MEMORY_USAGE_LABEL, +} from '../../../shared/charts/constants'; +import { formulas } from '../formulas'; + +const dockerContainerMemoryUsageXY: LensConfigWithId = { + id: 'memoryUsage', + chartType: 'xy', + title: MEMORY_USAGE_LABEL, + layers: [ + { + seriesType: 'line', + type: 'series', + xAxis: '@timestamp', + yAxis: [formulas.dockerContainerMemoryUsage], + }, + ], + ...DEFAULT_XY_FITTING_FUNCTION, + ...DEFAULT_XY_HIDDEN_LEGEND, + ...DEFAULT_XY_YBOUNDS, + ...DEFAULT_XY_HIDDEN_AXIS_TITLE, +}; + +const k8sContainerMemoryUsageXY: LensConfigWithId = { + id: 'k8sMemoryUsage', + chartType: 'xy', + title: MEMORY_USAGE_LABEL, + layers: [ + { + seriesType: 'line', + type: 'series', + xAxis: '@timestamp', + yAxis: [formulas.k8sContainerMemoryUsage], + }, + ], + ...DEFAULT_XY_FITTING_FUNCTION, + ...DEFAULT_XY_HIDDEN_LEGEND, + ...DEFAULT_XY_YBOUNDS, + ...DEFAULT_XY_HIDDEN_AXIS_TITLE, +}; + +const dockerContainerMemoryUsageMetric: LensConfigWithId = { + id: 'memoryUsage', + chartType: 'metric', + title: MEMORY_USAGE_LABEL, + trendLine: true, + ...formulas.dockerContainerMemoryUsage, +}; + +const k8sContainerMemoryUsageMetric: LensConfigWithId = { + id: 'k8sMemoryUsage', + chartType: 'metric', + title: MEMORY_USAGE_LABEL, + trendLine: true, + ...formulas.k8sContainerMemoryUsage, +}; + +export const memory = { + xy: { + dockerContainerMemoryUsage: dockerContainerMemoryUsageXY, + k8sContainerMemoryUsage: k8sContainerMemoryUsageXY, + }, + metric: { + dockerContainerMemoryUsage: dockerContainerMemoryUsageMetric, + k8sContainerMemoryUsage: k8sContainerMemoryUsageMetric, + }, +}; diff --git a/x-pack/plugins/observability_solution/metrics_data_access/common/inventory_models/container/metrics/formulas/cpu.ts b/x-pack/plugins/observability_solution/metrics_data_access/common/inventory_models/container/metrics/formulas/cpu.ts new file mode 100644 index 0000000000000..283f139d31a7a --- /dev/null +++ b/x-pack/plugins/observability_solution/metrics_data_access/common/inventory_models/container/metrics/formulas/cpu.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 type { LensBaseLayer } from '@kbn/lens-embeddable-utils/config_builder'; +import { CPU_USAGE_LABEL } from '../../../shared/charts/constants'; + +export const dockerContainerCpuUsage: LensBaseLayer = { + label: CPU_USAGE_LABEL, + value: 'average(docker.cpu.total.pct)', + format: 'percent', + decimals: 1, +}; + +export const k8sContainerCpuUsage: LensBaseLayer = { + label: CPU_USAGE_LABEL, + value: 'average(kubernetes.container.cpu.usage.limit.pct)', + format: 'percent', + decimals: 1, +}; diff --git a/x-pack/plugins/observability_solution/metrics_data_access/common/inventory_models/container/metrics/formulas/index.ts b/x-pack/plugins/observability_solution/metrics_data_access/common/inventory_models/container/metrics/formulas/index.ts new file mode 100644 index 0000000000000..2f5e4f7975f7a --- /dev/null +++ b/x-pack/plugins/observability_solution/metrics_data_access/common/inventory_models/container/metrics/formulas/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 { dockerContainerCpuUsage, k8sContainerCpuUsage } from './cpu'; +import { dockerContainerMemoryUsage, k8sContainerMemoryUsage } from './memory'; + +export const formulas = { + dockerContainerCpuUsage, + dockerContainerMemoryUsage, + k8sContainerCpuUsage, + k8sContainerMemoryUsage, +} as const; + +export type ContainerFormulas = typeof formulas; diff --git a/x-pack/plugins/observability_solution/metrics_data_access/common/inventory_models/container/metrics/formulas/memory.ts b/x-pack/plugins/observability_solution/metrics_data_access/common/inventory_models/container/metrics/formulas/memory.ts new file mode 100644 index 0000000000000..827f06e4fdb0d --- /dev/null +++ b/x-pack/plugins/observability_solution/metrics_data_access/common/inventory_models/container/metrics/formulas/memory.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 { LensBaseLayer } from '@kbn/lens-embeddable-utils/config_builder'; +import { MEMORY_USAGE_LABEL } from '../../../shared/charts/constants'; + +export const dockerContainerMemoryUsage: LensBaseLayer = { + label: MEMORY_USAGE_LABEL, + value: 'average(docker.memory.usage.pct)', + format: 'percent', + decimals: 1, +}; + +export const k8sContainerMemoryUsage: LensBaseLayer = { + label: MEMORY_USAGE_LABEL, + value: 'average(kubernetes.container.memory.usage.limit.pct)', + format: 'percent', + decimals: 1, +}; diff --git a/x-pack/plugins/observability_solution/metrics_data_access/common/inventory_models/container/metrics/index.ts b/x-pack/plugins/observability_solution/metrics_data_access/common/inventory_models/container/metrics/index.ts index eb0678890ad3a..faa848192fd46 100644 --- a/x-pack/plugins/observability_solution/metrics_data_access/common/inventory_models/container/metrics/index.ts +++ b/x-pack/plugins/observability_solution/metrics_data_access/common/inventory_models/container/metrics/index.ts @@ -5,22 +5,23 @@ * 2.0. */ -import { InventoryMetrics } from '../../types'; +import { InventoryMetricsWithCharts } from '../../types'; import { cpu } from './snapshot/cpu'; import { memory } from './snapshot/memory'; import { rx } from './snapshot/rx'; import { tx } from './snapshot/tx'; - -import { containerOverview } from './tsvb/container_overview'; -import { containerCpuUsage } from './tsvb/container_cpu_usage'; import { containerCpuKernel } from './tsvb/container_cpu_kernel'; +import { containerCpuUsage } from './tsvb/container_cpu_usage'; import { containerDiskIOOps } from './tsvb/container_diskio_ops'; import { containerDiskIOBytes } from './tsvb/container_disk_io_bytes'; -import { containerMemory } from './tsvb/container_memory'; -import { containerNetworkTraffic } from './tsvb/container_network_traffic'; -import { containerK8sOverview } from './tsvb/container_k8s_overview'; import { containerK8sCpuUsage } from './tsvb/container_k8s_cpu_usage'; import { containerK8sMemoryUsage } from './tsvb/container_k8s_memory_usage'; +import { containerK8sOverview } from './tsvb/container_k8s_overview'; +import { containerMemory } from './tsvb/container_memory'; +import { containerNetworkTraffic } from './tsvb/container_network_traffic'; +import { containerOverview } from './tsvb/container_overview'; +import type { ContainerFormulas } from './formulas'; +import { ContainerCharts } from './charts'; const containerSnapshotMetrics = { cpu, memory, rx, tx }; @@ -28,7 +29,7 @@ export const containerSnapshotMetricTypes = Object.keys(containerSnapshotMetrics keyof typeof containerSnapshotMetrics >; -export const metrics: InventoryMetrics = { +export const metrics: InventoryMetricsWithCharts = { tsvb: { containerOverview, containerCpuUsage, @@ -42,6 +43,8 @@ export const metrics: InventoryMetrics = { containerK8sMemoryUsage, }, snapshot: containerSnapshotMetrics, + getFormulas: async () => await import('./formulas').then(({ formulas }) => formulas), + getCharts: async () => await import('./charts').then(({ charts }) => charts), defaultSnapshot: 'cpu', defaultTimeRangeInSeconds: 3600, // 1 hour }; diff --git a/x-pack/plugins/observability_solution/metrics_data_access/common/inventory_models/host/metrics/charts/cpu.ts b/x-pack/plugins/observability_solution/metrics_data_access/common/inventory_models/host/metrics/charts/cpu.ts index a12637d6c9a2c..bfa9c1f9dec60 100644 --- a/x-pack/plugins/observability_solution/metrics_data_access/common/inventory_models/host/metrics/charts/cpu.ts +++ b/x-pack/plugins/observability_solution/metrics_data_access/common/inventory_models/host/metrics/charts/cpu.ts @@ -5,8 +5,9 @@ * 2.0. */ -import { i18n } from '@kbn/i18n'; import { + CPU_USAGE_LABEL, + LOAD_LABEL, DEFAULT_XY_FITTING_FUNCTION, DEFAULT_XY_HIDDEN_AXIS_TITLE, DEFAULT_XY_HIDDEN_LEGEND, @@ -19,9 +20,7 @@ import { formulas } from '../formulas'; const cpuUsageBreakdown: LensConfigWithId = { id: 'cpuUsageBreakdown', chartType: 'xy', - title: i18n.translate('xpack.metricsData.assetDetails.metricsCharts.cpuUsage', { - defaultMessage: 'CPU Usage', - }), + title: CPU_USAGE_LABEL, layers: [ { seriesType: 'area', @@ -47,9 +46,7 @@ const cpuUsageBreakdown: LensConfigWithId = { const loadBreakdown: LensConfigWithId = { id: 'loadBreakdown', chartType: 'xy', - title: i18n.translate('xpack.metricsData.assetDetails.metricsCharts.load', { - defaultMessage: 'Load', - }), + title: LOAD_LABEL, layers: [ { seriesType: 'area', diff --git a/x-pack/plugins/observability_solution/metrics_data_access/common/inventory_models/host/metrics/charts/disk.ts b/x-pack/plugins/observability_solution/metrics_data_access/common/inventory_models/host/metrics/charts/disk.ts index a73c9f274b40b..112de73066518 100644 --- a/x-pack/plugins/observability_solution/metrics_data_access/common/inventory_models/host/metrics/charts/disk.ts +++ b/x-pack/plugins/observability_solution/metrics_data_access/common/inventory_models/host/metrics/charts/disk.ts @@ -14,14 +14,15 @@ import { DEFAULT_XY_HIDDEN_LEGEND, DEFAULT_XY_LEGEND, DEFAULT_XY_YBOUNDS, + DISK_IOPS_LABEL, + DISK_THROUGHPUT_LABEL, + DISK_USAGE_BY_MOUNT_POINT_LABEL, } from '../../../shared/charts/constants'; const diskIOReadWrite: LensConfigWithId = { id: 'diskIOReadWrite', chartType: 'xy', - title: i18n.translate('xpack.metricsData.assetDetails.metricsCharts.diskIOPS', { - defaultMessage: 'Disk IOPS', - }), + title: DISK_IOPS_LABEL, layers: [ { seriesType: 'area', @@ -51,9 +52,7 @@ const diskIOReadWrite: LensConfigWithId = { const diskUsageByMountPoint: LensConfigWithId = { id: 'diskUsageByMountPoint', chartType: 'xy', - title: i18n.translate('xpack.metricsData.assetDetails.metricsCharts.diskUsageByMountingPoint', { - defaultMessage: 'Disk Usage by Mount Point', - }), + title: DISK_USAGE_BY_MOUNT_POINT_LABEL, layers: [ { seriesType: 'area', @@ -86,9 +85,7 @@ const diskUsageByMountPoint: LensConfigWithId = { const diskThroughputReadWrite: LensConfigWithId = { id: 'diskThroughputReadWrite', chartType: 'xy', - title: i18n.translate('xpack.metricsData.assetDetails.metricsCharts.diskThroughput', { - defaultMessage: 'Disk Throughput', - }), + title: DISK_THROUGHPUT_LABEL, layers: [ { seriesType: 'area', diff --git a/x-pack/plugins/observability_solution/metrics_data_access/common/inventory_models/host/metrics/charts/memory.ts b/x-pack/plugins/observability_solution/metrics_data_access/common/inventory_models/host/metrics/charts/memory.ts index 91e5fcff000e8..8113848810fe8 100644 --- a/x-pack/plugins/observability_solution/metrics_data_access/common/inventory_models/host/metrics/charts/memory.ts +++ b/x-pack/plugins/observability_solution/metrics_data_access/common/inventory_models/host/metrics/charts/memory.ts @@ -14,14 +14,13 @@ import { DEFAULT_XY_HIDDEN_LEGEND, DEFAULT_XY_LEGEND, DEFAULT_XY_YBOUNDS, + MEMORY_USAGE_LABEL, } from '../../../shared/charts/constants'; const memoryUsageBreakdown: LensConfigWithId = { id: 'memoryUsageBreakdown', chartType: 'xy', - title: i18n.translate('xpack.metricsData.assetDetails.metricsCharts.memoryUsage', { - defaultMessage: 'Memory Usage', - }), + title: MEMORY_USAGE_LABEL, layers: [ { seriesType: 'area', diff --git a/x-pack/plugins/observability_solution/metrics_data_access/common/inventory_models/host/metrics/charts/network.ts b/x-pack/plugins/observability_solution/metrics_data_access/common/inventory_models/host/metrics/charts/network.ts index e9a4ea0351779..d94dd48db8370 100644 --- a/x-pack/plugins/observability_solution/metrics_data_access/common/inventory_models/host/metrics/charts/network.ts +++ b/x-pack/plugins/observability_solution/metrics_data_access/common/inventory_models/host/metrics/charts/network.ts @@ -13,14 +13,13 @@ import { DEFAULT_XY_HIDDEN_AXIS_TITLE, DEFAULT_XY_HIDDEN_LEGEND, DEFAULT_XY_LEGEND, + NETWORK_LABEL, } from '../../../shared/charts/constants'; const rxTx: LensConfigWithId = { id: 'rxTx', chartType: 'xy', - title: i18n.translate('xpack.metricsData.assetDetails.metricsCharts.network', { - defaultMessage: 'Network', - }), + title: NETWORK_LABEL, layers: [ { seriesType: 'area', diff --git a/x-pack/plugins/observability_solution/metrics_data_access/common/inventory_models/host/metrics/formulas/cpu.ts b/x-pack/plugins/observability_solution/metrics_data_access/common/inventory_models/host/metrics/formulas/cpu.ts index 10256dcb1cbf5..fa75dc071666c 100644 --- a/x-pack/plugins/observability_solution/metrics_data_access/common/inventory_models/host/metrics/formulas/cpu.ts +++ b/x-pack/plugins/observability_solution/metrics_data_access/common/inventory_models/host/metrics/formulas/cpu.ts @@ -7,6 +7,13 @@ import { i18n } from '@kbn/i18n'; import type { LensBaseLayer } from '@kbn/lens-embeddable-utils/config_builder'; +import { + CPU_USAGE_LABEL, + LOAD_15M_LABEL, + LOAD_1M_LABEL, + LOAD_5M_LABEL, + NORMALIZED_LOAD_LABEL, +} from '../../../shared/charts/constants'; export const cpuUsageIowait: LensBaseLayer = { label: i18n.translate('xpack.metricsData.assetDetails.formulas.cpuUsage.iowaitLabel', { @@ -72,45 +79,35 @@ export const cpuUsageUser: LensBaseLayer = { }; export const cpuUsage: LensBaseLayer = { - label: i18n.translate('xpack.metricsData.assetDetails.formulas.cpuUsage', { - defaultMessage: 'CPU Usage', - }), + label: CPU_USAGE_LABEL, value: '(average(system.cpu.user.pct) + average(system.cpu.system.pct)) / max(system.cpu.cores)', format: 'percent', decimals: 0, }; export const load1m: LensBaseLayer = { - label: i18n.translate('xpack.metricsData.assetDetails.formulas.load1m', { - defaultMessage: 'Load (1m)', - }), + label: LOAD_1M_LABEL, value: 'average(system.load.1)', format: 'number', decimals: 1, }; export const load5m: LensBaseLayer = { - label: i18n.translate('xpack.metricsData.assetDetails.formulas.load5m', { - defaultMessage: 'Load (5m)', - }), + label: LOAD_5M_LABEL, value: 'average(system.load.5)', format: 'number', decimals: 1, }; export const load15m: LensBaseLayer = { - label: i18n.translate('xpack.metricsData.assetDetails.formulas.load15m', { - defaultMessage: 'Load (15m)', - }), + label: LOAD_15M_LABEL, value: 'average(system.load.15)', format: 'number', decimals: 1, }; export const normalizedLoad1m: LensBaseLayer = { - label: i18n.translate('xpack.metricsData.assetDetails.formulas.normalizedLoad1m', { - defaultMessage: 'Normalized Load', - }), + label: NORMALIZED_LOAD_LABEL, value: 'average(system.load.1) / max(system.load.cores)', format: 'percent', decimals: 0, diff --git a/x-pack/plugins/observability_solution/metrics_data_access/common/inventory_models/host/metrics/formulas/disk.ts b/x-pack/plugins/observability_solution/metrics_data_access/common/inventory_models/host/metrics/formulas/disk.ts index 6d6f644e19ace..9eae6986a6065 100644 --- a/x-pack/plugins/observability_solution/metrics_data_access/common/inventory_models/host/metrics/formulas/disk.ts +++ b/x-pack/plugins/observability_solution/metrics_data_access/common/inventory_models/host/metrics/formulas/disk.ts @@ -5,13 +5,20 @@ * 2.0. */ -import { i18n } from '@kbn/i18n'; import type { LensBaseLayer } from '@kbn/lens-embeddable-utils/config_builder'; +import { + DISK_READ_IOPS_LABEL, + DISK_READ_THROUGHPUT_LABEL, + DISK_SPACE_AVAILABILITY_LABEL, + DISK_SPACE_AVAILABLE_LABEL, + DISK_USAGE_AVERAGE_LABEL, + DISK_USAGE_LABEL, + DISK_WRITE_IOPS_LABEL, + DISK_WRITE_THROUGHPUT_LABEL, +} from '../../../shared/charts/constants'; export const diskIORead: LensBaseLayer = { - label: i18n.translate('xpack.metricsData.assetDetails.formulas.diskIORead', { - defaultMessage: 'Disk Read IOPS', - }), + label: DISK_READ_IOPS_LABEL, value: "counter_rate(max(system.diskio.read.count), kql='system.diskio.read.count: *')", format: 'number', decimals: 0, @@ -19,9 +26,7 @@ export const diskIORead: LensBaseLayer = { }; export const diskReadThroughput: LensBaseLayer = { - label: i18n.translate('xpack.metricsData.assetDetails.formulas.diskReadThroughput', { - defaultMessage: 'Disk Read Throughput', - }), + label: DISK_READ_THROUGHPUT_LABEL, value: "counter_rate(max(system.diskio.read.bytes), kql='system.diskio.read.bytes: *')", format: 'bytes', decimals: 1, @@ -29,45 +34,35 @@ export const diskReadThroughput: LensBaseLayer = { }; export const diskSpaceAvailable: LensBaseLayer = { - label: i18n.translate('xpack.metricsData.assetDetails.formulas.diskSpaceAvailable', { - defaultMessage: 'Disk Space Available', - }), + label: DISK_SPACE_AVAILABLE_LABEL, value: 'average(system.filesystem.free)', format: 'bytes', decimals: 0, }; export const diskSpaceAvailability: LensBaseLayer = { - label: i18n.translate('xpack.metricsData.assetDetails.formulas.diskSpaceAvailability', { - defaultMessage: 'Disk Space Availability', - }), + label: DISK_SPACE_AVAILABILITY_LABEL, value: '1 - average(system.filesystem.used.pct)', format: 'percent', decimals: 0, }; export const diskUsage: LensBaseLayer = { - label: i18n.translate('xpack.metricsData.assetDetails.formulas.diskUsage', { - defaultMessage: 'Disk Usage', - }), + label: DISK_USAGE_LABEL, value: 'max(system.filesystem.used.pct)', format: 'percent', decimals: 0, }; export const diskUsageAverage: LensBaseLayer = { - label: i18n.translate('xpack.metricsData.assetDetails.formulas.diskUsageAverage', { - defaultMessage: 'Disk Usage Average', - }), + label: DISK_USAGE_AVERAGE_LABEL, value: 'average(system.filesystem.used.pct)', format: 'percent', decimals: 0, }; export const diskIOWrite: LensBaseLayer = { - label: i18n.translate('xpack.metricsData.assetDetails.formulas.diskIOWrite', { - defaultMessage: 'Disk Write IOPS', - }), + label: DISK_WRITE_IOPS_LABEL, value: "counter_rate(max(system.diskio.write.count), kql='system.diskio.write.count: *')", format: 'number', decimals: 0, @@ -75,9 +70,7 @@ export const diskIOWrite: LensBaseLayer = { }; export const diskWriteThroughput: LensBaseLayer = { - label: i18n.translate('xpack.metricsData.assetDetails.formulas.diskWriteThroughput', { - defaultMessage: 'Disk Write Throughput', - }), + label: DISK_WRITE_THROUGHPUT_LABEL, value: "counter_rate(max(system.diskio.write.bytes), kql='system.diskio.write.bytes: *')", format: 'bytes', decimals: 1, diff --git a/x-pack/plugins/observability_solution/metrics_data_access/common/inventory_models/host/metrics/formulas/memory.ts b/x-pack/plugins/observability_solution/metrics_data_access/common/inventory_models/host/metrics/formulas/memory.ts index 7b3afb4894e12..9c1d285d1b879 100644 --- a/x-pack/plugins/observability_solution/metrics_data_access/common/inventory_models/host/metrics/formulas/memory.ts +++ b/x-pack/plugins/observability_solution/metrics_data_access/common/inventory_models/host/metrics/formulas/memory.ts @@ -7,6 +7,7 @@ import { i18n } from '@kbn/i18n'; import type { LensBaseLayer } from '@kbn/lens-embeddable-utils/config_builder'; +import { MEMORY_FREE_LABEL, MEMORY_USAGE_LABEL } from '../../../shared/charts/constants'; export const memoryCache: LensBaseLayer = { label: i18n.translate('xpack.metricsData.assetDetails.formulas.metric.label.cache', { @@ -18,9 +19,7 @@ export const memoryCache: LensBaseLayer = { }; export const memoryFree: LensBaseLayer = { - label: i18n.translate('xpack.metricsData.assetDetails.formulas.memoryFree', { - defaultMessage: 'Memory Free', - }), + label: MEMORY_FREE_LABEL, value: 'max(system.memory.total) - average(system.memory.actual.used.bytes)', format: 'bytes', decimals: 1, @@ -36,9 +35,7 @@ export const memoryFreeExcludingCache: LensBaseLayer = { }; export const memoryUsage: LensBaseLayer = { - label: i18n.translate('xpack.metricsData.assetDetails.formulas.memoryUsage', { - defaultMessage: 'Memory Usage', - }), + label: MEMORY_USAGE_LABEL, value: 'average(system.memory.actual.used.pct)', format: 'percent', diff --git a/x-pack/plugins/observability_solution/metrics_data_access/common/inventory_models/shared/charts/constants.ts b/x-pack/plugins/observability_solution/metrics_data_access/common/inventory_models/shared/charts/constants.ts index c835b1239769b..6d6d22c116f43 100644 --- a/x-pack/plugins/observability_solution/metrics_data_access/common/inventory_models/shared/charts/constants.ts +++ b/x-pack/plugins/observability_solution/metrics_data_access/common/inventory_models/shared/charts/constants.ts @@ -5,6 +5,7 @@ * 2.0. */ +import { i18n } from '@kbn/i18n'; import type { LensXYConfigBase } from '@kbn/lens-embeddable-utils/config_builder'; export const DEFAULT_XY_FITTING_FUNCTION: Pick = { @@ -38,3 +39,134 @@ export const DEFAULT_XY_HIDDEN_AXIS_TITLE: Pick = { }), schema: schema.boolean(), }, + [enableInfrastructureContainerAssetView]: { + category: [observabilityFeatureId], + name: i18n.translate('xpack.observability.enableInfrastructureContainerAssetView', { + defaultMessage: 'Container view', + }), + value: false, + description: i18n.translate( + 'xpack.observability.enableInfrastructureContainerAssetViewDescription', + { + defaultMessage: 'Enable the Container asset view in the Infrastructure app.', + } + ), + schema: schema.boolean(), + }, [enableInfrastructureProfilingIntegration]: { category: [observabilityFeatureId], name: i18n.translate('xpack.observability.enableInfrastructureProfilingIntegration', { diff --git a/x-pack/plugins/observability_solution/observability_ai_assistant/server/functions/get_dataset_info/get_relevant_field_names.ts b/x-pack/plugins/observability_solution/observability_ai_assistant/server/functions/get_dataset_info/get_relevant_field_names.ts index 543641098836f..2f32731ac3f2d 100644 --- a/x-pack/plugins/observability_solution/observability_ai_assistant/server/functions/get_dataset_info/get_relevant_field_names.ts +++ b/x-pack/plugins/observability_solution/observability_ai_assistant/server/functions/get_dataset_info/get_relevant_field_names.ts @@ -36,9 +36,25 @@ export async function getRelevantFieldNames({ }): Promise<{ fields: string[] }> { const dataViewsService = await dataViews.dataViewsServiceFactory(savedObjectsClient, esClient); + const hasAnyHitsResponse = await esClient.search({ + index, + _source: false, + track_total_hits: 1, + terminate_after: 1, + }); + + const hitCount = + typeof hasAnyHitsResponse.hits.total === 'number' + ? hasAnyHitsResponse.hits.total + : hasAnyHitsResponse.hits.total?.value ?? 0; + + // all fields are empty in this case, so get them all + const includeEmptyFields = hitCount === 0; + const fields = await dataViewsService.getFieldsForWildcard({ pattern: castArray(index).join(','), allowNoIndex: true, + includeEmptyFields, indexFilter: start && end ? { @@ -74,7 +90,7 @@ export async function getRelevantFieldNames({ const relevantFields = await Promise.all( chunk(fieldNames, 500).map(async (fieldsInChunk) => { const chunkResponse$ = ( - await chat('get_relevent_dataset_names', { + await chat('get_relevant_dataset_names', { signal, messages: [ { @@ -88,7 +104,8 @@ export async function getRelevantFieldNames({ CIRCUMSTANCES include fields not mentioned in this list.`, }, }, - ...messages.slice(1), + // remove the system message and the function request + ...messages.slice(1, -1), { '@timestamp': new Date().toISOString(), message: { diff --git a/x-pack/plugins/observability_solution/observability_ai_assistant/server/functions/get_dataset_info/index.ts b/x-pack/plugins/observability_solution/observability_ai_assistant/server/functions/get_dataset_info/index.ts index e5b4e21195003..f016ae126ca53 100644 --- a/x-pack/plugins/observability_solution/observability_ai_assistant/server/functions/get_dataset_info/index.ts +++ b/x-pack/plugins/observability_solution/observability_ai_assistant/server/functions/get_dataset_info/index.ts @@ -26,7 +26,6 @@ export function registerGetDatasetInfoFunction({ 'This function allows the assistant to get information about available indices and their fields.', parameters: { type: 'object', - additionalProperties: false, properties: { index: { type: 'string', @@ -90,7 +89,7 @@ export function registerGetDatasetInfoFunction({ return { content: { indices: [index], - fields: relevantFieldNames, + fields: relevantFieldNames.fields, }, }; } diff --git a/x-pack/plugins/observability_solution/observability_ai_assistant_app/public/components/nav_control/index.tsx b/x-pack/plugins/observability_solution/observability_ai_assistant_app/public/components/nav_control/index.tsx index cf8a5cd9dffe7..8757b9f8235bf 100644 --- a/x-pack/plugins/observability_solution/observability_ai_assistant_app/public/components/nav_control/index.tsx +++ b/x-pack/plugins/observability_solution/observability_ai_assistant_app/public/components/nav_control/index.tsx @@ -6,7 +6,7 @@ */ import React, { useEffect, useRef, useState } from 'react'; import { AssistantAvatar, useAbortableAsync } from '@kbn/observability-ai-assistant-plugin/public'; -import { EuiButton, EuiLoadingSpinner } from '@elastic/eui'; +import { EuiButton, EuiLoadingSpinner, EuiToolTip } from '@elastic/eui'; import { css } from '@emotion/react'; import { v4 } from 'uuid'; import useObservable from 'react-use/lib/useObservable'; @@ -91,31 +91,46 @@ export function NavControl({}: {}) { } `; + useEffect(() => { + const keyboardListener = (event: KeyboardEvent) => { + if (event.ctrlKey && event.code === 'Semicolon') { + service.conversations.openNewConversation({ + messages: [], + }); + } + }; + + window.addEventListener('keypress', keyboardListener); + + return () => { + window.removeEventListener('keypress', keyboardListener); + }; + }, [service.conversations]); + if (!isVisible) { return null; } return ( <> - { - service.conversations.openNewConversation({ - messages: [], - }); - }} - color="primary" - size="s" - fullWidth={false} - minWidth={0} - > - {chatService.loading ? : } - + + { + service.conversations.openNewConversation({ + messages: [], + }); + }} + color="primary" + size="s" + fullWidth={false} + minWidth={0} + > + {chatService.loading ? : } + + {chatService.value ? ( ); } + +const buttonLabel = i18n.translate( + 'xpack.observabilityAiAssistant.navControl.openTheAIAssistantPopoverLabel', + { defaultMessage: 'Open the AI Assistant' } +); diff --git a/x-pack/plugins/observability_solution/observability_ai_assistant_app/server/functions/alerts.ts b/x-pack/plugins/observability_solution/observability_ai_assistant_app/server/functions/alerts.ts index 7b62ca4f5a6d2..03c61843e702a 100644 --- a/x-pack/plugins/observability_solution/observability_ai_assistant_app/server/functions/alerts.ts +++ b/x-pack/plugins/observability_solution/observability_ai_assistant_app/server/functions/alerts.ts @@ -6,18 +6,49 @@ */ import datemath from '@elastic/datemath'; +import { KibanaRequest } from '@kbn/core/server'; import { fromKueryExpression, toElasticsearchQuery } from '@kbn/es-query'; +import { FunctionVisibility } from '@kbn/observability-ai-assistant-plugin/common'; +import { getRelevantFieldNames } from '@kbn/observability-ai-assistant-plugin/server/functions/get_dataset_info/get_relevant_field_names'; import { ParsedTechnicalFields } from '@kbn/rule-registry-plugin/common'; import { ALERT_STATUS, ALERT_STATUS_ACTIVE, } from '@kbn/rule-registry-plugin/common/technical_rule_data_field_names'; import { omit } from 'lodash'; -import { KibanaRequest } from '@kbn/core/server'; import { FunctionRegistrationParameters } from '.'; -const OMITTED_ALERT_FIELDS = [ +const defaultFields = [ + '@timestamp', + 'kibana.alert.start', + 'kibana.alert.end', + 'kibana.alert.flapping', + 'kibana.alert.group', + 'kibana.alert.instance.id', + 'kibana.alert.reason', + 'kibana.alert.rule.category', + 'kibana.alert.rule.name', + 'kibana.alert.rule.tags', + 'kibana.alert.start', + 'kibana.alert.status', + 'kibana.alert.time_range.gte', + 'kibana.alert.time_range.lte', + 'kibana.alert.workflow_status', 'tags', + // infra + 'host.name', + 'container.id', + 'kubernetes.pod.name', + // APM + 'processor.event', + 'service.environment', + 'service.name', + 'service.node.name', + 'transaction.type', + 'transaction.name', +]; + +const OMITTED_ALERT_FIELDS = [ 'event.action', 'event.kind', 'kibana.alert.rule.execution.uuid', @@ -46,22 +77,75 @@ export function registerAlertsFunction({ }: FunctionRegistrationParameters) { functions.registerFunction( { - name: 'alerts', - description: - 'Get alerts for Observability. Display the response in tabular format if appropriate.', - descriptionForUser: 'Get alerts for Observability', + name: 'get_alerts_dataset_info', + visibility: FunctionVisibility.AssistantOnly, + description: `Use this function to get information about alerts data.`, parameters: { type: 'object', properties: { - featureIds: { - type: 'array', - items: { - type: 'string', - enum: DEFAULT_FEATURE_IDS, - }, + start: { + type: 'string', description: - 'The Observability apps for which to retrieve alerts. By default it will return alerts for all apps.', + 'The start of the current time range, in datemath, like now-24h or an ISO timestamp', }, + end: { + type: 'string', + description: + 'The end of the current time range, in datemath, like now-24h or an ISO timestamp', + }, + }, + } as const, + }, + async ( + { arguments: { start, end }, chat, messages }, + signal + ): Promise<{ + content: { + fields: string[]; + }; + }> => { + const core = await resources.context.core; + + const { fields } = await getRelevantFieldNames({ + index: `.alerts-observability*`, + messages, + esClient: core.elasticsearch.client.asInternalUser, + dataViews: await resources.plugins.dataViews.start(), + savedObjectsClient: core.savedObjects.client, + signal, + chat: ( + operationName, + { messages: nextMessages, functionCall, functions: nextFunctions } + ) => { + return chat(operationName, { + messages: nextMessages, + functionCall, + functions: nextFunctions, + signal, + }); + }, + }); + + return { + content: { + fields: fields.length === 0 ? defaultFields : fields, + }, + }; + } + ); + + functions.registerFunction( + { + name: 'alerts', + description: `Get alerts for Observability. Make sure get_alerts_dataset_info was called before. + Use this to get open (and optionally recovered) alerts for Observability assets, like services, + hosts or containers. + Display the response in tabular format if appropriate. + `, + descriptionForUser: 'Get alerts for Observability', + parameters: { + type: 'object', + properties: { start: { type: 'string', description: 'The start of the time range, in Elasticsearch date math, like `now`.', @@ -72,8 +156,7 @@ export function registerAlertsFunction({ }, kqlFilter: { type: 'string', - description: - 'a KQL query to filter the data by. If no filter should be applied, leave it empty.', + description: `Filter alerts by field:value pairs`, }, includeRecovered: { type: 'boolean', @@ -85,15 +168,7 @@ export function registerAlertsFunction({ } as const, }, async ( - { - arguments: { - start: startAsDatemath, - end: endAsDatemath, - featureIds, - filter, - includeRecovered, - }, - }, + { arguments: { start: startAsDatemath, end: endAsDatemath, filter, includeRecovered } }, signal ) => { const alertsClient = await pluginsStart.ruleRegistry.getRacClientWithRequest( @@ -106,10 +181,7 @@ export function registerAlertsFunction({ const kqlQuery = !filter ? [] : [toElasticsearchQuery(fromKueryExpression(filter))]; const response = await alertsClient.find({ - featureIds: - !!featureIds && !!featureIds.length - ? featureIds - : (DEFAULT_FEATURE_IDS as unknown as string[]), + featureIds: DEFAULT_FEATURE_IDS as unknown as string[], query: { bool: { filter: [ @@ -134,6 +206,7 @@ export function registerAlertsFunction({ ], }, }, + size: 10, }); // trim some fields diff --git a/x-pack/plugins/observability_solution/observability_onboarding/server/routes/logs/route.ts b/x-pack/plugins/observability_solution/observability_onboarding/server/routes/logs/route.ts index c7a411441658e..b46b1508ed21b 100644 --- a/x-pack/plugins/observability_solution/observability_onboarding/server/routes/logs/route.ts +++ b/x-pack/plugins/observability_solution/observability_onboarding/server/routes/logs/route.ts @@ -58,12 +58,12 @@ const installShipperSetupRoute = createObservabilityOnboardingServerRoute({ core.setup.http.basePath.publicBaseUrl ?? // priority given to server.publicBaseUrl plugins.cloud?.setup?.kibanaUrl ?? // then cloud id getFallbackKibanaUrl(coreStart); // falls back to local network binding - const installScriptPath = coreStart.http.staticAssets.getPluginAssetHref( - 'standalone_agent_setup.sh' - ); + const scriptDownloadUrl = new URL( + coreStart.http.staticAssets.getPluginAssetHref('standalone_agent_setup.sh'), + kibanaUrl + ).toString(); - const scriptDownloadUrl = `${kibanaUrl}${installScriptPath}`; - const apiEndpoint = `${kibanaUrl}/internal/observability_onboarding`; + const apiEndpoint = new URL(`${kibanaUrl}/internal/observability_onboarding`).toString(); return { apiEndpoint, diff --git a/x-pack/plugins/observability_solution/observability_shared/public/index.ts b/x-pack/plugins/observability_solution/observability_shared/public/index.ts index 93094c79369a9..a06f086d6588d 100644 --- a/x-pack/plugins/observability_solution/observability_shared/public/index.ts +++ b/x-pack/plugins/observability_solution/observability_shared/public/index.ts @@ -103,6 +103,7 @@ export { export { BottomBarActions } from './components/bottom_bar_actions/bottom_bar_actions'; export { FieldValueSelection, FieldValueSuggestions } from './components'; export { ASSET_DETAILS_FLYOUT_LOCATOR_ID } from './locators/infra/asset_details_flyout_locator'; +export { INVENTORY_LOCATOR_ID } from './locators/infra/inventory_locator'; export { ASSET_DETAILS_LOCATOR_ID, type AssetDetailsLocatorParams, diff --git a/x-pack/plugins/observability_solution/observability_shared/public/locators/infra/inventory_locator.ts b/x-pack/plugins/observability_solution/observability_shared/public/locators/infra/inventory_locator.ts new file mode 100644 index 0000000000000..ca6e997468b5b --- /dev/null +++ b/x-pack/plugins/observability_solution/observability_shared/public/locators/infra/inventory_locator.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 { SerializableRecord } from '@kbn/utility-types'; +import rison from '@kbn/rison'; +import { LocatorDefinition, LocatorPublic } from '@kbn/share-plugin/common'; +import querystring from 'querystring'; + +export type InventoryLocator = LocatorPublic; + +export interface InventoryLocatorParams extends SerializableRecord { + inventoryViewId?: string; + waffleFilter?: { + expression: string; + kind: string; + }; + waffleTime?: { + currentTime: number; + isAutoReloading: boolean; + }; + waffleOptions?: { + accountId: string; + autoBounds: boolean; + boundsOverride: { + max: number; + min: number; + }; + }; + customMetrics?: string; // encoded value + customOptions?: string; // encoded value + groupBy?: { field: string }; + legend?: { + palette: string; + reverseColors: boolean; + steps: number; + }; + metric: string; // encoded value + nodeType: string; + region?: string; + sort: { + by: string; + direction: 'desc' | 'async'; + }; + timelineOpen: boolean; + view: 'map' | 'table'; + state?: SerializableRecord; +} + +export const INVENTORY_LOCATOR_ID = 'INVENTORY_LOCATOR'; + +export class InventoryLocatorDefinition implements LocatorDefinition { + public readonly id = INVENTORY_LOCATOR_ID; + + public readonly getLocation = async (params: InventoryLocatorParams) => { + const paramsWithDefaults = { + waffleFilter: rison.encodeUnknown(params.waffleFilter ?? { kind: 'kuery', expression: '' }), + waffleTime: rison.encodeUnknown( + params.waffleTime ?? { + currentTime: new Date().getTime(), + isAutoReloading: false, + } + ), + waffleOptions: rison.encodeUnknown( + params.waffleOptions ?? { + accountId: '', + autoBounds: true, + boundsOverride: { max: 1, min: 0 }, + } + ), + customMetrics: params.customMetrics, + customOptions: params.customOptions, + groupBy: rison.encodeUnknown(params.groupBy ?? {}), + legend: rison.encodeUnknown( + params.legend ?? { palette: 'cool', reverseColors: false, steps: 10 } + ), + metric: params.metric, + nodeType: rison.encodeUnknown(params.nodeType), + region: rison.encodeUnknown(params.region ?? ''), + sort: rison.encodeUnknown(params.sort ?? { by: 'name', direction: 'desc' }), + timelineOpen: rison.encodeUnknown(params.timelineOpen ?? false), + view: rison.encodeUnknown(params.view ?? 'map'), + }; + + const queryStringParams = querystring.stringify(paramsWithDefaults); + return { + app: 'metrics', + path: `/inventory?${queryStringParams}`, + state: params.state ? params.state : {}, + }; + }; +} diff --git a/x-pack/plugins/observability_solution/observability_shared/public/locators/infra/locators.test.ts b/x-pack/plugins/observability_solution/observability_shared/public/locators/infra/locators.test.ts index ff02eff6dc76f..c7b5e16625e03 100644 --- a/x-pack/plugins/observability_solution/observability_shared/public/locators/infra/locators.test.ts +++ b/x-pack/plugins/observability_solution/observability_shared/public/locators/infra/locators.test.ts @@ -9,6 +9,8 @@ import rison from '@kbn/rison'; import { AssetDetailsLocatorDefinition } from './asset_details_locator'; import { AssetDetailsFlyoutLocatorDefinition } from './asset_details_flyout_locator'; import { HostsLocatorDefinition } from './hosts_locator'; +import { InventoryLocatorDefinition } from './inventory_locator'; +import querystring from 'querystring'; const setupAssetDetailsLocator = async () => { const assetDetailsLocator = new AssetDetailsLocatorDefinition(); @@ -28,6 +30,14 @@ const setupHostsLocator = async () => { }; }; +const setupInventoryLocator = async () => { + const inventoryLocator = new InventoryLocatorDefinition(); + + return { + inventoryLocator, + }; +}; + describe('Infra Locators', () => { describe('Asset Details Locator', () => { const params = { @@ -162,4 +172,59 @@ describe('Infra Locators', () => { expect(Object.keys(state)).toHaveLength(0); }); }); + + describe('Inventory Locator', () => { + const params = { + waffleFilter: { kind: 'kuery', expression: '' }, + waffleTime: { + currentTime: 1715688477985, + isAutoReloading: false, + }, + waffleOptions: { + accountId: '', + autoBounds: true, + boundsOverride: { max: 1, min: 0 }, + }, + customMetrics: undefined, + customOptions: undefined, + groupBy: { field: 'cloud.provider' }, + legend: { palette: 'cool', reverseColors: false, steps: 10 }, + metric: '(type:cpu)', + nodeType: 'host', + region: '', + sort: { by: 'name', direction: 'desc' as const }, + timelineOpen: false, + view: 'map' as const, + }; + + const expected = Object.keys(params).reduce((acc: Record, key) => { + acc[key] = + key === 'metric' || key === 'customOptions' || key === 'customMetrics' + ? params[key] + : rison.encodeUnknown(params[key as keyof typeof params]); + return acc; + }, {}); + + const queryStringParams = querystring.stringify(expected); + + it('should create a link to Inventory with no state', async () => { + const { inventoryLocator } = await setupInventoryLocator(); + const { app, path, state } = await inventoryLocator.getLocation(params); + + expect(app).toBe('metrics'); + expect(path).toBe(`/inventory?${queryStringParams}`); + expect(state).toBeDefined(); + expect(Object.keys(state)).toHaveLength(0); + }); + + it('should return correct structured url', async () => { + const { inventoryLocator } = await setupInventoryLocator(); + const { app, path, state } = await inventoryLocator.getLocation(params); + + expect(app).toBe('metrics'); + expect(path).toBe(`/inventory?${queryStringParams}`); + expect(state).toBeDefined(); + expect(Object.keys(state)).toHaveLength(0); + }); + }); }); diff --git a/x-pack/plugins/observability_solution/observability_shared/public/plugin.ts b/x-pack/plugins/observability_solution/observability_shared/public/plugin.ts index 625bdbaaeeb3a..97808e516f320 100644 --- a/x-pack/plugins/observability_solution/observability_shared/public/plugin.ts +++ b/x-pack/plugins/observability_solution/observability_shared/public/plugin.ts @@ -27,6 +27,10 @@ import { AssetDetailsLocatorDefinition, } from './locators/infra/asset_details_locator'; import { type HostsLocator, HostsLocatorDefinition } from './locators/infra/hosts_locator'; +import { + type InventoryLocator, + InventoryLocatorDefinition, +} from './locators/infra/inventory_locator'; import { type FlamegraphLocator, FlamegraphLocatorDefinition, @@ -69,6 +73,7 @@ interface ObservabilitySharedLocators { assetDetailsLocator: AssetDetailsLocator; assetDetailsFlyoutLocator: AssetDetailsFlyoutLocator; hostsLocator: HostsLocator; + inventoryLocator: InventoryLocator; }; profiling: { flamegraphLocator: FlamegraphLocator; @@ -137,6 +142,7 @@ export class ObservabilitySharedPlugin implements Plugin { new AssetDetailsFlyoutLocatorDefinition() ), hostsLocator: urlService.locators.create(new HostsLocatorDefinition()), + inventoryLocator: urlService.locators.create(new InventoryLocatorDefinition()), }, profiling: { flamegraphLocator: urlService.locators.create(new FlamegraphLocatorDefinition()), diff --git a/x-pack/plugins/observability_solution/slo/public/components/slo/error_rate_chart/error_rate_chart.tsx b/x-pack/plugins/observability_solution/slo/public/components/slo/error_rate_chart/error_rate_chart.tsx index e42f5a9115bb6..793ebdb89ba6b 100644 --- a/x-pack/plugins/observability_solution/slo/public/components/slo/error_rate_chart/error_rate_chart.tsx +++ b/x-pack/plugins/observability_solution/slo/public/components/slo/error_rate_chart/error_rate_chart.tsx @@ -64,10 +64,8 @@ export function ErrorRateChart({ viewMode={ViewMode.VIEW} onBrushEnd={({ range }) => { onBrushed?.({ - from: range[0], - to: range[1], - fromUtc: moment(range[0]).format(), - toUtc: moment(range[1]).format(), + from: moment(range[0]).toDate(), + to: moment(range[1]).toDate(), }); }} noPadding diff --git a/x-pack/plugins/observability_solution/slo/public/hooks/query_key_factory.ts b/x-pack/plugins/observability_solution/slo/public/hooks/query_key_factory.ts index a493a9cc27066..11f10b624106f 100644 --- a/x-pack/plugins/observability_solution/slo/public/hooks/query_key_factory.ts +++ b/x-pack/plugins/observability_solution/slo/public/hooks/query_key_factory.ts @@ -62,7 +62,7 @@ export const sloKeys = { ) => [...sloKeys.all, 'burnRates', sloId, instanceId, windows] as const, preview: ( indicator: Indicator, - range: { start: number; end: number }, + range: { from: Date; to: Date }, groupings?: Record ) => [...sloKeys.all, 'preview', indicator, range, groupings] as const, burnRateRules: (search: string) => [...sloKeys.all, 'burnRateRules', search], diff --git a/x-pack/plugins/observability_solution/slo/public/hooks/use_fetch_historical_summary.ts b/x-pack/plugins/observability_solution/slo/public/hooks/use_fetch_historical_summary.ts index 95abc489d69de..fc77e0ba40c7a 100644 --- a/x-pack/plugins/observability_solution/slo/public/hooks/use_fetch_historical_summary.ts +++ b/x-pack/plugins/observability_solution/slo/public/hooks/use_fetch_historical_summary.ts @@ -24,8 +24,8 @@ export interface Params { sloList: SLOWithSummaryResponse[]; shouldRefetch?: boolean; range?: { - from: string; - to: string; + from: Date; + to: Date; }; } @@ -45,7 +45,12 @@ export function useFetchHistoricalSummary({ revision: slo.revision, objective: slo.objective, budgetingMethod: slo.budgetingMethod, - range, + range: range + ? { + from: range?.from.toISOString(), + to: range?.to.toISOString(), + } + : undefined, })); const { isInitialLoading, isLoading, isError, isSuccess, isRefetching, data } = useQuery({ diff --git a/x-pack/plugins/observability_solution/slo/public/hooks/use_get_preview_data.ts b/x-pack/plugins/observability_solution/slo/public/hooks/use_get_preview_data.ts index fc032e96cf9cc..316c5300b9f9a 100644 --- a/x-pack/plugins/observability_solution/slo/public/hooks/use_get_preview_data.ts +++ b/x-pack/plugins/observability_solution/slo/public/hooks/use_get_preview_data.ts @@ -35,7 +35,7 @@ export function useGetPreviewData({ groupings?: Record; objective?: Objective; indicator: Indicator; - range: { start: number; end: number }; + range: { from: Date; to: Date }; }): UseGetPreviewData { const { http } = useKibana().services; diff --git a/x-pack/plugins/observability_solution/slo/public/pages/slo_details/components/events_chart_panel.tsx b/x-pack/plugins/observability_solution/slo/public/pages/slo_details/components/events_chart_panel.tsx index 340d6ce465884..bb99a6ce7c2c6 100644 --- a/x-pack/plugins/observability_solution/slo/public/pages/slo_details/components/events_chart_panel.tsx +++ b/x-pack/plugins/observability_solution/slo/public/pages/slo_details/components/events_chart_panel.tsx @@ -37,7 +37,7 @@ import moment from 'moment'; import React, { useRef } from 'react'; import { FormattedMessage } from '@kbn/i18n-react'; import { TimeBounds } from '../types'; -import { getBrushData } from '../../../utils/slo/duration'; +import { getBrushTimeBounds } from '../../../utils/slo/duration'; import { SloTabId } from './slo_details'; import { useGetPreviewData } from '../../../hooks/use_get_preview_data'; import { useKibana } from '../../../utils/kibana_react'; @@ -47,10 +47,7 @@ import { getDiscoverLink } from '../../../utils/slo/get_discover_link'; export interface Props { slo: SLOWithSummaryResponse; - range: { - start: number; - end: number; - }; + range: { from: Date; to: Date }; selectedTabId: SloTabId; onBrushed?: (timeBounds: TimeBounds) => void; } @@ -234,7 +231,7 @@ export function EventsChartPanel({ slo, range, selectedTabId, onBrushed }: Props pointerUpdateTrigger={'x'} locale={i18n.getLocale()} onBrushEnd={(brushArea) => { - onBrushed?.(getBrushData(brushArea)); + onBrushed?.(getBrushTimeBounds(brushArea)); }} /> {annotation} diff --git a/x-pack/plugins/observability_solution/slo/public/pages/slo_details/components/historical_data_charts.tsx b/x-pack/plugins/observability_solution/slo/public/pages/slo_details/components/historical_data_charts.tsx index f2e096195f474..da766b765cac7 100644 --- a/x-pack/plugins/observability_solution/slo/public/pages/slo_details/components/historical_data_charts.tsx +++ b/x-pack/plugins/observability_solution/slo/public/pages/slo_details/components/historical_data_charts.tsx @@ -18,12 +18,10 @@ export interface Props { slo: SLOWithSummaryResponse; isAutoRefreshing: boolean; selectedTabId: SloTabId; - range?: { - from: string; - to: string; - }; + range?: { from: Date; to: Date }; onBrushed?: (timeBounds: TimeBounds) => void; } + export function HistoricalDataCharts({ slo, range, diff --git a/x-pack/plugins/observability_solution/slo/public/pages/slo_details/components/history/slo_details_history.tsx b/x-pack/plugins/observability_solution/slo/public/pages/slo_details/components/history/slo_details_history.tsx index 0e20cb3960fbc..7ecf4d4672775 100644 --- a/x-pack/plugins/observability_solution/slo/public/pages/slo_details/components/history/slo_details_history.tsx +++ b/x-pack/plugins/observability_solution/slo/public/pages/slo_details/components/history/slo_details_history.tsx @@ -4,23 +4,25 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import React, { useCallback, useMemo, useState } from 'react'; -import { SLOWithSummaryResponse } from '@kbn/slo-schema'; import { EuiFlexGroup, EuiFlexItem, + EuiSpacer, EuiSuperDatePicker, - OnTimeChangeProps, OnRefreshProps, - EuiSpacer, + OnTimeChangeProps, } from '@elastic/eui'; import DateMath from '@kbn/datemath'; +import { SLOWithSummaryResponse } from '@kbn/slo-schema'; +import React, { useMemo, useState } from 'react'; +import { BurnRates } from '../../../../components/slo/burn_rate/burn_rates'; import { useKibana } from '../../../../utils/kibana_react'; -import { HistoricalDataCharts } from '../historical_data_charts'; import { useBurnRateOptions } from '../../hooks/use_burn_rate_options'; -import { SloTabId } from '../slo_details'; -import { BurnRates } from '../../../../components/slo/burn_rate/burn_rates'; +import { TimeBounds } from '../../types'; import { EventsChartPanel } from '../events_chart_panel'; +import { HistoricalDataCharts } from '../historical_data_charts'; +import { SloTabId } from '../slo_details'; + export interface Props { slo: SLOWithSummaryResponse; isAutoRefreshing: boolean; @@ -29,10 +31,8 @@ export interface Props { export function SLODetailsHistory({ slo, isAutoRefreshing, selectedTabId }: Props) { const { uiSettings } = useKibana().services; - const { burnRateOptions } = useBurnRateOptions(slo); - - const [start, setStart] = useState('now-30d'); + const [start, setStart] = useState(`now-${slo.timeWindow.duration}`); const [end, setEnd] = useState('now'); const onTimeChange = (val: OnTimeChangeProps) => { @@ -42,19 +42,17 @@ export function SLODetailsHistory({ slo, isAutoRefreshing, selectedTabId }: Prop const onRefresh = (val: OnRefreshProps) => {}; - const absRange = useMemo(() => { + const range = useMemo(() => { return { from: new Date(DateMath.parse(start)!.valueOf()), to: new Date(DateMath.parse(end, { roundUp: true })!.valueOf()), - absoluteFrom: DateMath.parse(start)!.valueOf(), - absoluteTo: DateMath.parse(end, { roundUp: true })!.valueOf(), }; }, [start, end]); - const onBrushed = useCallback(({ fromUtc, toUtc }) => { - setStart(fromUtc); - setEnd(toUtc); - }, []); + const onBrushed = ({ from, to }: TimeBounds) => { + setStart(from.toISOString()); + setEnd(to.toISOString()); + }; return ( <> @@ -94,10 +92,7 @@ export function SLODetailsHistory({ slo, isAutoRefreshing, selectedTabId }: Prop isAutoRefreshing={isAutoRefreshing} burnRateOptions={burnRateOptions} selectedTabId={selectedTabId} - range={{ - from: absRange.from, - to: absRange.to, - }} + range={range} onBrushed={onBrushed} />
@@ -105,19 +100,13 @@ export function SLODetailsHistory({ slo, isAutoRefreshing, selectedTabId }: Prop slo={slo} selectedTabId={selectedTabId} isAutoRefreshing={isAutoRefreshing} - range={{ - from: start, - to: end, - }} + range={range} onBrushed={onBrushed} /> diff --git a/x-pack/plugins/observability_solution/slo/public/pages/slo_details/components/slo_details.tsx b/x-pack/plugins/observability_solution/slo/public/pages/slo_details/components/slo_details.tsx index cb5a1420dc06a..249984fb3ed56 100644 --- a/x-pack/plugins/observability_solution/slo/public/pages/slo_details/components/slo_details.tsx +++ b/x-pack/plugins/observability_solution/slo/public/pages/slo_details/components/slo_details.tsx @@ -7,12 +7,13 @@ import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import { SLOWithSummaryResponse } from '@kbn/slo-schema'; +import moment from 'moment'; import React, { useEffect, useState } from 'react'; -import { HistoricalDataCharts } from './historical_data_charts'; -import { useBurnRateOptions } from '../hooks/use_burn_rate_options'; -import { SLODetailsHistory } from './history/slo_details_history'; import { BurnRates } from '../../../components/slo/burn_rate/burn_rates'; +import { useBurnRateOptions } from '../hooks/use_burn_rate_options'; import { EventsChartPanel } from './events_chart_panel'; +import { HistoricalDataCharts } from './historical_data_charts'; +import { SLODetailsHistory } from './history/slo_details_history'; import { Overview } from './overview/overview'; import { SloDetailsAlerts } from './slo_detail_alerts'; import { SloHealthCallout } from './slo_health_callout'; @@ -22,7 +23,6 @@ export const TAB_ID_URL_PARAM = 'tabId'; export const OVERVIEW_TAB_ID = 'overview'; export const HISTORY_TAB_ID = 'history'; export const ALERTS_TAB_ID = 'alerts'; -const DAY_IN_MILLISECONDS = 24 * 60 * 60 * 1000; export type SloTabId = typeof OVERVIEW_TAB_ID | typeof ALERTS_TAB_ID | typeof HISTORY_TAB_ID; @@ -34,16 +34,16 @@ export interface Props { export function SloDetails({ slo, isAutoRefreshing, selectedTabId }: Props) { const { burnRateOptions } = useBurnRateOptions(slo); - const [range, setRange] = useState({ - start: new Date().getTime() - DAY_IN_MILLISECONDS, - end: new Date().getTime(), + const [range, setRange] = useState<{ from: Date; to: Date }>({ + from: moment().subtract(1, 'day').toDate(), + to: new Date(), }); useEffect(() => { let intervalId: any; if (isAutoRefreshing) { intervalId = setInterval(() => { - setRange({ start: new Date().getTime() - DAY_IN_MILLISECONDS, end: new Date().getTime() }); + setRange({ from: moment().subtract(1, 'day').toDate(), to: new Date() }); }, 60 * 1000); } diff --git a/x-pack/plugins/observability_solution/slo/public/pages/slo_details/components/wide_chart.tsx b/x-pack/plugins/observability_solution/slo/public/pages/slo_details/components/wide_chart.tsx index 5d6d68ae7d892..5ba7effaa9a99 100644 --- a/x-pack/plugins/observability_solution/slo/public/pages/slo_details/components/wide_chart.tsx +++ b/x-pack/plugins/observability_solution/slo/public/pages/slo_details/components/wide_chart.tsx @@ -24,7 +24,7 @@ import moment from 'moment'; import React, { useRef } from 'react'; import { i18n } from '@kbn/i18n'; -import { getBrushData } from '../../../utils/slo/duration'; +import { getBrushTimeBounds } from '../../../utils/slo/duration'; import { TimeBounds } from '../types'; import { useKibana } from '../../../utils/kibana_react'; import { ChartData } from '../../../typings'; @@ -84,7 +84,7 @@ export function WideChart({ chart, data, id, isLoading, state, onBrushed }: Prop pointerUpdateTrigger={'x'} locale={i18n.getLocale()} onBrushEnd={(brushArea) => { - onBrushed?.(getBrushData(brushArea)); + onBrushed?.(getBrushTimeBounds(brushArea)); }} /> row.sliValue && row.sliValue > 1) != null; diff --git a/x-pack/plugins/observability_solution/slo/public/pages/slo_edit/components/synthetics_availability/synthetics_availability_indicator_type_form.tsx b/x-pack/plugins/observability_solution/slo/public/pages/slo_edit/components/synthetics_availability/synthetics_availability_indicator_type_form.tsx index a1ec5714de504..b796f1b25633d 100644 --- a/x-pack/plugins/observability_solution/slo/public/pages/slo_edit/components/synthetics_availability/synthetics_availability_indicator_type_form.tsx +++ b/x-pack/plugins/observability_solution/slo/public/pages/slo_edit/components/synthetics_availability/synthetics_availability_indicator_type_form.tsx @@ -4,25 +4,24 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import React, { useState } from 'react'; import { EuiFlexGroup, EuiFlexItem, EuiIconTip } from '@elastic/eui'; +import { FilterStateStore } from '@kbn/es-query'; import { i18n } from '@kbn/i18n'; import { ALL_VALUE, - SyntheticsAvailabilityIndicator, - QuerySchema, FiltersSchema, + QuerySchema, + SyntheticsAvailabilityIndicator, } from '@kbn/slo-schema'; -import { FilterStateStore } from '@kbn/es-query'; +import moment from 'moment'; +import React, { useState } from 'react'; import { useFormContext } from 'react-hook-form'; -import { FieldSelector } from '../synthetics_common/field_selector'; +import { formatAllFilters } from '../../helpers/format_filters'; import { CreateSLOForm } from '../../types'; import { DataPreviewChart } from '../common/data_preview_chart'; -import { QueryBuilder } from '../common/query_builder'; import { GroupByCardinality } from '../common/group_by_cardinality'; -import { formatAllFilters } from '../../helpers/format_filters'; - -const ONE_DAY_IN_MILLISECONDS = 1 * 60 * 60 * 1000 * 24; +import { QueryBuilder } from '../common/query_builder'; +import { FieldSelector } from '../synthetics_common/field_selector'; export function SyntheticsAvailabilityIndicatorTypeForm() { const { watch } = useFormContext>(); @@ -36,8 +35,8 @@ export function SyntheticsAvailabilityIndicatorTypeForm() { ]); const [range, _] = useState({ - start: new Date().getTime() - ONE_DAY_IN_MILLISECONDS, - end: new Date().getTime(), + from: moment().subtract(1, 'day').toDate(), + to: new Date(), }); const filters = { diff --git a/x-pack/plugins/observability_solution/slo/public/pages/slo_edit/hooks/use_preview.ts b/x-pack/plugins/observability_solution/slo/public/pages/slo_edit/hooks/use_preview.ts index 8d21ac3938b8d..bab6492ac3bd1 100644 --- a/x-pack/plugins/observability_solution/slo/public/pages/slo_edit/hooks/use_preview.ts +++ b/x-pack/plugins/observability_solution/slo/public/pages/slo_edit/hooks/use_preview.ts @@ -13,7 +13,7 @@ import { useGetPreviewData } from '../../../hooks/use_get_preview_data'; export function useDebouncedGetPreviewData( isIndicatorValid: boolean, indicator: Indicator, - range: { start: number; end: number } + range: { from: Date; to: Date } ) { const serializedIndicator = JSON.stringify(indicator); const [indicatorState, setIndicatorState] = useState(serializedIndicator); diff --git a/x-pack/plugins/observability_solution/slo/public/pages/slos/components/common/good_bad_events_chart.tsx b/x-pack/plugins/observability_solution/slo/public/pages/slos/components/common/good_bad_events_chart.tsx index 3f0e88b912ec2..6d65c4e344d3d 100644 --- a/x-pack/plugins/observability_solution/slo/public/pages/slos/components/common/good_bad_events_chart.tsx +++ b/x-pack/plugins/observability_solution/slo/public/pages/slos/components/common/good_bad_events_chart.tsx @@ -24,7 +24,7 @@ import { GetPreviewDataResponse, SLOWithSummaryResponse } from '@kbn/slo-schema' import moment from 'moment'; import React, { useRef } from 'react'; import { TimeBounds } from '../../../slo_details/types'; -import { getBrushData } from '../../../../utils/slo/duration'; +import { getBrushTimeBounds } from '../../../../utils/slo/duration'; import { useKibana } from '../../../../utils/kibana_react'; import { openInDiscover } from '../../../../utils/slo/get_discover_link'; @@ -120,7 +120,7 @@ export function GoodBadEventsChart({ locale={i18n.getLocale()} onElementClick={barClickHandler as ElementClickListener} onBrushEnd={(brushArea) => { - onBrushed?.(getBrushData(brushArea)); + onBrushed?.(getBrushTimeBounds(brushArea)); }} /> {annotation} diff --git a/x-pack/plugins/observability_solution/slo/public/utils/slo/duration.ts b/x-pack/plugins/observability_solution/slo/public/utils/slo/duration.ts index c4d0af54a893a..d577feb263ce7 100644 --- a/x-pack/plugins/observability_solution/slo/public/utils/slo/duration.ts +++ b/x-pack/plugins/observability_solution/slo/public/utils/slo/duration.ts @@ -9,6 +9,7 @@ import moment from 'moment'; import { assertNever } from '@kbn/std'; import { BrushEvent } from '@elastic/charts'; import { Duration, DurationUnit } from '../../typings'; +import { TimeBounds } from '../../pages/slo_details/types'; export function toDuration(duration: string): Duration { const durationValue = duration.substring(0, duration.length - 1); @@ -44,9 +45,9 @@ export function toCalendarAlignedMomentUnitOfTime(unit: string): moment.unitOfTi } } -export function getBrushData(e: BrushEvent) { - const [from, to] = [Number(e.x?.[0]), Number(e.x?.[1])]; - const [fromUtc, toUtc] = [moment(from).format(), moment(to).format()]; +export function getBrushTimeBounds(e: BrushEvent): TimeBounds { + const from = moment(Number(e.x?.[0])).toDate(); + const to = moment(Number(e.x?.[1])).toDate(); - return { from, to, fromUtc, toUtc }; + return { from, to }; } diff --git a/x-pack/plugins/observability_solution/slo/server/routes/slo/route.ts b/x-pack/plugins/observability_solution/slo/server/routes/slo/route.ts index d7e6d02583376..61c081b087e15 100644 --- a/x-pack/plugins/observability_solution/slo/server/routes/slo/route.ts +++ b/x-pack/plugins/observability_solution/slo/server/routes/slo/route.ts @@ -12,12 +12,13 @@ import { deleteSLOInstancesParamsSchema, deleteSLOParamsSchema, fetchHistoricalSummaryParamsSchema, + fetchHistoricalSummaryResponseSchema, + fetchSLOHealthParamsSchema, findSloDefinitionsParamsSchema, findSLOGroupsParamsSchema, findSLOParamsSchema, getPreviewDataParamsSchema, getSLOBurnRatesParamsSchema, - fetchSLOHealthParamsSchema, getSLOInstancesParamsSchema, getSLOParamsSchema, manageSLOParamsSchema, @@ -44,7 +45,6 @@ import { KibanaSavedObjectsSLORepository, UpdateSLO, } from '../../services'; -import { FetchHistoricalSummary } from '../../services/fetch_historical_summary'; import { FindSLODefinitions } from '../../services/find_slo_definitions'; import { getBurnRates } from '../../services/get_burn_rates'; import { getGlobalDiagnosis } from '../../services/get_diagnosis'; @@ -513,9 +513,10 @@ const fetchHistoricalSummary = createSloServerRoute({ const esClient = (await context.core).elasticsearch.client.asCurrentUser; const historicalSummaryClient = new DefaultHistoricalSummaryClient(esClient); - const fetchSummaryData = new FetchHistoricalSummary(historicalSummaryClient); - return await fetchSummaryData.execute(params.body); + const historicalSummary = await historicalSummaryClient.fetch(params.body); + + return fetchHistoricalSummaryResponseSchema.encode(historicalSummary); }, }); diff --git a/x-pack/plugins/observability_solution/slo/server/services/__snapshots__/historical_summary_client.test.ts.snap b/x-pack/plugins/observability_solution/slo/server/services/__snapshots__/historical_summary_client.test.ts.snap index 0609ce39540c0..2759ac43d2149 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/__snapshots__/historical_summary_client.test.ts.snap +++ b/x-pack/plugins/observability_solution/slo/server/services/__snapshots__/historical_summary_client.test.ts.snap @@ -3024,7 +3024,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 1`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 1`] = ` Object { "date": Any, "errorBudget": Object { @@ -3038,7 +3038,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 2`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 2`] = ` Object { "date": Any, "errorBudget": Object { @@ -3052,7 +3052,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 3`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 3`] = ` Object { "date": Any, "errorBudget": Object { @@ -3066,7 +3066,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 4`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 4`] = ` Object { "date": Any, "errorBudget": Object { @@ -3080,7 +3080,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 5`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 5`] = ` Object { "date": Any, "errorBudget": Object { @@ -3094,7 +3094,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 6`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 6`] = ` Object { "date": Any, "errorBudget": Object { @@ -3108,7 +3108,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 7`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 7`] = ` Object { "date": Any, "errorBudget": Object { @@ -3122,7 +3122,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 8`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 8`] = ` Object { "date": Any, "errorBudget": Object { @@ -3136,7 +3136,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 9`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 9`] = ` Object { "date": Any, "errorBudget": Object { @@ -3150,7 +3150,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 10`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 10`] = ` Object { "date": Any, "errorBudget": Object { @@ -3164,7 +3164,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 11`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 11`] = ` Object { "date": Any, "errorBudget": Object { @@ -3178,7 +3178,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 12`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 12`] = ` Object { "date": Any, "errorBudget": Object { @@ -3192,7 +3192,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 13`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 13`] = ` Object { "date": Any, "errorBudget": Object { @@ -3206,7 +3206,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 14`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 14`] = ` Object { "date": Any, "errorBudget": Object { @@ -3220,7 +3220,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 15`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 15`] = ` Object { "date": Any, "errorBudget": Object { @@ -3234,7 +3234,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 16`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 16`] = ` Object { "date": Any, "errorBudget": Object { @@ -3248,7 +3248,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 17`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 17`] = ` Object { "date": Any, "errorBudget": Object { @@ -3262,7 +3262,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 18`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 18`] = ` Object { "date": Any, "errorBudget": Object { @@ -3276,7 +3276,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 19`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 19`] = ` Object { "date": Any, "errorBudget": Object { @@ -3290,7 +3290,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 20`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 20`] = ` Object { "date": Any, "errorBudget": Object { @@ -3304,7 +3304,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 21`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 21`] = ` Object { "date": Any, "errorBudget": Object { @@ -3318,7 +3318,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 22`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 22`] = ` Object { "date": Any, "errorBudget": Object { @@ -3332,7 +3332,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 23`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 23`] = ` Object { "date": Any, "errorBudget": Object { @@ -3346,7 +3346,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 24`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 24`] = ` Object { "date": Any, "errorBudget": Object { @@ -3360,7 +3360,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 25`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 25`] = ` Object { "date": Any, "errorBudget": Object { @@ -3374,7 +3374,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 26`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 26`] = ` Object { "date": Any, "errorBudget": Object { @@ -3388,7 +3388,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 27`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 27`] = ` Object { "date": Any, "errorBudget": Object { @@ -3402,7 +3402,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 28`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 28`] = ` Object { "date": Any, "errorBudget": Object { @@ -3416,7 +3416,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 29`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 29`] = ` Object { "date": Any, "errorBudget": Object { @@ -3430,7 +3430,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 30`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 30`] = ` Object { "date": Any, "errorBudget": Object { @@ -3444,7 +3444,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 31`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 31`] = ` Object { "date": Any, "errorBudget": Object { @@ -3458,7 +3458,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 32`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 32`] = ` Object { "date": Any, "errorBudget": Object { @@ -3472,7 +3472,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 33`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 33`] = ` Object { "date": Any, "errorBudget": Object { @@ -3486,7 +3486,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 34`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 34`] = ` Object { "date": Any, "errorBudget": Object { @@ -3500,7 +3500,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 35`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 35`] = ` Object { "date": Any, "errorBudget": Object { @@ -3514,7 +3514,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 36`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 36`] = ` Object { "date": Any, "errorBudget": Object { @@ -3528,7 +3528,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 37`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 37`] = ` Object { "date": Any, "errorBudget": Object { @@ -3542,7 +3542,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 38`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 38`] = ` Object { "date": Any, "errorBudget": Object { @@ -3556,7 +3556,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 39`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 39`] = ` Object { "date": Any, "errorBudget": Object { @@ -3570,7 +3570,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 40`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 40`] = ` Object { "date": Any, "errorBudget": Object { @@ -3584,7 +3584,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 41`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 41`] = ` Object { "date": Any, "errorBudget": Object { @@ -3598,7 +3598,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 42`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 42`] = ` Object { "date": Any, "errorBudget": Object { @@ -3612,7 +3612,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 43`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 43`] = ` Object { "date": Any, "errorBudget": Object { @@ -3626,7 +3626,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 44`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 44`] = ` Object { "date": Any, "errorBudget": Object { @@ -3640,7 +3640,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 45`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 45`] = ` Object { "date": Any, "errorBudget": Object { @@ -3654,7 +3654,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 46`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 46`] = ` Object { "date": Any, "errorBudget": Object { @@ -3668,7 +3668,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 47`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 47`] = ` Object { "date": Any, "errorBudget": Object { @@ -3682,7 +3682,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 48`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 48`] = ` Object { "date": Any, "errorBudget": Object { @@ -3696,7 +3696,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 49`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 49`] = ` Object { "date": Any, "errorBudget": Object { @@ -3710,7 +3710,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 50`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 50`] = ` Object { "date": Any, "errorBudget": Object { @@ -3724,7 +3724,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 51`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 51`] = ` Object { "date": Any, "errorBudget": Object { @@ -3738,7 +3738,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 52`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 52`] = ` Object { "date": Any, "errorBudget": Object { @@ -3752,7 +3752,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 53`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 53`] = ` Object { "date": Any, "errorBudget": Object { @@ -3766,7 +3766,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 54`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 54`] = ` Object { "date": Any, "errorBudget": Object { @@ -3780,7 +3780,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 55`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 55`] = ` Object { "date": Any, "errorBudget": Object { @@ -3794,7 +3794,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 56`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 56`] = ` Object { "date": Any, "errorBudget": Object { @@ -3808,7 +3808,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 57`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 57`] = ` Object { "date": Any, "errorBudget": Object { @@ -3822,7 +3822,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 58`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 58`] = ` Object { "date": Any, "errorBudget": Object { @@ -3836,7 +3836,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 59`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 59`] = ` Object { "date": Any, "errorBudget": Object { @@ -3850,7 +3850,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 60`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 60`] = ` Object { "date": Any, "errorBudget": Object { @@ -3864,7 +3864,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 61`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 61`] = ` Object { "date": Any, "errorBudget": Object { @@ -3878,7 +3878,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 62`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 62`] = ` Object { "date": Any, "errorBudget": Object { @@ -3892,7 +3892,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 63`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 63`] = ` Object { "date": Any, "errorBudget": Object { @@ -3906,7 +3906,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 64`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 64`] = ` Object { "date": Any, "errorBudget": Object { @@ -3920,7 +3920,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 65`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 65`] = ` Object { "date": Any, "errorBudget": Object { @@ -3934,7 +3934,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 66`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 66`] = ` Object { "date": Any, "errorBudget": Object { @@ -3948,7 +3948,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 67`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 67`] = ` Object { "date": Any, "errorBudget": Object { @@ -3962,7 +3962,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 68`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 68`] = ` Object { "date": Any, "errorBudget": Object { @@ -3976,7 +3976,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 69`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 69`] = ` Object { "date": Any, "errorBudget": Object { @@ -3990,7 +3990,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 70`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 70`] = ` Object { "date": Any, "errorBudget": Object { @@ -4004,7 +4004,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 71`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 71`] = ` Object { "date": Any, "errorBudget": Object { @@ -4018,7 +4018,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 72`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 72`] = ` Object { "date": Any, "errorBudget": Object { @@ -4032,7 +4032,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 73`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 73`] = ` Object { "date": Any, "errorBudget": Object { @@ -4046,7 +4046,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 74`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 74`] = ` Object { "date": Any, "errorBudget": Object { @@ -4060,7 +4060,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 75`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 75`] = ` Object { "date": Any, "errorBudget": Object { @@ -4074,7 +4074,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 76`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 76`] = ` Object { "date": Any, "errorBudget": Object { @@ -4088,7 +4088,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 77`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 77`] = ` Object { "date": Any, "errorBudget": Object { @@ -4102,7 +4102,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 78`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 78`] = ` Object { "date": Any, "errorBudget": Object { @@ -4116,7 +4116,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 79`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 79`] = ` Object { "date": Any, "errorBudget": Object { @@ -4130,7 +4130,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 80`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 80`] = ` Object { "date": Any, "errorBudget": Object { @@ -4144,7 +4144,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 81`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 81`] = ` Object { "date": Any, "errorBudget": Object { @@ -4158,7 +4158,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 82`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 82`] = ` Object { "date": Any, "errorBudget": Object { @@ -4172,7 +4172,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 83`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 83`] = ` Object { "date": Any, "errorBudget": Object { @@ -4186,7 +4186,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 84`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 84`] = ` Object { "date": Any, "errorBudget": Object { @@ -4200,7 +4200,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 85`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 85`] = ` Object { "date": Any, "errorBudget": Object { @@ -4214,7 +4214,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 86`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 86`] = ` Object { "date": Any, "errorBudget": Object { @@ -4228,7 +4228,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 87`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 87`] = ` Object { "date": Any, "errorBudget": Object { @@ -4242,7 +4242,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 88`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 88`] = ` Object { "date": Any, "errorBudget": Object { @@ -4256,7 +4256,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 89`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 89`] = ` Object { "date": Any, "errorBudget": Object { @@ -4270,7 +4270,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 90`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 90`] = ` Object { "date": Any, "errorBudget": Object { @@ -4284,7 +4284,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 91`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 91`] = ` Object { "date": Any, "errorBudget": Object { @@ -4298,7 +4298,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 92`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 92`] = ` Object { "date": Any, "errorBudget": Object { @@ -4312,7 +4312,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 93`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 93`] = ` Object { "date": Any, "errorBudget": Object { @@ -4326,7 +4326,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 94`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 94`] = ` Object { "date": Any, "errorBudget": Object { @@ -4340,7 +4340,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 95`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 95`] = ` Object { "date": Any, "errorBudget": Object { @@ -4354,7 +4354,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 96`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 96`] = ` Object { "date": Any, "errorBudget": Object { @@ -4368,7 +4368,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 97`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 97`] = ` Object { "date": Any, "errorBudget": Object { @@ -4382,7 +4382,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 98`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 98`] = ` Object { "date": Any, "errorBudget": Object { @@ -4396,7 +4396,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 99`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 99`] = ` Object { "date": Any, "errorBudget": Object { @@ -4410,7 +4410,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 100`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 100`] = ` Object { "date": Any, "errorBudget": Object { @@ -4424,7 +4424,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 101`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 101`] = ` Object { "date": Any, "errorBudget": Object { @@ -4438,7 +4438,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 102`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 102`] = ` Object { "date": Any, "errorBudget": Object { @@ -4452,7 +4452,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 103`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 103`] = ` Object { "date": Any, "errorBudget": Object { @@ -4466,7 +4466,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 104`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 104`] = ` Object { "date": Any, "errorBudget": Object { @@ -4480,7 +4480,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 105`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 105`] = ` Object { "date": Any, "errorBudget": Object { @@ -4494,7 +4494,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 106`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 106`] = ` Object { "date": Any, "errorBudget": Object { @@ -4508,7 +4508,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 107`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 107`] = ` Object { "date": Any, "errorBudget": Object { @@ -4522,7 +4522,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 108`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 108`] = ` Object { "date": Any, "errorBudget": Object { @@ -4536,7 +4536,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 109`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 109`] = ` Object { "date": Any, "errorBudget": Object { @@ -4550,7 +4550,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 110`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 110`] = ` Object { "date": Any, "errorBudget": Object { @@ -4564,7 +4564,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 111`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 111`] = ` Object { "date": Any, "errorBudget": Object { @@ -4578,7 +4578,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 112`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 112`] = ` Object { "date": Any, "errorBudget": Object { @@ -4592,7 +4592,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 113`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 113`] = ` Object { "date": Any, "errorBudget": Object { @@ -4606,7 +4606,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 114`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 114`] = ` Object { "date": Any, "errorBudget": Object { @@ -4620,7 +4620,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 115`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 115`] = ` Object { "date": Any, "errorBudget": Object { @@ -4634,7 +4634,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 116`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 116`] = ` Object { "date": Any, "errorBudget": Object { @@ -4648,7 +4648,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 117`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 117`] = ` Object { "date": Any, "errorBudget": Object { @@ -4662,7 +4662,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 118`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 118`] = ` Object { "date": Any, "errorBudget": Object { @@ -4676,7 +4676,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 119`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 119`] = ` Object { "date": Any, "errorBudget": Object { @@ -4690,7 +4690,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 120`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 120`] = ` Object { "date": Any, "errorBudget": Object { @@ -4704,7 +4704,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 121`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 121`] = ` Object { "date": Any, "errorBudget": Object { @@ -4718,7 +4718,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 122`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 122`] = ` Object { "date": Any, "errorBudget": Object { @@ -4732,7 +4732,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 123`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 123`] = ` Object { "date": Any, "errorBudget": Object { @@ -4746,7 +4746,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 124`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 124`] = ` Object { "date": Any, "errorBudget": Object { @@ -4760,7 +4760,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 125`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 125`] = ` Object { "date": Any, "errorBudget": Object { @@ -4774,7 +4774,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 126`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 126`] = ` Object { "date": Any, "errorBudget": Object { @@ -4788,7 +4788,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 127`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 127`] = ` Object { "date": Any, "errorBudget": Object { @@ -4802,7 +4802,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 128`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 128`] = ` Object { "date": Any, "errorBudget": Object { @@ -4816,7 +4816,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 129`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 129`] = ` Object { "date": Any, "errorBudget": Object { @@ -4830,7 +4830,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 130`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 130`] = ` Object { "date": Any, "errorBudget": Object { @@ -4844,7 +4844,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 131`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 131`] = ` Object { "date": Any, "errorBudget": Object { @@ -4858,7 +4858,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 132`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 132`] = ` Object { "date": Any, "errorBudget": Object { @@ -4872,7 +4872,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 133`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 133`] = ` Object { "date": Any, "errorBudget": Object { @@ -4886,7 +4886,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 134`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 134`] = ` Object { "date": Any, "errorBudget": Object { @@ -4900,7 +4900,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 135`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 135`] = ` Object { "date": Any, "errorBudget": Object { @@ -4914,7 +4914,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 136`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 136`] = ` Object { "date": Any, "errorBudget": Object { @@ -4928,7 +4928,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 137`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 137`] = ` Object { "date": Any, "errorBudget": Object { @@ -4942,7 +4942,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 138`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 138`] = ` Object { "date": Any, "errorBudget": Object { @@ -4956,7 +4956,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 139`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 139`] = ` Object { "date": Any, "errorBudget": Object { @@ -4970,7 +4970,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 140`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 140`] = ` Object { "date": Any, "errorBudget": Object { @@ -4984,7 +4984,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 141`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 141`] = ` Object { "date": Any, "errorBudget": Object { @@ -4998,7 +4998,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 142`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 142`] = ` Object { "date": Any, "errorBudget": Object { @@ -5012,7 +5012,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 143`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 143`] = ` Object { "date": Any, "errorBudget": Object { @@ -5026,7 +5026,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 144`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 144`] = ` Object { "date": Any, "errorBudget": Object { @@ -5040,7 +5040,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 145`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 145`] = ` Object { "date": Any, "errorBudget": Object { @@ -5054,7 +5054,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 146`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 146`] = ` Object { "date": Any, "errorBudget": Object { @@ -5068,7 +5068,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 147`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 147`] = ` Object { "date": Any, "errorBudget": Object { @@ -5082,7 +5082,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 148`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 148`] = ` Object { "date": Any, "errorBudget": Object { @@ -5096,7 +5096,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 149`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 149`] = ` Object { "date": Any, "errorBudget": Object { @@ -5110,7 +5110,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 150`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 150`] = ` Object { "date": Any, "errorBudget": Object { @@ -5124,7 +5124,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 151`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 151`] = ` Object { "date": Any, "errorBudget": Object { @@ -5138,7 +5138,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 152`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 152`] = ` Object { "date": Any, "errorBudget": Object { @@ -5152,7 +5152,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 153`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 153`] = ` Object { "date": Any, "errorBudget": Object { @@ -5166,7 +5166,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 154`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 154`] = ` Object { "date": Any, "errorBudget": Object { @@ -5180,7 +5180,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 155`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 155`] = ` Object { "date": Any, "errorBudget": Object { @@ -5194,7 +5194,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 156`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 156`] = ` Object { "date": Any, "errorBudget": Object { @@ -5208,7 +5208,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 157`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 157`] = ` Object { "date": Any, "errorBudget": Object { @@ -5222,7 +5222,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 158`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 158`] = ` Object { "date": Any, "errorBudget": Object { @@ -5236,7 +5236,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 159`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 159`] = ` Object { "date": Any, "errorBudget": Object { @@ -5250,7 +5250,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 160`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 160`] = ` Object { "date": Any, "errorBudget": Object { @@ -5264,7 +5264,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 161`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 161`] = ` Object { "date": Any, "errorBudget": Object { @@ -5278,7 +5278,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 162`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 162`] = ` Object { "date": Any, "errorBudget": Object { @@ -5292,7 +5292,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 163`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 163`] = ` Object { "date": Any, "errorBudget": Object { @@ -5306,7 +5306,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 164`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 164`] = ` Object { "date": Any, "errorBudget": Object { @@ -5320,7 +5320,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 165`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 165`] = ` Object { "date": Any, "errorBudget": Object { @@ -5334,7 +5334,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 166`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 166`] = ` Object { "date": Any, "errorBudget": Object { @@ -5348,7 +5348,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 167`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 167`] = ` Object { "date": Any, "errorBudget": Object { @@ -5362,7 +5362,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 168`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 168`] = ` Object { "date": Any, "errorBudget": Object { @@ -5376,7 +5376,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 169`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 169`] = ` Object { "date": Any, "errorBudget": Object { @@ -5390,7 +5390,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 170`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 170`] = ` Object { "date": Any, "errorBudget": Object { @@ -5404,7 +5404,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 171`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 171`] = ` Object { "date": Any, "errorBudget": Object { @@ -5418,7 +5418,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 172`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 172`] = ` Object { "date": Any, "errorBudget": Object { @@ -5432,7 +5432,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 173`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 173`] = ` Object { "date": Any, "errorBudget": Object { @@ -5446,7 +5446,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 174`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 174`] = ` Object { "date": Any, "errorBudget": Object { @@ -5460,7 +5460,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 175`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 175`] = ` Object { "date": Any, "errorBudget": Object { @@ -5474,7 +5474,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 176`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 176`] = ` Object { "date": Any, "errorBudget": Object { @@ -5488,7 +5488,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 177`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 177`] = ` Object { "date": Any, "errorBudget": Object { @@ -5502,7 +5502,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 178`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 178`] = ` Object { "date": Any, "errorBudget": Object { @@ -5516,7 +5516,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 179`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 179`] = ` Object { "date": Any, "errorBudget": Object { @@ -5530,7 +5530,7 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary 180`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the SLO timeWindow date range 180`] = ` Object { "date": Any, "errorBudget": Object { @@ -5544,2522 +5544,5238 @@ Object { } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 1`] = ` +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 1`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.00138, + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 2`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 3`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 4`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 5`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 6`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 7`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 8`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 9`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 10`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 11`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 12`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 13`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 14`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 15`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 16`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 17`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 18`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 19`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 20`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 21`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 22`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 23`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 24`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 25`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 26`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 27`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 28`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 29`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 30`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 31`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 32`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 33`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 34`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 35`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 36`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 37`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 38`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 39`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 40`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 41`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 42`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 43`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 44`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 45`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 46`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 47`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 48`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 49`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 50`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 51`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 52`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 53`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 54`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 55`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 56`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 57`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 58`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 59`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 60`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 61`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 62`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 63`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 64`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 65`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 66`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 67`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 68`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 69`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 70`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 71`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 72`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 73`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 74`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 75`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 76`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 77`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 78`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 79`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 80`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 81`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 82`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 83`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 84`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 85`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 86`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 87`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 88`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 89`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 90`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 91`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 92`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 93`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 94`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 95`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 96`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Occurrences SLOs returns the summary using the provided date range 97`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.3, + "initial": 0.1, + "isEstimated": false, + "remaining": 0.7, + }, + "sliValue": 0.97, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 1`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.66666, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.33334, + }, + "sliValue": 0.966667, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 2`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.66666, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.33334, + }, + "sliValue": 0.966667, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 3`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.66666, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.33334, + }, + "sliValue": 0.966667, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 4`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.66666, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.33334, + }, + "sliValue": 0.966667, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 5`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.66666, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.33334, + }, + "sliValue": 0.966667, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 6`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.66666, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.33334, + }, + "sliValue": 0.966667, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 7`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.66666, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.33334, + }, + "sliValue": 0.966667, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 8`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.66666, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.33334, + }, + "sliValue": 0.966667, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 9`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.66666, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.33334, + }, + "sliValue": 0.966667, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 10`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.66666, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.33334, + }, + "sliValue": 0.966667, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 11`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.66666, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.33334, + }, + "sliValue": 0.966667, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 12`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.66666, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.33334, + }, + "sliValue": 0.966667, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 13`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.66666, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.33334, + }, + "sliValue": 0.966667, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 14`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.66666, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.33334, + }, + "sliValue": 0.966667, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 15`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.66666, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.33334, + }, + "sliValue": 0.966667, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 16`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.66666, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.33334, + }, + "sliValue": 0.966667, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 17`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.66666, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.33334, + }, + "sliValue": 0.966667, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 18`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.66666, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.33334, + }, + "sliValue": 0.966667, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 19`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.66666, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.33334, + }, + "sliValue": 0.966667, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 20`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.66666, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.33334, + }, + "sliValue": 0.966667, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 21`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.66666, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.33334, + }, + "sliValue": 0.966667, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 22`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.66666, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.33334, + }, + "sliValue": 0.966667, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 23`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.66666, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.33334, + }, + "sliValue": 0.966667, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 24`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.66666, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.33334, + }, + "sliValue": 0.966667, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 25`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.66666, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.33334, + }, + "sliValue": 0.966667, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 26`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.66666, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.33334, + }, + "sliValue": 0.966667, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 27`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.66666, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.33334, + }, + "sliValue": 0.966667, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 28`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.66666, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.33334, + }, + "sliValue": 0.966667, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 29`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.66666, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.33334, + }, + "sliValue": 0.966667, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 30`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.66666, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.33334, + }, + "sliValue": 0.966667, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 31`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.66666, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.33334, + }, + "sliValue": 0.966667, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 32`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.66666, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.33334, + }, + "sliValue": 0.966667, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 33`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.66666, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.33334, + }, + "sliValue": 0.966667, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 34`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.66666, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.33334, + }, + "sliValue": 0.966667, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 35`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.66666, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.33334, + }, + "sliValue": 0.966667, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 36`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.66666, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.33334, + }, + "sliValue": 0.966667, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 37`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.66666, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.33334, + }, + "sliValue": 0.966667, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 38`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.66666, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.33334, + }, + "sliValue": 0.966667, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 39`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.66666, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.33334, + }, + "sliValue": 0.966667, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 40`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.66666, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.33334, + }, + "sliValue": 0.966667, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 41`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.66666, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.33334, + }, + "sliValue": 0.966667, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 42`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.66666, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.33334, + }, + "sliValue": 0.966667, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 43`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.66666, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.33334, + }, + "sliValue": 0.966667, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 44`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.66666, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.33334, + }, + "sliValue": 0.966667, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 45`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.66666, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.33334, + }, + "sliValue": 0.966667, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 46`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.66666, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.33334, + }, + "sliValue": 0.966667, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 47`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.66666, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.33334, + }, + "sliValue": 0.966667, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 48`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.66666, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.33334, + }, + "sliValue": 0.966667, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 49`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.66666, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.33334, + }, + "sliValue": 0.966667, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 50`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.66666, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.33334, + }, + "sliValue": 0.966667, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 51`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.66666, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.33334, + }, + "sliValue": 0.966667, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 52`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.66666, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.33334, + }, + "sliValue": 0.966667, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 53`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.66666, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.33334, + }, + "sliValue": 0.966667, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 54`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.66666, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.33334, + }, + "sliValue": 0.966667, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 55`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.66666, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.33334, + }, + "sliValue": 0.966667, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 56`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.66666, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.33334, + }, + "sliValue": 0.966667, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 57`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.66666, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.33334, + }, + "sliValue": 0.966667, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 58`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.66666, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.33334, + }, + "sliValue": 0.966667, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 59`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.66666, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.33334, + }, + "sliValue": 0.966667, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 60`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.66666, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.33334, + }, + "sliValue": 0.966667, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 61`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.66666, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.33334, + }, + "sliValue": 0.966667, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 62`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.66666, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.33334, + }, + "sliValue": 0.966667, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 63`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.66666, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.33334, + }, + "sliValue": 0.966667, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 64`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.66666, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.33334, + }, + "sliValue": 0.966667, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 65`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.66666, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.33334, + }, + "sliValue": 0.966667, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 66`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.66666, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.33334, + }, + "sliValue": 0.966667, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 67`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.66666, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.33334, + }, + "sliValue": 0.966667, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 68`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.66666, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.33334, + }, + "sliValue": 0.966667, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 69`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.66666, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.33334, + }, + "sliValue": 0.966667, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 70`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.66666, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.33334, + }, + "sliValue": 0.966667, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 71`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.66666, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.33334, + }, + "sliValue": 0.966667, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 72`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.66666, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.33334, + }, + "sliValue": 0.966667, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 73`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.66666, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.33334, + }, + "sliValue": 0.966667, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 74`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.66666, "initial": 0.05, "isEstimated": false, - "remaining": 0.99862, + "remaining": 0.33334, }, - "sliValue": 0.999931, + "sliValue": 0.966667, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 2`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 75`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.00278, + "consumed": 0.66666, "initial": 0.05, "isEstimated": false, - "remaining": 0.99722, + "remaining": 0.33334, }, - "sliValue": 0.999861, + "sliValue": 0.966667, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 3`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 76`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.00416, + "consumed": 0.66666, "initial": 0.05, "isEstimated": false, - "remaining": 0.99584, + "remaining": 0.33334, }, - "sliValue": 0.999792, + "sliValue": 0.966667, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 4`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 77`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.00556, + "consumed": 0.66666, "initial": 0.05, "isEstimated": false, - "remaining": 0.99444, + "remaining": 0.33334, }, - "sliValue": 0.999722, + "sliValue": 0.966667, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 5`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 78`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.00694, + "consumed": 0.66666, "initial": 0.05, "isEstimated": false, - "remaining": 0.99306, + "remaining": 0.33334, }, - "sliValue": 0.999653, + "sliValue": 0.966667, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 6`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 79`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.00834, + "consumed": 0.66666, "initial": 0.05, "isEstimated": false, - "remaining": 0.99166, + "remaining": 0.33334, }, - "sliValue": 0.999583, + "sliValue": 0.966667, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 7`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 80`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.00972, + "consumed": 0.66666, "initial": 0.05, "isEstimated": false, - "remaining": 0.99028, + "remaining": 0.33334, }, - "sliValue": 0.999514, + "sliValue": 0.966667, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 8`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 81`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.01112, + "consumed": 0.66666, "initial": 0.05, "isEstimated": false, - "remaining": 0.98888, + "remaining": 0.33334, }, - "sliValue": 0.999444, + "sliValue": 0.966667, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 9`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 82`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.0125, + "consumed": 0.66666, "initial": 0.05, "isEstimated": false, - "remaining": 0.9875, + "remaining": 0.33334, }, - "sliValue": 0.999375, + "sliValue": 0.966667, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 10`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 83`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.01388, + "consumed": 0.66666, "initial": 0.05, "isEstimated": false, - "remaining": 0.98612, + "remaining": 0.33334, }, - "sliValue": 0.999306, + "sliValue": 0.966667, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 11`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 84`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.01528, + "consumed": 0.66666, "initial": 0.05, "isEstimated": false, - "remaining": 0.98472, + "remaining": 0.33334, }, - "sliValue": 0.999236, + "sliValue": 0.966667, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 12`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 85`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.01666, + "consumed": 0.66666, "initial": 0.05, "isEstimated": false, - "remaining": 0.98334, + "remaining": 0.33334, }, - "sliValue": 0.999167, + "sliValue": 0.966667, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 13`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 86`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.01806, + "consumed": 0.66666, "initial": 0.05, "isEstimated": false, - "remaining": 0.98194, + "remaining": 0.33334, }, - "sliValue": 0.999097, + "sliValue": 0.966667, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 14`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 87`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.01944, + "consumed": 0.66666, "initial": 0.05, "isEstimated": false, - "remaining": 0.98056, + "remaining": 0.33334, }, - "sliValue": 0.999028, + "sliValue": 0.966667, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 15`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 88`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.02084, + "consumed": 0.66666, "initial": 0.05, "isEstimated": false, - "remaining": 0.97916, + "remaining": 0.33334, }, - "sliValue": 0.998958, + "sliValue": 0.966667, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 16`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 89`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.02222, + "consumed": 0.66666, "initial": 0.05, "isEstimated": false, - "remaining": 0.97778, + "remaining": 0.33334, }, - "sliValue": 0.998889, + "sliValue": 0.966667, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 17`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 90`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.02362, + "consumed": 0.66666, "initial": 0.05, "isEstimated": false, - "remaining": 0.97638, + "remaining": 0.33334, }, - "sliValue": 0.998819, + "sliValue": 0.966667, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 18`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 91`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.025, + "consumed": 0.66666, "initial": 0.05, "isEstimated": false, - "remaining": 0.975, + "remaining": 0.33334, }, - "sliValue": 0.99875, + "sliValue": 0.966667, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 19`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 92`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.02638, + "consumed": 0.66666, "initial": 0.05, "isEstimated": false, - "remaining": 0.97362, + "remaining": 0.33334, }, - "sliValue": 0.998681, + "sliValue": 0.966667, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 20`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 93`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.02778, + "consumed": 0.66666, "initial": 0.05, "isEstimated": false, - "remaining": 0.97222, + "remaining": 0.33334, }, - "sliValue": 0.998611, + "sliValue": 0.966667, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 21`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 94`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.02916, + "consumed": 0.66666, "initial": 0.05, "isEstimated": false, - "remaining": 0.97084, + "remaining": 0.33334, }, - "sliValue": 0.998542, + "sliValue": 0.966667, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 22`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 95`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.03056, + "consumed": 0.66666, "initial": 0.05, "isEstimated": false, - "remaining": 0.96944, + "remaining": 0.33334, }, - "sliValue": 0.998472, + "sliValue": 0.966667, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 23`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 96`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.03194, + "consumed": 0.66666, "initial": 0.05, "isEstimated": false, - "remaining": 0.96806, + "remaining": 0.33334, }, - "sliValue": 0.998403, + "sliValue": 0.966667, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 24`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 97`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.03334, + "consumed": 0.66666, "initial": 0.05, "isEstimated": false, - "remaining": 0.96666, + "remaining": 0.33334, }, - "sliValue": 0.998333, + "sliValue": 0.966667, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 25`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 98`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.03472, + "consumed": 0.66666, "initial": 0.05, "isEstimated": false, - "remaining": 0.96528, + "remaining": 0.33334, }, - "sliValue": 0.998264, + "sliValue": 0.966667, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 26`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 99`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.03612, + "consumed": 0.66666, "initial": 0.05, "isEstimated": false, - "remaining": 0.96388, + "remaining": 0.33334, }, - "sliValue": 0.998194, + "sliValue": 0.966667, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 27`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 100`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.0375, + "consumed": 0.66666, "initial": 0.05, "isEstimated": false, - "remaining": 0.9625, + "remaining": 0.33334, }, - "sliValue": 0.998125, + "sliValue": 0.966667, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 28`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 101`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.03888, + "consumed": 0.66666, "initial": 0.05, "isEstimated": false, - "remaining": 0.96112, + "remaining": 0.33334, }, - "sliValue": 0.998056, + "sliValue": 0.966667, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 29`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 102`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.04028, + "consumed": 0.66666, "initial": 0.05, "isEstimated": false, - "remaining": 0.95972, + "remaining": 0.33334, }, - "sliValue": 0.997986, + "sliValue": 0.966667, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 30`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 103`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.04166, + "consumed": 0.66666, "initial": 0.05, "isEstimated": false, - "remaining": 0.95834, + "remaining": 0.33334, }, - "sliValue": 0.997917, + "sliValue": 0.966667, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 31`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 104`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.04306, + "consumed": 0.66666, "initial": 0.05, "isEstimated": false, - "remaining": 0.95694, + "remaining": 0.33334, }, - "sliValue": 0.997847, + "sliValue": 0.966667, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 32`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 105`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.04444, + "consumed": 0.66666, "initial": 0.05, "isEstimated": false, - "remaining": 0.95556, + "remaining": 0.33334, }, - "sliValue": 0.997778, + "sliValue": 0.966667, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 33`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 106`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.04584, + "consumed": 0.66666, "initial": 0.05, "isEstimated": false, - "remaining": 0.95416, + "remaining": 0.33334, }, - "sliValue": 0.997708, + "sliValue": 0.966667, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 34`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 107`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.04722, + "consumed": 0.66666, "initial": 0.05, "isEstimated": false, - "remaining": 0.95278, + "remaining": 0.33334, }, - "sliValue": 0.997639, + "sliValue": 0.966667, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 35`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 108`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.04862, + "consumed": 0.66666, "initial": 0.05, "isEstimated": false, - "remaining": 0.95138, + "remaining": 0.33334, }, - "sliValue": 0.997569, + "sliValue": 0.966667, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 36`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 109`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.05, + "consumed": 0.66666, "initial": 0.05, "isEstimated": false, - "remaining": 0.95, + "remaining": 0.33334, }, - "sliValue": 0.9975, + "sliValue": 0.966667, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 37`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 110`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.05138, + "consumed": 0.66666, "initial": 0.05, "isEstimated": false, - "remaining": 0.94862, + "remaining": 0.33334, }, - "sliValue": 0.997431, + "sliValue": 0.966667, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 38`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 111`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.05278, + "consumed": 0.66666, "initial": 0.05, "isEstimated": false, - "remaining": 0.94722, + "remaining": 0.33334, }, - "sliValue": 0.997361, + "sliValue": 0.966667, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 39`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 112`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.05416, + "consumed": 0.66666, "initial": 0.05, "isEstimated": false, - "remaining": 0.94584, + "remaining": 0.33334, }, - "sliValue": 0.997292, + "sliValue": 0.966667, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 40`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 113`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.05556, + "consumed": 0.66666, "initial": 0.05, "isEstimated": false, - "remaining": 0.94444, + "remaining": 0.33334, }, - "sliValue": 0.997222, + "sliValue": 0.966667, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 41`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 114`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.05694, + "consumed": 0.66666, "initial": 0.05, "isEstimated": false, - "remaining": 0.94306, + "remaining": 0.33334, }, - "sliValue": 0.997153, + "sliValue": 0.966667, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 42`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 115`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.05834, + "consumed": 0.66666, "initial": 0.05, "isEstimated": false, - "remaining": 0.94166, + "remaining": 0.33334, }, - "sliValue": 0.997083, + "sliValue": 0.966667, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 43`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 116`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.05972, + "consumed": 0.66666, "initial": 0.05, "isEstimated": false, - "remaining": 0.94028, + "remaining": 0.33334, }, - "sliValue": 0.997014, + "sliValue": 0.966667, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 44`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 117`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.06112, + "consumed": 0.66666, "initial": 0.05, "isEstimated": false, - "remaining": 0.93888, + "remaining": 0.33334, }, - "sliValue": 0.996944, + "sliValue": 0.966667, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 45`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 118`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.0625, + "consumed": 0.66666, "initial": 0.05, "isEstimated": false, - "remaining": 0.9375, + "remaining": 0.33334, }, - "sliValue": 0.996875, + "sliValue": 0.966667, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 46`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 119`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.06388, + "consumed": 0.66666, "initial": 0.05, "isEstimated": false, - "remaining": 0.93612, + "remaining": 0.33334, }, - "sliValue": 0.996806, + "sliValue": 0.966667, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 47`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 120`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.06528, + "consumed": 0.66666, "initial": 0.05, "isEstimated": false, - "remaining": 0.93472, + "remaining": 0.33334, }, - "sliValue": 0.996736, + "sliValue": 0.966667, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 48`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 121`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.06666, + "consumed": 0.66666, "initial": 0.05, "isEstimated": false, - "remaining": 0.93334, + "remaining": 0.33334, }, - "sliValue": 0.996667, + "sliValue": 0.966667, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 49`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 122`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.06806, + "consumed": 0.66666, "initial": 0.05, "isEstimated": false, - "remaining": 0.93194, + "remaining": 0.33334, }, - "sliValue": 0.996597, + "sliValue": 0.966667, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 50`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 123`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.06944, + "consumed": 0.66666, "initial": 0.05, "isEstimated": false, - "remaining": 0.93056, + "remaining": 0.33334, }, - "sliValue": 0.996528, + "sliValue": 0.966667, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 51`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 124`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.07084, + "consumed": 0.66666, "initial": 0.05, "isEstimated": false, - "remaining": 0.92916, + "remaining": 0.33334, }, - "sliValue": 0.996458, + "sliValue": 0.966667, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 52`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 125`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.07222, + "consumed": 0.66666, "initial": 0.05, "isEstimated": false, - "remaining": 0.92778, + "remaining": 0.33334, }, - "sliValue": 0.996389, + "sliValue": 0.966667, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 53`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 126`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.07362, + "consumed": 0.66666, "initial": 0.05, "isEstimated": false, - "remaining": 0.92638, + "remaining": 0.33334, }, - "sliValue": 0.996319, + "sliValue": 0.966667, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 54`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 127`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.075, + "consumed": 0.66666, "initial": 0.05, "isEstimated": false, - "remaining": 0.925, + "remaining": 0.33334, }, - "sliValue": 0.99625, + "sliValue": 0.966667, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 55`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 128`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.07638, + "consumed": 0.66666, "initial": 0.05, "isEstimated": false, - "remaining": 0.92362, + "remaining": 0.33334, }, - "sliValue": 0.996181, + "sliValue": 0.966667, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 56`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 129`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.07778, + "consumed": 0.66666, "initial": 0.05, "isEstimated": false, - "remaining": 0.92222, + "remaining": 0.33334, }, - "sliValue": 0.996111, + "sliValue": 0.966667, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 57`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 130`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.07916, + "consumed": 0.66666, "initial": 0.05, "isEstimated": false, - "remaining": 0.92084, + "remaining": 0.33334, }, - "sliValue": 0.996042, + "sliValue": 0.966667, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 58`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 131`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.08056, + "consumed": 0.66666, "initial": 0.05, "isEstimated": false, - "remaining": 0.91944, + "remaining": 0.33334, }, - "sliValue": 0.995972, + "sliValue": 0.966667, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 59`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 132`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.08194, + "consumed": 0.66666, "initial": 0.05, "isEstimated": false, - "remaining": 0.91806, + "remaining": 0.33334, }, - "sliValue": 0.995903, + "sliValue": 0.966667, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 60`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 133`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.08334, + "consumed": 0.66666, "initial": 0.05, "isEstimated": false, - "remaining": 0.91666, + "remaining": 0.33334, }, - "sliValue": 0.995833, + "sliValue": 0.966667, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 61`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 134`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.08472, + "consumed": 0.66666, "initial": 0.05, "isEstimated": false, - "remaining": 0.91528, + "remaining": 0.33334, }, - "sliValue": 0.995764, + "sliValue": 0.966667, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 62`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 135`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.08612, + "consumed": 0.66666, "initial": 0.05, "isEstimated": false, - "remaining": 0.91388, + "remaining": 0.33334, }, - "sliValue": 0.995694, + "sliValue": 0.966667, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 63`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 136`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.0875, + "consumed": 0.66666, "initial": 0.05, "isEstimated": false, - "remaining": 0.9125, + "remaining": 0.33334, }, - "sliValue": 0.995625, + "sliValue": 0.966667, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 64`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 137`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.08888, + "consumed": 0.66666, "initial": 0.05, "isEstimated": false, - "remaining": 0.91112, + "remaining": 0.33334, }, - "sliValue": 0.995556, + "sliValue": 0.966667, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 65`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 138`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.09028, + "consumed": 0.66666, "initial": 0.05, "isEstimated": false, - "remaining": 0.90972, + "remaining": 0.33334, }, - "sliValue": 0.995486, + "sliValue": 0.966667, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 66`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 139`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.09166, + "consumed": 0.66666, "initial": 0.05, "isEstimated": false, - "remaining": 0.90834, + "remaining": 0.33334, }, - "sliValue": 0.995417, + "sliValue": 0.966667, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 67`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 140`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.09306, + "consumed": 0.66666, "initial": 0.05, "isEstimated": false, - "remaining": 0.90694, + "remaining": 0.33334, }, - "sliValue": 0.995347, + "sliValue": 0.966667, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 68`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 141`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.09444, + "consumed": 0.66666, "initial": 0.05, "isEstimated": false, - "remaining": 0.90556, + "remaining": 0.33334, }, - "sliValue": 0.995278, + "sliValue": 0.966667, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 69`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 142`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.09584, + "consumed": 0.66666, "initial": 0.05, "isEstimated": false, - "remaining": 0.90416, + "remaining": 0.33334, }, - "sliValue": 0.995208, + "sliValue": 0.966667, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 70`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 143`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.09722, + "consumed": 0.66666, "initial": 0.05, "isEstimated": false, - "remaining": 0.90278, + "remaining": 0.33334, }, - "sliValue": 0.995139, + "sliValue": 0.966667, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 71`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 144`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.09862, + "consumed": 0.66666, "initial": 0.05, "isEstimated": false, - "remaining": 0.90138, + "remaining": 0.33334, }, - "sliValue": 0.995069, + "sliValue": 0.966667, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 72`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 145`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.1, + "consumed": 0.66666, "initial": 0.05, "isEstimated": false, - "remaining": 0.9, + "remaining": 0.33334, }, - "sliValue": 0.995, + "sliValue": 0.966667, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 73`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 146`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.10138, + "consumed": 0.66666, "initial": 0.05, "isEstimated": false, - "remaining": 0.89862, + "remaining": 0.33334, }, - "sliValue": 0.994931, + "sliValue": 0.966667, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 74`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 147`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.10278, + "consumed": 0.66666, "initial": 0.05, "isEstimated": false, - "remaining": 0.89722, + "remaining": 0.33334, }, - "sliValue": 0.994861, + "sliValue": 0.966667, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 75`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 148`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.10416, + "consumed": 0.66666, "initial": 0.05, "isEstimated": false, - "remaining": 0.89584, + "remaining": 0.33334, }, - "sliValue": 0.994792, + "sliValue": 0.966667, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 76`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 149`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.10556, + "consumed": 0.66666, "initial": 0.05, "isEstimated": false, - "remaining": 0.89444, + "remaining": 0.33334, }, - "sliValue": 0.994722, + "sliValue": 0.966667, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 77`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 150`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.10694, + "consumed": 0.66666, "initial": 0.05, "isEstimated": false, - "remaining": 0.89306, + "remaining": 0.33334, }, - "sliValue": 0.994653, + "sliValue": 0.966667, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 78`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 151`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.10834, + "consumed": 0.66666, "initial": 0.05, "isEstimated": false, - "remaining": 0.89166, + "remaining": 0.33334, }, - "sliValue": 0.994583, + "sliValue": 0.966667, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 79`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 152`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.10972, + "consumed": 0.66666, "initial": 0.05, "isEstimated": false, - "remaining": 0.89028, + "remaining": 0.33334, }, - "sliValue": 0.994514, + "sliValue": 0.966667, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 80`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 153`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.11112, + "consumed": 0.66666, "initial": 0.05, "isEstimated": false, - "remaining": 0.88888, + "remaining": 0.33334, }, - "sliValue": 0.994444, + "sliValue": 0.966667, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 81`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 154`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.1125, + "consumed": 0.66666, "initial": 0.05, "isEstimated": false, - "remaining": 0.8875, + "remaining": 0.33334, }, - "sliValue": 0.994375, + "sliValue": 0.966667, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 82`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 155`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.11388, + "consumed": 0.66666, "initial": 0.05, "isEstimated": false, - "remaining": 0.88612, + "remaining": 0.33334, }, - "sliValue": 0.994306, + "sliValue": 0.966667, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 83`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 156`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.11528, + "consumed": 0.66666, "initial": 0.05, "isEstimated": false, - "remaining": 0.88472, + "remaining": 0.33334, }, - "sliValue": 0.994236, + "sliValue": 0.966667, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 84`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 157`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.11666, + "consumed": 0.66666, "initial": 0.05, "isEstimated": false, - "remaining": 0.88334, + "remaining": 0.33334, }, - "sliValue": 0.994167, + "sliValue": 0.966667, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 85`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 158`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.11806, + "consumed": 0.66666, "initial": 0.05, "isEstimated": false, - "remaining": 0.88194, + "remaining": 0.33334, }, - "sliValue": 0.994097, + "sliValue": 0.966667, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 86`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 159`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.11944, + "consumed": 0.66666, "initial": 0.05, "isEstimated": false, - "remaining": 0.88056, + "remaining": 0.33334, }, - "sliValue": 0.994028, + "sliValue": 0.966667, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 87`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 160`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.12084, + "consumed": 0.66666, "initial": 0.05, "isEstimated": false, - "remaining": 0.87916, + "remaining": 0.33334, }, - "sliValue": 0.993958, + "sliValue": 0.966667, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 88`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 161`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.12222, + "consumed": 0.66666, "initial": 0.05, "isEstimated": false, - "remaining": 0.87778, + "remaining": 0.33334, }, - "sliValue": 0.993889, + "sliValue": 0.966667, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 89`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 162`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.12362, + "consumed": 0.66666, "initial": 0.05, "isEstimated": false, - "remaining": 0.87638, + "remaining": 0.33334, }, - "sliValue": 0.993819, + "sliValue": 0.966667, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 90`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 163`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.125, + "consumed": 0.66666, "initial": 0.05, "isEstimated": false, - "remaining": 0.875, + "remaining": 0.33334, }, - "sliValue": 0.99375, + "sliValue": 0.966667, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 164`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.66666, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.33334, + }, + "sliValue": 0.966667, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 165`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.66666, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.33334, + }, + "sliValue": 0.966667, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 166`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.66666, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.33334, + }, + "sliValue": 0.966667, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 167`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.66666, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.33334, + }, + "sliValue": 0.966667, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 168`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.66666, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.33334, + }, + "sliValue": 0.966667, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 169`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.66666, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.33334, + }, + "sliValue": 0.966667, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 170`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.66666, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.33334, + }, + "sliValue": 0.966667, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 171`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.66666, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.33334, + }, + "sliValue": 0.966667, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 172`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.66666, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.33334, + }, + "sliValue": 0.966667, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 173`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.66666, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.33334, + }, + "sliValue": 0.966667, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 174`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.66666, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.33334, + }, + "sliValue": 0.966667, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 175`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.66666, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.33334, + }, + "sliValue": 0.966667, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 176`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.66666, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.33334, + }, + "sliValue": 0.966667, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 177`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.66666, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.33334, + }, + "sliValue": 0.966667, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 178`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.66666, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.33334, + }, + "sliValue": 0.966667, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 179`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.66666, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.33334, + }, + "sliValue": 0.966667, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the SLO timeWindow date range 180`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.66666, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.33334, + }, + "sliValue": 0.966667, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 1`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.56574, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.43426, + }, + "sliValue": 0.971713, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 2`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.56666, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.43334, + }, + "sliValue": 0.971667, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 3`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.5676, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.4324, + }, + "sliValue": 0.97162, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 4`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.56852, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.43148, + }, + "sliValue": 0.971574, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 5`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.56944, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.43056, + }, + "sliValue": 0.971528, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 6`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.57038, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.42962, + }, + "sliValue": 0.971481, + "status": "HEALTHY", +} +`; + +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 7`] = ` +Object { + "date": Any, + "errorBudget": Object { + "consumed": 0.5713, + "initial": 0.05, + "isEstimated": false, + "remaining": 0.4287, + }, + "sliValue": 0.971435, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 91`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 8`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.12638, + "consumed": 0.57222, "initial": 0.05, "isEstimated": false, - "remaining": 0.87362, + "remaining": 0.42778, }, - "sliValue": 0.993681, + "sliValue": 0.971389, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 92`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 9`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.12778, + "consumed": 0.57314, "initial": 0.05, "isEstimated": false, - "remaining": 0.87222, + "remaining": 0.42686, }, - "sliValue": 0.993611, + "sliValue": 0.971343, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 93`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 10`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.12916, + "consumed": 0.57408, "initial": 0.05, "isEstimated": false, - "remaining": 0.87084, + "remaining": 0.42592, }, - "sliValue": 0.993542, + "sliValue": 0.971296, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 94`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 11`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.13056, + "consumed": 0.575, "initial": 0.05, "isEstimated": false, - "remaining": 0.86944, + "remaining": 0.425, }, - "sliValue": 0.993472, + "sliValue": 0.97125, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 95`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 12`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.13194, + "consumed": 0.57592, "initial": 0.05, "isEstimated": false, - "remaining": 0.86806, + "remaining": 0.42408, }, - "sliValue": 0.993403, + "sliValue": 0.971204, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 96`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 13`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.13334, + "consumed": 0.57686, "initial": 0.05, "isEstimated": false, - "remaining": 0.86666, + "remaining": 0.42314, }, - "sliValue": 0.993333, + "sliValue": 0.971157, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 97`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 14`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.13472, + "consumed": 0.57778, "initial": 0.05, "isEstimated": false, - "remaining": 0.86528, + "remaining": 0.42222, }, - "sliValue": 0.993264, + "sliValue": 0.971111, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 98`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 15`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.13612, + "consumed": 0.5787, "initial": 0.05, "isEstimated": false, - "remaining": 0.86388, + "remaining": 0.4213, }, - "sliValue": 0.993194, + "sliValue": 0.971065, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 99`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 16`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.1375, + "consumed": 0.57962, "initial": 0.05, "isEstimated": false, - "remaining": 0.8625, + "remaining": 0.42038, }, - "sliValue": 0.993125, + "sliValue": 0.971019, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 100`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 17`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.13888, + "consumed": 0.58056, "initial": 0.05, "isEstimated": false, - "remaining": 0.86112, + "remaining": 0.41944, }, - "sliValue": 0.993056, + "sliValue": 0.970972, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 101`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 18`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.14028, + "consumed": 0.58148, "initial": 0.05, "isEstimated": false, - "remaining": 0.85972, + "remaining": 0.41852, }, - "sliValue": 0.992986, + "sliValue": 0.970926, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 102`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 19`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.14166, + "consumed": 0.5824, "initial": 0.05, "isEstimated": false, - "remaining": 0.85834, + "remaining": 0.4176, }, - "sliValue": 0.992917, + "sliValue": 0.97088, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 103`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 20`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.14306, + "consumed": 0.58334, "initial": 0.05, "isEstimated": false, - "remaining": 0.85694, + "remaining": 0.41666, }, - "sliValue": 0.992847, + "sliValue": 0.970833, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 104`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 21`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.14444, + "consumed": 0.58426, "initial": 0.05, "isEstimated": false, - "remaining": 0.85556, + "remaining": 0.41574, }, - "sliValue": 0.992778, + "sliValue": 0.970787, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 105`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 22`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.14584, + "consumed": 0.58518, "initial": 0.05, "isEstimated": false, - "remaining": 0.85416, + "remaining": 0.41482, }, - "sliValue": 0.992708, + "sliValue": 0.970741, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 106`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 23`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.14722, + "consumed": 0.58612, "initial": 0.05, "isEstimated": false, - "remaining": 0.85278, + "remaining": 0.41388, }, - "sliValue": 0.992639, + "sliValue": 0.970694, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 107`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 24`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.14862, + "consumed": 0.58704, "initial": 0.05, "isEstimated": false, - "remaining": 0.85138, + "remaining": 0.41296, }, - "sliValue": 0.992569, + "sliValue": 0.970648, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 108`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 25`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.15, + "consumed": 0.58796, "initial": 0.05, "isEstimated": false, - "remaining": 0.85, + "remaining": 0.41204, }, - "sliValue": 0.9925, + "sliValue": 0.970602, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 109`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 26`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.15138, + "consumed": 0.58888, "initial": 0.05, "isEstimated": false, - "remaining": 0.84862, + "remaining": 0.41112, }, - "sliValue": 0.992431, + "sliValue": 0.970556, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 110`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 27`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.15278, + "consumed": 0.58982, "initial": 0.05, "isEstimated": false, - "remaining": 0.84722, + "remaining": 0.41018, }, - "sliValue": 0.992361, + "sliValue": 0.970509, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 111`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 28`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.15416, + "consumed": 0.59074, "initial": 0.05, "isEstimated": false, - "remaining": 0.84584, + "remaining": 0.40926, }, - "sliValue": 0.992292, + "sliValue": 0.970463, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 112`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 29`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.15556, + "consumed": 0.59166, "initial": 0.05, "isEstimated": false, - "remaining": 0.84444, + "remaining": 0.40834, }, - "sliValue": 0.992222, + "sliValue": 0.970417, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 113`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 30`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.15694, + "consumed": 0.5926, "initial": 0.05, "isEstimated": false, - "remaining": 0.84306, + "remaining": 0.4074, }, - "sliValue": 0.992153, + "sliValue": 0.97037, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 114`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 31`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.15834, + "consumed": 0.59352, "initial": 0.05, "isEstimated": false, - "remaining": 0.84166, + "remaining": 0.40648, }, - "sliValue": 0.992083, + "sliValue": 0.970324, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 115`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 32`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.15972, + "consumed": 0.59444, "initial": 0.05, "isEstimated": false, - "remaining": 0.84028, + "remaining": 0.40556, }, - "sliValue": 0.992014, + "sliValue": 0.970278, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 116`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 33`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.16112, + "consumed": 0.59538, "initial": 0.05, "isEstimated": false, - "remaining": 0.83888, + "remaining": 0.40462, }, - "sliValue": 0.991944, + "sliValue": 0.970231, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 117`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 34`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.1625, + "consumed": 0.5963, "initial": 0.05, "isEstimated": false, - "remaining": 0.8375, + "remaining": 0.4037, }, - "sliValue": 0.991875, + "sliValue": 0.970185, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 118`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 35`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.16388, + "consumed": 0.59722, "initial": 0.05, "isEstimated": false, - "remaining": 0.83612, + "remaining": 0.40278, }, - "sliValue": 0.991806, + "sliValue": 0.970139, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 119`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 36`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.16528, + "consumed": 0.59814, "initial": 0.05, "isEstimated": false, - "remaining": 0.83472, + "remaining": 0.40186, }, - "sliValue": 0.991736, + "sliValue": 0.970093, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 120`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 37`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.16666, + "consumed": 0.59908, "initial": 0.05, "isEstimated": false, - "remaining": 0.83334, + "remaining": 0.40092, }, - "sliValue": 0.991667, + "sliValue": 0.970046, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 121`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 38`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.16806, + "consumed": 0.6, "initial": 0.05, "isEstimated": false, - "remaining": 0.83194, + "remaining": 0.4, }, - "sliValue": 0.991597, + "sliValue": 0.97, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 122`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 39`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.16944, + "consumed": 0.60092, "initial": 0.05, "isEstimated": false, - "remaining": 0.83056, + "remaining": 0.39908, }, - "sliValue": 0.991528, + "sliValue": 0.969954, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 123`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 40`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.17084, + "consumed": 0.60186, "initial": 0.05, "isEstimated": false, - "remaining": 0.82916, + "remaining": 0.39814, }, - "sliValue": 0.991458, + "sliValue": 0.969907, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 124`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 41`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.17222, + "consumed": 0.60278, "initial": 0.05, "isEstimated": false, - "remaining": 0.82778, + "remaining": 0.39722, }, - "sliValue": 0.991389, + "sliValue": 0.969861, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 125`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 42`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.17362, + "consumed": 0.6037, "initial": 0.05, "isEstimated": false, - "remaining": 0.82638, + "remaining": 0.3963, }, - "sliValue": 0.991319, + "sliValue": 0.969815, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 126`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 43`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.175, + "consumed": 0.60462, "initial": 0.05, "isEstimated": false, - "remaining": 0.825, + "remaining": 0.39538, }, - "sliValue": 0.99125, + "sliValue": 0.969769, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 127`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 44`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.17638, + "consumed": 0.60556, "initial": 0.05, "isEstimated": false, - "remaining": 0.82362, + "remaining": 0.39444, }, - "sliValue": 0.991181, + "sliValue": 0.969722, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 128`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 45`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.17778, + "consumed": 0.60648, "initial": 0.05, "isEstimated": false, - "remaining": 0.82222, + "remaining": 0.39352, }, - "sliValue": 0.991111, + "sliValue": 0.969676, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 129`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 46`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.17916, + "consumed": 0.6074, "initial": 0.05, "isEstimated": false, - "remaining": 0.82084, + "remaining": 0.3926, }, - "sliValue": 0.991042, + "sliValue": 0.96963, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 130`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 47`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.18056, + "consumed": 0.60834, "initial": 0.05, "isEstimated": false, - "remaining": 0.81944, + "remaining": 0.39166, }, - "sliValue": 0.990972, + "sliValue": 0.969583, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 131`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 48`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.18194, + "consumed": 0.60926, "initial": 0.05, "isEstimated": false, - "remaining": 0.81806, + "remaining": 0.39074, }, - "sliValue": 0.990903, + "sliValue": 0.969537, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 132`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 49`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.18334, + "consumed": 0.61018, "initial": 0.05, "isEstimated": false, - "remaining": 0.81666, + "remaining": 0.38982, }, - "sliValue": 0.990833, + "sliValue": 0.969491, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 133`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 50`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.18472, + "consumed": 0.61112, "initial": 0.05, "isEstimated": false, - "remaining": 0.81528, + "remaining": 0.38888, }, - "sliValue": 0.990764, + "sliValue": 0.969444, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 134`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 51`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.18612, + "consumed": 0.61204, "initial": 0.05, "isEstimated": false, - "remaining": 0.81388, + "remaining": 0.38796, }, - "sliValue": 0.990694, + "sliValue": 0.969398, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 135`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 52`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.1875, + "consumed": 0.61296, "initial": 0.05, "isEstimated": false, - "remaining": 0.8125, + "remaining": 0.38704, }, - "sliValue": 0.990625, + "sliValue": 0.969352, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 136`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 53`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.18888, + "consumed": 0.61388, "initial": 0.05, "isEstimated": false, - "remaining": 0.81112, + "remaining": 0.38612, }, - "sliValue": 0.990556, + "sliValue": 0.969306, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 137`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 54`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.19028, + "consumed": 0.61482, "initial": 0.05, "isEstimated": false, - "remaining": 0.80972, + "remaining": 0.38518, }, - "sliValue": 0.990486, + "sliValue": 0.969259, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 138`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 55`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.19166, + "consumed": 0.61574, "initial": 0.05, "isEstimated": false, - "remaining": 0.80834, + "remaining": 0.38426, }, - "sliValue": 0.990417, + "sliValue": 0.969213, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 139`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 56`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.19306, + "consumed": 0.61666, "initial": 0.05, "isEstimated": false, - "remaining": 0.80694, + "remaining": 0.38334, }, - "sliValue": 0.990347, + "sliValue": 0.969167, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 140`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 57`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.19444, + "consumed": 0.6176, "initial": 0.05, "isEstimated": false, - "remaining": 0.80556, + "remaining": 0.3824, }, - "sliValue": 0.990278, + "sliValue": 0.96912, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 141`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 58`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.19584, + "consumed": 0.61852, "initial": 0.05, "isEstimated": false, - "remaining": 0.80416, + "remaining": 0.38148, }, - "sliValue": 0.990208, + "sliValue": 0.969074, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 142`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 59`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.19722, + "consumed": 0.61944, "initial": 0.05, "isEstimated": false, - "remaining": 0.80278, + "remaining": 0.38056, }, - "sliValue": 0.990139, + "sliValue": 0.969028, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 143`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 60`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.19862, + "consumed": 0.62038, "initial": 0.05, "isEstimated": false, - "remaining": 0.80138, + "remaining": 0.37962, }, - "sliValue": 0.990069, + "sliValue": 0.968981, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 144`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 61`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.2, + "consumed": 0.6213, "initial": 0.05, "isEstimated": false, - "remaining": 0.8, + "remaining": 0.3787, }, - "sliValue": 0.99, + "sliValue": 0.968935, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 145`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 62`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.20138, + "consumed": 0.62222, "initial": 0.05, "isEstimated": false, - "remaining": 0.79862, + "remaining": 0.37778, }, - "sliValue": 0.989931, + "sliValue": 0.968889, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 146`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 63`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.20278, + "consumed": 0.62314, "initial": 0.05, "isEstimated": false, - "remaining": 0.79722, + "remaining": 0.37686, }, - "sliValue": 0.989861, + "sliValue": 0.968843, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 147`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 64`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.20416, + "consumed": 0.62408, "initial": 0.05, "isEstimated": false, - "remaining": 0.79584, + "remaining": 0.37592, }, - "sliValue": 0.989792, + "sliValue": 0.968796, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 148`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 65`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.20556, + "consumed": 0.625, "initial": 0.05, "isEstimated": false, - "remaining": 0.79444, + "remaining": 0.375, }, - "sliValue": 0.989722, + "sliValue": 0.96875, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 149`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 66`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.20694, + "consumed": 0.62592, "initial": 0.05, "isEstimated": false, - "remaining": 0.79306, + "remaining": 0.37408, }, - "sliValue": 0.989653, + "sliValue": 0.968704, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 150`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 67`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.20834, + "consumed": 0.62686, "initial": 0.05, "isEstimated": false, - "remaining": 0.79166, + "remaining": 0.37314, }, - "sliValue": 0.989583, + "sliValue": 0.968657, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 151`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 68`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.20972, + "consumed": 0.62778, "initial": 0.05, "isEstimated": false, - "remaining": 0.79028, + "remaining": 0.37222, }, - "sliValue": 0.989514, + "sliValue": 0.968611, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 152`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 69`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.21112, + "consumed": 0.6287, "initial": 0.05, "isEstimated": false, - "remaining": 0.78888, + "remaining": 0.3713, }, - "sliValue": 0.989444, + "sliValue": 0.968565, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 153`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 70`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.2125, + "consumed": 0.62962, "initial": 0.05, "isEstimated": false, - "remaining": 0.7875, + "remaining": 0.37038, }, - "sliValue": 0.989375, + "sliValue": 0.968519, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 154`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 71`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.21388, + "consumed": 0.63056, "initial": 0.05, "isEstimated": false, - "remaining": 0.78612, + "remaining": 0.36944, }, - "sliValue": 0.989306, + "sliValue": 0.968472, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 155`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 72`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.21528, + "consumed": 0.63148, "initial": 0.05, "isEstimated": false, - "remaining": 0.78472, + "remaining": 0.36852, }, - "sliValue": 0.989236, + "sliValue": 0.968426, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 156`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 73`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.21666, + "consumed": 0.6324, "initial": 0.05, "isEstimated": false, - "remaining": 0.78334, + "remaining": 0.3676, }, - "sliValue": 0.989167, + "sliValue": 0.96838, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 157`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 74`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.21806, + "consumed": 0.63334, "initial": 0.05, "isEstimated": false, - "remaining": 0.78194, + "remaining": 0.36666, }, - "sliValue": 0.989097, + "sliValue": 0.968333, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 158`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 75`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.21944, + "consumed": 0.63426, "initial": 0.05, "isEstimated": false, - "remaining": 0.78056, + "remaining": 0.36574, }, - "sliValue": 0.989028, + "sliValue": 0.968287, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 159`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 76`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.22084, + "consumed": 0.63518, "initial": 0.05, "isEstimated": false, - "remaining": 0.77916, + "remaining": 0.36482, }, - "sliValue": 0.988958, + "sliValue": 0.968241, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 160`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 77`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.22222, + "consumed": 0.63612, "initial": 0.05, "isEstimated": false, - "remaining": 0.77778, + "remaining": 0.36388, }, - "sliValue": 0.988889, + "sliValue": 0.968194, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 161`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 78`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.22362, + "consumed": 0.63704, "initial": 0.05, "isEstimated": false, - "remaining": 0.77638, + "remaining": 0.36296, }, - "sliValue": 0.988819, + "sliValue": 0.968148, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 162`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 79`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.225, + "consumed": 0.63796, "initial": 0.05, "isEstimated": false, - "remaining": 0.775, + "remaining": 0.36204, }, - "sliValue": 0.98875, + "sliValue": 0.968102, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 163`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 80`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.22638, + "consumed": 0.63888, "initial": 0.05, "isEstimated": false, - "remaining": 0.77362, + "remaining": 0.36112, }, - "sliValue": 0.988681, + "sliValue": 0.968056, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 164`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 81`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.22778, + "consumed": 0.63982, "initial": 0.05, "isEstimated": false, - "remaining": 0.77222, + "remaining": 0.36018, }, - "sliValue": 0.988611, + "sliValue": 0.968009, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 165`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 82`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.22916, + "consumed": 0.64074, "initial": 0.05, "isEstimated": false, - "remaining": 0.77084, + "remaining": 0.35926, }, - "sliValue": 0.988542, + "sliValue": 0.967963, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 166`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 83`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.23056, + "consumed": 0.64166, "initial": 0.05, "isEstimated": false, - "remaining": 0.76944, + "remaining": 0.35834, }, - "sliValue": 0.988472, + "sliValue": 0.967917, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 167`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 84`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.23194, + "consumed": 0.6426, "initial": 0.05, "isEstimated": false, - "remaining": 0.76806, + "remaining": 0.3574, }, - "sliValue": 0.988403, + "sliValue": 0.96787, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 168`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 85`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.23334, + "consumed": 0.64352, "initial": 0.05, "isEstimated": false, - "remaining": 0.76666, + "remaining": 0.35648, }, - "sliValue": 0.988333, + "sliValue": 0.967824, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 169`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 86`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.23472, + "consumed": 0.64444, "initial": 0.05, "isEstimated": false, - "remaining": 0.76528, + "remaining": 0.35556, }, - "sliValue": 0.988264, + "sliValue": 0.967778, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 170`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 87`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.23612, + "consumed": 0.64538, "initial": 0.05, "isEstimated": false, - "remaining": 0.76388, + "remaining": 0.35462, }, - "sliValue": 0.988194, + "sliValue": 0.967731, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 171`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 88`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.2375, + "consumed": 0.6463, "initial": 0.05, "isEstimated": false, - "remaining": 0.7625, + "remaining": 0.3537, }, - "sliValue": 0.988125, + "sliValue": 0.967685, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 172`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 89`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.23888, + "consumed": 0.64722, "initial": 0.05, "isEstimated": false, - "remaining": 0.76112, + "remaining": 0.35278, }, - "sliValue": 0.988056, + "sliValue": 0.967639, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 173`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 90`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.24028, + "consumed": 0.64814, "initial": 0.05, "isEstimated": false, - "remaining": 0.75972, + "remaining": 0.35186, }, - "sliValue": 0.987986, + "sliValue": 0.967593, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 174`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 91`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.24166, + "consumed": 0.64908, "initial": 0.05, "isEstimated": false, - "remaining": 0.75834, + "remaining": 0.35092, }, - "sliValue": 0.987917, + "sliValue": 0.967546, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 175`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 92`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.24306, + "consumed": 0.65, "initial": 0.05, "isEstimated": false, - "remaining": 0.75694, + "remaining": 0.35, }, - "sliValue": 0.987847, + "sliValue": 0.9675, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 176`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 93`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.24444, + "consumed": 0.65092, "initial": 0.05, "isEstimated": false, - "remaining": 0.75556, + "remaining": 0.34908, }, - "sliValue": 0.987778, + "sliValue": 0.967454, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 177`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 94`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.24584, + "consumed": 0.65186, "initial": 0.05, "isEstimated": false, - "remaining": 0.75416, + "remaining": 0.34814, }, - "sliValue": 0.987708, + "sliValue": 0.967407, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 178`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 95`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.24722, + "consumed": 0.65278, "initial": 0.05, "isEstimated": false, - "remaining": 0.75278, + "remaining": 0.34722, }, - "sliValue": 0.987639, + "sliValue": 0.967361, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 179`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 96`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.24862, + "consumed": 0.6537, "initial": 0.05, "isEstimated": false, - "remaining": 0.75138, + "remaining": 0.3463, }, - "sliValue": 0.987569, + "sliValue": 0.967315, "status": "HEALTHY", } `; -exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary 180`] = ` +exports[`FetchHistoricalSummary Rolling and Timeslices SLOs returns the summary using the provided date range 97`] = ` Object { "date": Any, "errorBudget": Object { - "consumed": 0.25, + "consumed": 0.65462, "initial": 0.05, "isEstimated": false, - "remaining": 0.75, + "remaining": 0.34538, }, - "sliValue": 0.9875, + "sliValue": 0.967269, "status": "HEALTHY", } `; diff --git a/x-pack/plugins/observability_solution/slo/server/services/burn_rates_client.ts b/x-pack/plugins/observability_solution/slo/server/services/burn_rates_client.ts index ebcf04538886b..08b1c460bdf2b 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/burn_rates_client.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/burn_rates_client.ts @@ -19,7 +19,6 @@ import { occurrencesBudgetingMethodSchema, timeslicesBudgetingMethodSchema, } from '@kbn/slo-schema'; -import { getEsDateRange } from './historical_summary_client'; import { SLO_DESTINATION_INDEX_PATTERN } from '../../common/constants'; import { DateRange, Duration, SLODefinition } from '../domain/models'; import { computeBurnRate, computeSLI } from '../domain/services'; @@ -99,7 +98,7 @@ function commonQuery( { term: { 'slo.revision': slo.revision } }, { range: { - '@timestamp': getEsDateRange(dateRange), + '@timestamp': { gte: dateRange.from.toISOString(), lt: dateRange.to.toISOString() }, }, }, ]; diff --git a/x-pack/plugins/observability_solution/slo/server/services/fetch_historical_summary.ts b/x-pack/plugins/observability_solution/slo/server/services/fetch_historical_summary.ts deleted file mode 100644 index 480231a6838fe..0000000000000 --- a/x-pack/plugins/observability_solution/slo/server/services/fetch_historical_summary.ts +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { - FetchHistoricalSummaryParams, - FetchHistoricalSummaryResponse, - fetchHistoricalSummaryResponseSchema, -} from '@kbn/slo-schema'; -import { HistoricalSummaryClient } from './historical_summary_client'; - -export class FetchHistoricalSummary { - constructor(private historicalSummaryClient: HistoricalSummaryClient) {} - - public async execute( - params: FetchHistoricalSummaryParams - ): Promise { - const historicalSummary = await this.historicalSummaryClient.fetch(params); - - return fetchHistoricalSummaryResponseSchema.encode(historicalSummary); - } -} diff --git a/x-pack/plugins/observability_solution/slo/server/services/get_preview_data.ts b/x-pack/plugins/observability_solution/slo/server/services/get_preview_data.ts index e927a9758e375..06d740aca3508 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/get_preview_data.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/get_preview_data.ts @@ -592,20 +592,19 @@ export class GetPreviewData { // Timeslice metric so that the chart is as close to the evaluation as possible. // Otherwise due to how the statistics work, the values might not look like // they've breached the threshold. + const rangeDuration = moment(params.range.to).diff(params.range.from, 'ms'); const bucketSize = params.indicator.type === 'sli.metric.timeslice' && - params.range.end - params.range.start <= 86_400_000 && + rangeDuration <= 86_400_000 && params.objective?.timesliceWindow ? params.objective.timesliceWindow.asMinutes() : Math.max( - calculateAuto - .near(100, moment.duration(params.range.end - params.range.start, 'ms')) - ?.asMinutes() ?? 0, + calculateAuto.near(100, moment.duration(rangeDuration, 'ms'))?.asMinutes() ?? 0, 1 ); const options: Options = { instanceId: params.instanceId, - range: params.range, + range: { start: params.range.from.getTime(), end: params.range.to.getTime() }, groupBy: params.groupBy, remoteName: params.remoteName, groupings: params.groupings, diff --git a/x-pack/plugins/observability_solution/slo/server/services/historical_summary_client.test.ts b/x-pack/plugins/observability_solution/slo/server/services/historical_summary_client.test.ts index ee49c439fb5b7..939b240f5d88f 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/historical_summary_client.test.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/historical_summary_client.test.ts @@ -8,7 +8,8 @@ import { ElasticsearchClientMock, elasticsearchServiceMock } from '@kbn/core/server/mocks'; import { ALL_VALUE } from '@kbn/slo-schema'; import moment from 'moment'; -import { oneMinute, oneMonth, thirtyDays } from './fixtures/duration'; +import { DateRange, SLODefinition } from '../domain/models'; +import { oneMinute, oneMonth, sevenDays, thirtyDays } from './fixtures/duration'; import { createSLO } from './fixtures/slo'; import { DefaultHistoricalSummaryClient, @@ -29,16 +30,33 @@ const commonEsResponse = { }, }; -const generateEsResponseForRollingSLO = ( - rollingDays: number = 30, - good: number = 97, - total: number = 100 -) => { - const { fixedInterval, bucketsPerDay } = getFixedIntervalAndBucketsPerDay(rollingDays); - const numberOfBuckets = rollingDays * bucketsPerDay; - const doubleDuration = rollingDays * 2; - const startDay = moment.utc().subtract(doubleDuration, 'day').startOf('day'); - const bucketSize = fixedInterval === '1d' ? 24 : Number(fixedInterval.slice(0, -1)); +const MINUTES_IN_DAY = 1440; + +const generateEsResponseForRollingSLO = (slo: SLODefinition, overridedRange?: DateRange) => { + const rollingDurationInDays = slo.timeWindow.duration.asMinutes() / MINUTES_IN_DAY; + const timesliceInMin = slo.objective.timesliceWindow?.asMinutes(); + const overridedRangeInDays = overridedRange + ? moment(overridedRange.to).diff(moment(overridedRange.from), 'days') + : 0; + + const { fixedInterval, bucketsPerDay } = getFixedIntervalAndBucketsPerDay( + overridedRangeInDays ? overridedRangeInDays : rollingDurationInDays + ); + const fullDuration = overridedRange + ? rollingDurationInDays + overridedRangeInDays + : rollingDurationInDays * 2; + const numberOfBuckets = fullDuration * bucketsPerDay; + const startDay = moment().subtract(fullDuration, 'day').startOf('day'); + const bucketSizeInHour = moment + .duration( + fixedInterval.slice(0, -1), + fixedInterval.slice(-1) as moment.unitOfTime.DurationConstructor + ) + .asHours(); + + const good = timesliceInMin ? Math.floor(((bucketSizeInHour * 60) / timesliceInMin) * 0.97) : 97; + const total = timesliceInMin ? Math.floor((bucketSizeInHour * 60) / timesliceInMin) : 100; + return { ...commonEsResponse, responses: [ @@ -51,11 +69,11 @@ const generateEsResponseForRollingSLO = ( .map((_, index) => ({ key_as_string: startDay .clone() - .add(index * bucketSize, 'hours') + .add(index * bucketSizeInHour, 'hours') .toISOString(), key: startDay .clone() - .add(index * bucketSize, 'hours') + .add(index * bucketSizeInHour, 'hours') .format('x'), doc_count: 1440, total: { @@ -65,10 +83,16 @@ const generateEsResponseForRollingSLO = ( value: good, }, cumulative_good: { - value: good * (index + 1), + value: + index < rollingDurationInDays * bucketsPerDay + ? good * (index + 1) + : good * rollingDurationInDays * bucketsPerDay, }, cumulative_total: { - value: total * (index + 1), + value: + index < rollingDurationInDays * bucketsPerDay + ? total * (index + 1) + : total * rollingDurationInDays * bucketsPerDay, }, })), }, @@ -137,13 +161,13 @@ describe('FetchHistoricalSummary', () => { }); describe('Rolling and Occurrences SLOs', () => { - it('returns the summary', async () => { + it('returns the summary using the SLO timeWindow date range', async () => { const slo = createSLO({ timeWindow: { type: 'rolling', duration: thirtyDays() }, objective: { target: 0.95 }, groupBy: ALL_VALUE, }); - esClientMock.msearch.mockResolvedValueOnce(generateEsResponseForRollingSLO(30)); + esClientMock.msearch.mockResolvedValueOnce(generateEsResponseForRollingSLO(slo)); const client = new DefaultHistoricalSummaryClient(esClientMock); const results = await client.fetch({ @@ -163,20 +187,52 @@ describe('FetchHistoricalSummary', () => { results[0].data.forEach((dailyResult) => expect(dailyResult).toMatchSnapshot({ date: expect.any(Date) }) ); + }); - expect(results[0].data).toHaveLength(180); + it('returns the summary using the provided date range', async () => { + const slo = createSLO({ + timeWindow: { type: 'rolling', duration: sevenDays() }, + objective: { target: 0.9 }, + groupBy: ALL_VALUE, + }); + const range: DateRange = { + from: new Date('2023-01-09T15:00:00.000Z'), + to: new Date('2023-01-13T15:00:00.000Z'), + }; + + esClientMock.msearch.mockResolvedValueOnce(generateEsResponseForRollingSLO(slo, range)); + const client = new DefaultHistoricalSummaryClient(esClientMock); + + const results = await client.fetch({ + list: [ + { + timeWindow: slo.timeWindow, + groupBy: slo.groupBy, + budgetingMethod: slo.budgetingMethod, + objective: slo.objective, + revision: slo.revision, + sloId: slo.id, + instanceId: ALL_VALUE, + range, + }, + ], + }); + + results[0].data.forEach((dailyResult) => + expect(dailyResult).toMatchSnapshot({ date: expect.any(Date) }) + ); }); }); describe('Rolling and Timeslices SLOs', () => { - it('returns the summary', async () => { + it('returns the summary using the SLO timeWindow date range', async () => { const slo = createSLO({ timeWindow: { type: 'rolling', duration: thirtyDays() }, budgetingMethod: 'timeslices', objective: { target: 0.95, timesliceTarget: 0.9, timesliceWindow: oneMinute() }, groupBy: ALL_VALUE, }); - esClientMock.msearch.mockResolvedValueOnce(generateEsResponseForRollingSLO(30)); + esClientMock.msearch.mockResolvedValueOnce(generateEsResponseForRollingSLO(slo)); const client = new DefaultHistoricalSummaryClient(esClientMock); const results = await client.fetch({ @@ -198,6 +254,40 @@ describe('FetchHistoricalSummary', () => { ); expect(results[0].data).toHaveLength(180); }); + + it('returns the summary using the provided date range', async () => { + const slo = createSLO({ + timeWindow: { type: 'rolling', duration: thirtyDays() }, + budgetingMethod: 'timeslices', + objective: { target: 0.95, timesliceTarget: 0.9, timesliceWindow: oneMinute() }, + groupBy: ALL_VALUE, + }); + const range: DateRange = { + from: new Date('2023-01-09T15:00:00.000Z'), + to: new Date('2023-01-13T15:00:00.000Z'), + }; + esClientMock.msearch.mockResolvedValueOnce(generateEsResponseForRollingSLO(slo, range)); + const client = new DefaultHistoricalSummaryClient(esClientMock); + + const results = await client.fetch({ + list: [ + { + timeWindow: slo.timeWindow, + groupBy: slo.groupBy, + budgetingMethod: slo.budgetingMethod, + objective: slo.objective, + revision: slo.revision, + sloId: slo.id, + instanceId: ALL_VALUE, + range, + }, + ], + }); + + results[0].data.forEach((dailyResult) => + expect(dailyResult).toMatchSnapshot({ date: expect.any(Date) }) + ); + }); }); describe('Calendar Aligned and Timeslices SLOs', () => { @@ -275,7 +365,7 @@ describe('FetchHistoricalSummary', () => { objective: { target: 0.95 }, groupBy: 'host', }); - esClientMock.msearch.mockResolvedValueOnce(generateEsResponseForRollingSLO(30)); + esClientMock.msearch.mockResolvedValueOnce(generateEsResponseForRollingSLO(slo)); const client = new DefaultHistoricalSummaryClient(esClientMock); const results = await client.fetch({ diff --git a/x-pack/plugins/observability_solution/slo/server/services/historical_summary_client.ts b/x-pack/plugins/observability_solution/slo/server/services/historical_summary_client.ts index 6e07bb30c2cb6..263111c944da3 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/historical_summary_client.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/historical_summary_client.ts @@ -63,13 +63,12 @@ export class DefaultHistoricalSummaryClient implements HistoricalSummaryClient { constructor(private esClient: ElasticsearchClient) {} async fetch(params: FetchHistoricalSummaryParams): Promise { - const dateRangeBySlo = params.list.reduce>( - (acc, { sloId, timeWindow, range }) => { - acc[sloId] = range ?? getDateRange(timeWindow); - return acc; - }, - {} - ); + const dateRangeBySlo = params.list.reduce< + Record + >((acc, { sloId, timeWindow, range }) => { + acc[sloId] = getDateRange(timeWindow, range); + return acc; + }, {}); const searches = params.list.flatMap( ({ sloId, revision, budgetingMethod, instanceId, groupBy, timeWindow, remoteName }) => [ @@ -113,7 +112,12 @@ export class DefaultHistoricalSummaryClient implements HistoricalSummaryClient { historicalSummary.push({ sloId, instanceId, - data: handleResultForRollingAndTimeslices(objective, timeWindow, buckets), + data: handleResultForRollingAndTimeslices( + objective, + timeWindow, + buckets, + dateRangeBySlo[sloId] + ), }); continue; @@ -123,7 +127,7 @@ export class DefaultHistoricalSummaryClient implements HistoricalSummaryClient { historicalSummary.push({ sloId, instanceId, - data: handleResultForRollingAndOccurrences(objective, timeWindow, buckets), + data: handleResultForRollingAndOccurrences(objective, buckets, dateRangeBySlo[sloId]), }); continue; } @@ -187,10 +191,10 @@ function handleResultForCalendarAlignedAndOccurrences( function handleResultForCalendarAlignedAndTimeslices( objective: Objective, buckets: DailyAggBucket[], - dateRange: DateRange + dateRange: { range: DateRange; queryRange: DateRange } ): HistoricalSummary[] { const initialErrorBudget = 1 - objective.target; - const totalSlices = computeTotalSlicesFromDateRange(dateRange, objective.timesliceWindow!); + const totalSlices = computeTotalSlicesFromDateRange(dateRange.range, objective.timesliceWindow!); return buckets.map((bucket: DailyAggBucket): HistoricalSummary => { const good = bucket.cumulative_good?.value ?? 0; @@ -210,18 +214,17 @@ function handleResultForCalendarAlignedAndTimeslices( function handleResultForRollingAndOccurrences( objective: Objective, - timeWindow: TimeWindow, - buckets: DailyAggBucket[] + buckets: DailyAggBucket[], + dateRange: { range: DateRange; queryRange: DateRange } ): HistoricalSummary[] { const initialErrorBudget = 1 - objective.target; - const rollingWindowDurationInDays = moment - .duration(timeWindow.duration.value, toMomentUnitOfTime(timeWindow.duration.unit)) - .asDays(); - - const { bucketsPerDay } = getFixedIntervalAndBucketsPerDay(rollingWindowDurationInDays); return buckets - .slice(-bucketsPerDay * rollingWindowDurationInDays) + .filter( + (bucket) => + moment(bucket.key_as_string).isSameOrAfter(dateRange.range.from) && + moment(bucket.key_as_string).isSameOrBefore(dateRange.range.to) + ) .map((bucket: DailyAggBucket): HistoricalSummary => { const good = bucket.cumulative_good?.value ?? 0; const total = bucket.cumulative_total?.value ?? 0; @@ -242,20 +245,21 @@ function handleResultForRollingAndOccurrences( function handleResultForRollingAndTimeslices( objective: Objective, timeWindow: TimeWindow, - buckets: DailyAggBucket[] + buckets: DailyAggBucket[], + dateRange: { range: DateRange; queryRange: DateRange } ): HistoricalSummary[] { const initialErrorBudget = 1 - objective.target; - const rollingWindowDurationInDays = moment - .duration(timeWindow.duration.value, toMomentUnitOfTime(timeWindow.duration.unit)) - .asDays(); - const { bucketsPerDay } = getFixedIntervalAndBucketsPerDay(rollingWindowDurationInDays); const totalSlices = Math.ceil( timeWindow.duration.asSeconds() / objective.timesliceWindow!.asSeconds() ); return buckets - .slice(-bucketsPerDay * rollingWindowDurationInDays) + .filter( + (bucket) => + moment(bucket.key_as_string).isSameOrAfter(dateRange.range.from) && + moment(bucket.key_as_string).isSameOrBefore(dateRange.range.to) + ) .map((bucket: DailyAggBucket): HistoricalSummary => { const good = bucket.cumulative_good?.value ?? 0; const total = bucket.cumulative_total?.value ?? 0; @@ -272,13 +276,6 @@ function handleResultForRollingAndTimeslices( }); } -export const getEsDateRange = (dateRange: DateRange) => { - return { - gte: typeof dateRange.from === 'string' ? dateRange.from : dateRange.from.toISOString(), - lte: typeof dateRange.to === 'string' ? dateRange.to : dateRange.to.toISOString(), - }; -}; - function generateSearchQuery({ sloId, groupBy, @@ -292,15 +289,19 @@ function generateSearchQuery({ sloId: string; groupBy: GroupBy; revision: number; - dateRange: DateRange; + dateRange: { range: DateRange; queryRange: DateRange }; timeWindow: TimeWindow; budgetingMethod: BudgetingMethod; }): MsearchMultisearchBody { const unit = toMomentUnitOfTime(timeWindow.duration.unit); const timeWindowDurationInDays = moment.duration(timeWindow.duration.value, unit).asDays(); + const queryRangeDurationInDays = Math.ceil( + moment(dateRange.range.to).diff(dateRange.range.from, 'days') + ); + const { fixedInterval, bucketsPerDay } = - getFixedIntervalAndBucketsPerDay(timeWindowDurationInDays); + getFixedIntervalAndBucketsPerDay(queryRangeDurationInDays); const extraFilterByInstanceId = !!groupBy && ![groupBy].flat().includes(ALL_VALUE) && instanceId !== ALL_VALUE @@ -316,7 +317,10 @@ function generateSearchQuery({ { term: { 'slo.revision': revision } }, { range: { - '@timestamp': getEsDateRange(dateRange), + '@timestamp': { + gte: dateRange.queryRange.from.toISOString(), + lte: dateRange.queryRange.to.toISOString(), + }, }, }, ...extraFilterByInstanceId, @@ -329,8 +333,8 @@ function generateSearchQuery({ field: '@timestamp', fixed_interval: fixedInterval, extended_bounds: { - min: typeof dateRange.from === 'string' ? dateRange.from : dateRange.from.toISOString(), - max: 'now/d', + min: dateRange.queryRange.from.toISOString(), + max: dateRange.queryRange.to.toISOString(), }, }, aggs: { @@ -382,26 +386,62 @@ function generateSearchQuery({ }; } -function getDateRange(timeWindow: TimeWindow) { +/** + * queryRange is used for the filter range on the query, + * while range is used for storing the actual range requested + * For a rolling window, the query range starts 1 timeWindow duration before the actual range from. + * For calednar window, the query range is the same as the range. + * + * @param timeWindow + * @param range + * @returns the request {range} and the query range {queryRange} + * + */ +function getDateRange( + timeWindow: TimeWindow, + range?: DateRange +): { range: DateRange; queryRange: DateRange } { if (rollingTimeWindowSchema.is(timeWindow)) { const unit = toMomentUnitOfTime(timeWindow.duration.unit as DurationUnit); + + if (range) { + return { + range, + queryRange: { + from: moment(range.from) + .subtract(timeWindow.duration.value, unit) + .startOf('day') + .toDate(), + to: moment(range.to).startOf('minute').toDate(), + }, + }; + } + const now = moment(); return { - from: now - .clone() - .subtract(timeWindow.duration.value * 2, unit) - .startOf('day') - .toDate(), - to: now.startOf('minute').toDate(), + range: { + from: now.clone().subtract(timeWindow.duration.value, unit).startOf('day').toDate(), + to: now.clone().startOf('minute').toDate(), + }, + queryRange: { + from: now + .clone() + .subtract(timeWindow.duration.value * 2, unit) + .startOf('day') + .toDate(), + to: now.clone().startOf('minute').toDate(), + }, }; } + if (calendarAlignedTimeWindowSchema.is(timeWindow)) { const now = moment(); const unit = toCalendarAlignedTimeWindowMomentUnit(timeWindow); const from = moment.utc(now).startOf(unit); const to = moment.utc(now).endOf(unit); - return { from: from.toDate(), to: to.toDate() }; + const calendarRange = { from: from.toDate(), to: to.toDate() }; + return { range: calendarRange, queryRange: calendarRange }; } assertNever(timeWindow); @@ -411,6 +451,9 @@ export function getFixedIntervalAndBucketsPerDay(durationInDays: number): { fixedInterval: string; bucketsPerDay: number; } { + if (durationInDays <= 3) { + return { fixedInterval: '30m', bucketsPerDay: 48 }; + } if (durationInDays <= 7) { return { fixedInterval: '1h', bucketsPerDay: 24 }; } diff --git a/x-pack/plugins/observability_solution/slo/server/services/index.ts b/x-pack/plugins/observability_solution/slo/server/services/index.ts index 7f6e7683e582d..6c9bdc906914c 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/index.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/index.ts @@ -8,7 +8,6 @@ export * from './create_slo'; export * from './delete_slo'; export * from './delete_slo_instances'; -export * from './fetch_historical_summary'; export * from './find_slo'; export * from './get_slo'; export * from './historical_summary_client'; diff --git a/x-pack/plugins/observability_solution/slo/server/services/summary_client.ts b/x-pack/plugins/observability_solution/slo/server/services/summary_client.ts index 5e5ee5a7228a0..635dbdd654ead 100644 --- a/x-pack/plugins/observability_solution/slo/server/services/summary_client.ts +++ b/x-pack/plugins/observability_solution/slo/server/services/summary_client.ts @@ -16,7 +16,6 @@ import { occurrencesBudgetingMethodSchema, timeslicesBudgetingMethodSchema, } from '@kbn/slo-schema'; -import { getEsDateRange } from './historical_summary_client'; import { SLO_DESTINATION_INDEX_PATTERN } from '../../common/constants'; import { Groupings, Meta, SLODefinition, Summary } from '../domain/models'; import { computeSLI, computeSummaryStatus, toErrorBudget } from '../domain/services'; @@ -76,7 +75,10 @@ export class DefaultSummaryClient implements SummaryClient { { term: { 'slo.revision': slo.revision } }, { range: { - '@timestamp': getEsDateRange(dateRange), + '@timestamp': { + gte: dateRange.from.toISOString(), + lte: dateRange.to.toISOString(), + }, }, }, ...instanceIdFilter, diff --git a/x-pack/plugins/observability_solution/synthetics/e2e/synthetics/journeys/add_monitor.journey.ts b/x-pack/plugins/observability_solution/synthetics/e2e/synthetics/journeys/add_monitor.journey.ts index e18b5cac11e2f..6e317150907ca 100644 --- a/x-pack/plugins/observability_solution/synthetics/e2e/synthetics/journeys/add_monitor.journey.ts +++ b/x-pack/plugins/observability_solution/synthetics/e2e/synthetics/journeys/add_monitor.journey.ts @@ -6,7 +6,6 @@ */ import { v4 as uuidv4 } from 'uuid'; import { journey, step, expect, Page } from '@elastic/synthetics'; -import { recordVideo } from '../../helpers/record_video'; import { FormMonitorType } from '../../../common/runtime_types'; import { syntheticsAppPageProvider } from '../page_objects/synthetics_app'; @@ -147,10 +146,11 @@ const createMonitorJourney = ({ journey( `SyntheticsAddMonitor - ${monitorName}`, async ({ page, params }: { page: Page; params: any }) => { - page.setDefaultTimeout(60 * 1000); - recordVideo(page); - - const syntheticsApp = syntheticsAppPageProvider({ page, kibanaUrl: params.kibanaUrl }); + const syntheticsApp = syntheticsAppPageProvider({ + page, + kibanaUrl: params.kibanaUrl, + params, + }); step('Go to monitor management', async () => { await syntheticsApp.navigateToMonitorManagement(true); diff --git a/x-pack/plugins/observability_solution/synthetics/e2e/synthetics/journeys/alert_rules/default_status_alert.journey.ts b/x-pack/plugins/observability_solution/synthetics/e2e/synthetics/journeys/alert_rules/default_status_alert.journey.ts index 35b2bbbbef5f6..70327eb614ba7 100644 --- a/x-pack/plugins/observability_solution/synthetics/e2e/synthetics/journeys/alert_rules/default_status_alert.journey.ts +++ b/x-pack/plugins/observability_solution/synthetics/e2e/synthetics/journeys/alert_rules/default_status_alert.journey.ts @@ -10,15 +10,11 @@ import { byTestId } from '@kbn/ux-plugin/e2e/journeys/utils'; import { RetryService } from '@kbn/ftr-common-functional-services'; import { v4 as uuidv4 } from 'uuid'; import { getReasonMessage } from '../../../../server/alert_rules/status_rule/message_utils'; -import { recordVideo } from '../../../helpers/record_video'; import { syntheticsAppPageProvider } from '../../page_objects/synthetics_app'; import { SyntheticsServices } from '../services/synthetics_services'; journey(`DefaultStatusAlert`, async ({ page, params }) => { - recordVideo(page); - - page.setDefaultTimeout(60 * 1000); - const syntheticsApp = syntheticsAppPageProvider({ page, kibanaUrl: params.kibanaUrl }); + const syntheticsApp = syntheticsAppPageProvider({ page, kibanaUrl: params.kibanaUrl, params }); const services = new SyntheticsServices(params); diff --git a/x-pack/plugins/observability_solution/synthetics/e2e/synthetics/journeys/alerting_default.journey.ts b/x-pack/plugins/observability_solution/synthetics/e2e/synthetics/journeys/alerting_default.journey.ts index 96e91f81ff9fa..540a8e584cc5e 100644 --- a/x-pack/plugins/observability_solution/synthetics/e2e/synthetics/journeys/alerting_default.journey.ts +++ b/x-pack/plugins/observability_solution/synthetics/e2e/synthetics/journeys/alerting_default.journey.ts @@ -6,17 +6,12 @@ */ import { journey, step, expect, before, after } from '@elastic/synthetics'; -import { recordVideo } from '../../helpers/record_video'; import { byTestId } from '../../helpers/utils'; import { syntheticsAppPageProvider } from '../page_objects/synthetics_app'; import { cleanSettings } from './services/settings'; journey('AlertingDefaults', async ({ page, params }) => { - recordVideo(page); - - const syntheticsApp = syntheticsAppPageProvider({ page, kibanaUrl: params.kibanaUrl }); - - page.setDefaultTimeout(60 * 1000); + const syntheticsApp = syntheticsAppPageProvider({ page, kibanaUrl: params.kibanaUrl, params }); before(async () => { await cleanSettings(params); diff --git a/x-pack/plugins/observability_solution/synthetics/e2e/synthetics/journeys/data_retention.journey.ts b/x-pack/plugins/observability_solution/synthetics/e2e/synthetics/journeys/data_retention.journey.ts index 1e0c00f42a92f..7f7a395b09b36 100644 --- a/x-pack/plugins/observability_solution/synthetics/e2e/synthetics/journeys/data_retention.journey.ts +++ b/x-pack/plugins/observability_solution/synthetics/e2e/synthetics/journeys/data_retention.journey.ts @@ -13,9 +13,7 @@ import { byTestId, assertText } from '../../helpers/utils'; let page1: Page; journey(`DataRetentionPage`, async ({ page, params }) => { - page.setDefaultTimeout(60 * 1000); - recordVideo(page); - const syntheticsApp = syntheticsAppPageProvider({ page, kibanaUrl: params.kibanaUrl }); + const syntheticsApp = syntheticsAppPageProvider({ page, kibanaUrl: params.kibanaUrl, params }); const getService = params.getService; const retry: RetryService = getService('retry'); diff --git a/x-pack/plugins/observability_solution/synthetics/e2e/synthetics/journeys/detail_flyout.ts b/x-pack/plugins/observability_solution/synthetics/e2e/synthetics/journeys/detail_flyout.ts index 4204e68099042..037ad7bbb651a 100644 --- a/x-pack/plugins/observability_solution/synthetics/e2e/synthetics/journeys/detail_flyout.ts +++ b/x-pack/plugins/observability_solution/synthetics/e2e/synthetics/journeys/detail_flyout.ts @@ -6,13 +6,10 @@ */ import { expect, journey, step } from '@elastic/synthetics'; -import { recordVideo } from '../../helpers/record_video'; import { syntheticsAppPageProvider } from '../page_objects/synthetics_app'; journey('TestMonitorDetailFlyout', async ({ page, params }) => { - recordVideo(page); - - const syntheticsApp = syntheticsAppPageProvider({ page, kibanaUrl: params.kibanaUrl }); + const syntheticsApp = syntheticsAppPageProvider({ page, kibanaUrl: params.kibanaUrl, params }); const monitorName = 'test-flyout-http-monitor'; step('Go to monitor-management', async () => { diff --git a/x-pack/plugins/observability_solution/synthetics/e2e/synthetics/journeys/getting_started.journey.ts b/x-pack/plugins/observability_solution/synthetics/e2e/synthetics/journeys/getting_started.journey.ts index abb66db15d601..78261c08e4415 100644 --- a/x-pack/plugins/observability_solution/synthetics/e2e/synthetics/journeys/getting_started.journey.ts +++ b/x-pack/plugins/observability_solution/synthetics/e2e/synthetics/journeys/getting_started.journey.ts @@ -6,14 +6,11 @@ */ import { journey, step, expect, before, Page } from '@elastic/synthetics'; -import { recordVideo } from '../../helpers/record_video'; import { syntheticsAppPageProvider } from '../page_objects/synthetics_app'; import { cleanTestMonitors } from './services/add_monitor'; journey(`Getting Started Page`, async ({ page, params }: { page: Page; params: any }) => { - recordVideo(page); - - const syntheticsApp = syntheticsAppPageProvider({ page, kibanaUrl: params.kibanaUrl }); + const syntheticsApp = syntheticsAppPageProvider({ page, kibanaUrl: params.kibanaUrl, params }); const createBasicMonitor = async () => { await syntheticsApp.fillFirstMonitorDetails({ diff --git a/x-pack/plugins/observability_solution/synthetics/e2e/synthetics/journeys/global_parameters.journey.ts b/x-pack/plugins/observability_solution/synthetics/e2e/synthetics/journeys/global_parameters.journey.ts index d5581e51b1833..3ff9423180686 100644 --- a/x-pack/plugins/observability_solution/synthetics/e2e/synthetics/journeys/global_parameters.journey.ts +++ b/x-pack/plugins/observability_solution/synthetics/e2e/synthetics/journeys/global_parameters.journey.ts @@ -7,14 +7,11 @@ import { journey, step, before, after, expect } from '@elastic/synthetics'; import { byTestId } from '../../helpers/utils'; -import { recordVideo } from '../../helpers/record_video'; import { cleanTestParams } from './services/add_monitor'; import { syntheticsAppPageProvider } from '../page_objects/synthetics_app'; journey(`GlobalParameters`, async ({ page, params }) => { - recordVideo(page); - - const syntheticsApp = syntheticsAppPageProvider({ page, kibanaUrl: params.kibanaUrl }); + const syntheticsApp = syntheticsAppPageProvider({ page, kibanaUrl: params.kibanaUrl, params }); before(async () => { await cleanTestParams(params); diff --git a/x-pack/plugins/observability_solution/synthetics/e2e/synthetics/journeys/management_list.journey.ts b/x-pack/plugins/observability_solution/synthetics/e2e/synthetics/journeys/management_list.journey.ts index b3a4db77680e0..c81fe084194d5 100644 --- a/x-pack/plugins/observability_solution/synthetics/e2e/synthetics/journeys/management_list.journey.ts +++ b/x-pack/plugins/observability_solution/synthetics/e2e/synthetics/journeys/management_list.journey.ts @@ -7,7 +7,6 @@ import { journey, step, expect, before, after } from '@elastic/synthetics'; import { byTestId } from '../../helpers/utils'; -import { recordVideo } from '../../helpers/record_video'; import { addTestMonitor, cleanTestMonitors, @@ -16,9 +15,7 @@ import { import { syntheticsAppPageProvider } from '../page_objects/synthetics_app'; journey(`MonitorManagementList`, async ({ page, params }) => { - recordVideo(page); - - const syntheticsApp = syntheticsAppPageProvider({ page, kibanaUrl: params.kibanaUrl }); + const syntheticsApp = syntheticsAppPageProvider({ page, kibanaUrl: params.kibanaUrl, params }); const testMonitor1 = 'Test monitor 1'; const testMonitor2 = 'Test monitor 2'; const testMonitor3 = 'Test monitor 3'; diff --git a/x-pack/plugins/observability_solution/synthetics/e2e/synthetics/journeys/monitor_details_page/monitor_summary.journey.ts b/x-pack/plugins/observability_solution/synthetics/e2e/synthetics/journeys/monitor_details_page/monitor_summary.journey.ts index 34b4e0ca985f7..46fa7837ded99 100644 --- a/x-pack/plugins/observability_solution/synthetics/e2e/synthetics/journeys/monitor_details_page/monitor_summary.journey.ts +++ b/x-pack/plugins/observability_solution/synthetics/e2e/synthetics/journeys/monitor_details_page/monitor_summary.journey.ts @@ -9,15 +9,11 @@ import { journey, step, before, after, expect } from '@elastic/synthetics'; import { byTestId } from '@kbn/ux-plugin/e2e/journeys/utils'; import { RetryService } from '@kbn/ftr-common-functional-services'; import moment from 'moment'; -import { recordVideo } from '../../../helpers/record_video'; import { syntheticsAppPageProvider } from '../../page_objects/synthetics_app'; import { SyntheticsServices } from '../services/synthetics_services'; journey(`MonitorSummaryTab`, async ({ page, params }) => { - recordVideo(page); - - page.setDefaultTimeout(60 * 1000); - const syntheticsApp = syntheticsAppPageProvider({ page, kibanaUrl: params.kibanaUrl }); + const syntheticsApp = syntheticsAppPageProvider({ page, kibanaUrl: params.kibanaUrl, params }); const services = new SyntheticsServices(params); diff --git a/x-pack/plugins/observability_solution/synthetics/e2e/synthetics/journeys/monitor_form_validation.journey.ts b/x-pack/plugins/observability_solution/synthetics/e2e/synthetics/journeys/monitor_form_validation.journey.ts index c34ea3fa7c8cb..7fdce8d921055 100644 --- a/x-pack/plugins/observability_solution/synthetics/e2e/synthetics/journeys/monitor_form_validation.journey.ts +++ b/x-pack/plugins/observability_solution/synthetics/e2e/synthetics/journeys/monitor_form_validation.journey.ts @@ -6,7 +6,6 @@ */ import { expect, journey, Page, step } from '@elastic/synthetics'; import { FormMonitorType } from '../../../common/runtime_types'; -import { recordVideo } from '../../helpers/record_video'; import { syntheticsAppPageProvider } from '../page_objects/synthetics_app'; import { isEuiFormFieldInValid, @@ -362,10 +361,7 @@ const exitingMonitorConfig = { journey( `SyntheticsAddMonitor - Validation Test`, async ({ page, params }: { page: Page; params: any }) => { - page.setDefaultTimeout(60 * 1000); - recordVideo(page); - - const syntheticsApp = syntheticsAppPageProvider({ page, kibanaUrl: params.kibanaUrl }); + const syntheticsApp = syntheticsAppPageProvider({ page, kibanaUrl: params.kibanaUrl, params }); step('Go to monitor management', async () => { await syntheticsApp.navigateToMonitorManagement(true); diff --git a/x-pack/plugins/observability_solution/synthetics/e2e/synthetics/journeys/monitor_selector.journey.ts b/x-pack/plugins/observability_solution/synthetics/e2e/synthetics/journeys/monitor_selector.journey.ts index 35e4a8996d5b3..73b7e6e53ca1d 100644 --- a/x-pack/plugins/observability_solution/synthetics/e2e/synthetics/journeys/monitor_selector.journey.ts +++ b/x-pack/plugins/observability_solution/synthetics/e2e/synthetics/journeys/monitor_selector.journey.ts @@ -7,7 +7,6 @@ import { journey, step, expect, before, after } from '@elastic/synthetics'; import { byTestId } from '../../helpers/utils'; -import { recordVideo } from '../../helpers/record_video'; import { addTestMonitor, cleanTestMonitors, @@ -16,9 +15,7 @@ import { import { syntheticsAppPageProvider } from '../page_objects/synthetics_app'; journey(`MonitorSelector`, async ({ page, params }) => { - recordVideo(page); - - const syntheticsApp = syntheticsAppPageProvider({ page, kibanaUrl: params.kibanaUrl }); + const syntheticsApp = syntheticsAppPageProvider({ page, kibanaUrl: params.kibanaUrl, params }); const testMonitor1 = 'Test monitor 1'; const testMonitor2 = 'Test monitor 2'; const testMonitor3 = 'Test monitor 3'; diff --git a/x-pack/plugins/observability_solution/synthetics/e2e/synthetics/journeys/overview_scrolling.journey.ts b/x-pack/plugins/observability_solution/synthetics/e2e/synthetics/journeys/overview_scrolling.journey.ts index 7bec9a7a4b389..30b8a4f456a0d 100644 --- a/x-pack/plugins/observability_solution/synthetics/e2e/synthetics/journeys/overview_scrolling.journey.ts +++ b/x-pack/plugins/observability_solution/synthetics/e2e/synthetics/journeys/overview_scrolling.journey.ts @@ -7,7 +7,6 @@ import { before, after, expect, journey, step } from '@elastic/synthetics'; import { RetryService } from '@kbn/ftr-common-functional-services'; -import { recordVideo } from '../../helpers/record_video'; import { addTestMonitor, cleanTestMonitors, @@ -16,9 +15,7 @@ import { import { syntheticsAppPageProvider } from '../page_objects/synthetics_app'; journey('OverviewScrolling', async ({ page, params }) => { - recordVideo(page); - - const syntheticsApp = syntheticsAppPageProvider({ page, kibanaUrl: params.kibanaUrl }); + const syntheticsApp = syntheticsAppPageProvider({ page, kibanaUrl: params.kibanaUrl, params }); const retry: RetryService = params.getService('retry'); const listOfRequests: string[] = []; diff --git a/x-pack/plugins/observability_solution/synthetics/e2e/synthetics/journeys/overview_search.journey.ts b/x-pack/plugins/observability_solution/synthetics/e2e/synthetics/journeys/overview_search.journey.ts index a1729fca0faa3..790cb06f5f5c2 100644 --- a/x-pack/plugins/observability_solution/synthetics/e2e/synthetics/journeys/overview_search.journey.ts +++ b/x-pack/plugins/observability_solution/synthetics/e2e/synthetics/journeys/overview_search.journey.ts @@ -7,7 +7,6 @@ import { before, expect, journey, step } from '@elastic/synthetics'; import { RetryService } from '@kbn/ftr-common-functional-services'; -import { recordVideo } from '../../helpers/record_video'; import { addTestMonitor, cleanTestMonitors, @@ -16,11 +15,9 @@ import { import { syntheticsAppPageProvider } from '../page_objects/synthetics_app'; journey('Overview Search', async ({ page, params }) => { - recordVideo(page); - const retry: RetryService = params.getService('retry'); - const syntheticsApp = syntheticsAppPageProvider({ page, kibanaUrl: params.kibanaUrl }); + const syntheticsApp = syntheticsAppPageProvider({ page, kibanaUrl: params.kibanaUrl, params }); const elasticJourney = 'Elastic journey'; const cnnJourney = 'CNN journey'; const googleJourney = 'Google journey'; diff --git a/x-pack/plugins/observability_solution/synthetics/e2e/synthetics/journeys/overview_sorting.journey.ts b/x-pack/plugins/observability_solution/synthetics/e2e/synthetics/journeys/overview_sorting.journey.ts index 018df450628ef..cd65a67f1e22a 100644 --- a/x-pack/plugins/observability_solution/synthetics/e2e/synthetics/journeys/overview_sorting.journey.ts +++ b/x-pack/plugins/observability_solution/synthetics/e2e/synthetics/journeys/overview_sorting.journey.ts @@ -6,7 +6,6 @@ */ import { before, expect, journey, step } from '@elastic/synthetics'; -import { recordVideo } from '../../helpers/record_video'; import { addTestMonitor, cleanTestMonitors, @@ -15,9 +14,7 @@ import { import { syntheticsAppPageProvider } from '../page_objects/synthetics_app'; journey('OverviewSorting', async ({ page, params }) => { - recordVideo(page); - - const syntheticsApp = syntheticsAppPageProvider({ page, kibanaUrl: params.kibanaUrl }); + const syntheticsApp = syntheticsAppPageProvider({ page, kibanaUrl: params.kibanaUrl, params }); const testMonitor1 = 'acb'; // second alpha, first created const testMonitor2 = 'aCd'; // third alpha, second created const testMonitor3 = 'Abc'; // first alpha, last created diff --git a/x-pack/plugins/observability_solution/synthetics/e2e/synthetics/journeys/private_locations.journey.ts b/x-pack/plugins/observability_solution/synthetics/e2e/synthetics/journeys/private_locations.journey.ts index b9a9b23d16ca7..9e6bb8352c35f 100644 --- a/x-pack/plugins/observability_solution/synthetics/e2e/synthetics/journeys/private_locations.journey.ts +++ b/x-pack/plugins/observability_solution/synthetics/e2e/synthetics/journeys/private_locations.journey.ts @@ -8,7 +8,6 @@ import { journey, step, before, after, expect } from '@elastic/synthetics'; import { waitForLoadingToFinish } from '@kbn/ux-plugin/e2e/journeys/utils'; import { byTestId } from '../../helpers/utils'; -import { recordVideo } from '../../helpers/record_video'; import { addTestMonitor, cleanPrivateLocations, @@ -18,9 +17,7 @@ import { import { syntheticsAppPageProvider } from '../page_objects/synthetics_app'; journey(`PrivateLocationsSettings`, async ({ page, params }) => { - recordVideo(page); - - const syntheticsApp = syntheticsAppPageProvider({ page, kibanaUrl: params.kibanaUrl }); + const syntheticsApp = syntheticsAppPageProvider({ page, kibanaUrl: params.kibanaUrl, params }); page.setDefaultTimeout(2 * 30000); diff --git a/x-pack/plugins/observability_solution/synthetics/e2e/synthetics/journeys/project_monitor_read_only.journey.ts b/x-pack/plugins/observability_solution/synthetics/e2e/synthetics/journeys/project_monitor_read_only.journey.ts index 2bfc97bb9f5f1..4c9d73f3be815 100644 --- a/x-pack/plugins/observability_solution/synthetics/e2e/synthetics/journeys/project_monitor_read_only.journey.ts +++ b/x-pack/plugins/observability_solution/synthetics/e2e/synthetics/journeys/project_monitor_read_only.journey.ts @@ -7,18 +7,15 @@ import { after, before, expect, journey, step } from '@elastic/synthetics'; import { SyntheticsServices } from './services/synthetics_services'; -import { recordVideo } from '../../helpers/record_video'; import { cleanTestMonitors, enableMonitorManagedViaApi } from './services/add_monitor'; import { addTestMonitorProject } from './services/add_monitor_project'; import { syntheticsAppPageProvider } from '../page_objects/synthetics_app'; import { SyntheticsMonitor } from '../../../common/runtime_types'; journey('ProjectMonitorReadOnly', async ({ page, params }) => { - recordVideo(page); - const services = new SyntheticsServices(params); - const syntheticsApp = syntheticsAppPageProvider({ page, kibanaUrl: params.kibanaUrl }); + const syntheticsApp = syntheticsAppPageProvider({ page, kibanaUrl: params.kibanaUrl, params }); let originalMonitorConfiguration: SyntheticsMonitor | null; let monitorId: string; diff --git a/x-pack/plugins/observability_solution/synthetics/e2e/synthetics/journeys/step_details.journey.ts b/x-pack/plugins/observability_solution/synthetics/e2e/synthetics/journeys/step_details.journey.ts index 5d4c677b21718..07dab69c33ed8 100644 --- a/x-pack/plugins/observability_solution/synthetics/e2e/synthetics/journeys/step_details.journey.ts +++ b/x-pack/plugins/observability_solution/synthetics/e2e/synthetics/journeys/step_details.journey.ts @@ -6,15 +6,11 @@ */ import { journey, step, before, after } from '@elastic/synthetics'; -import { recordVideo } from '../../helpers/record_video'; import { syntheticsAppPageProvider } from '../page_objects/synthetics_app'; import { SyntheticsServices } from './services/synthetics_services'; journey(`StepDetailsPage`, async ({ page, params }) => { - recordVideo(page); - - page.setDefaultTimeout(60 * 1000); - const syntheticsApp = syntheticsAppPageProvider({ page, kibanaUrl: params.kibanaUrl }); + const syntheticsApp = syntheticsAppPageProvider({ page, kibanaUrl: params.kibanaUrl, params }); const services = new SyntheticsServices(params); diff --git a/x-pack/plugins/observability_solution/synthetics/e2e/synthetics/journeys/test_now_mode.journey.ts b/x-pack/plugins/observability_solution/synthetics/e2e/synthetics/journeys/test_now_mode.journey.ts index ac931bbd1e725..2d8b4de8e5b40 100644 --- a/x-pack/plugins/observability_solution/synthetics/e2e/synthetics/journeys/test_now_mode.journey.ts +++ b/x-pack/plugins/observability_solution/synthetics/e2e/synthetics/journeys/test_now_mode.journey.ts @@ -7,15 +7,12 @@ import { journey, step, before, after, expect } from '@elastic/synthetics'; import { RetryService } from '@kbn/ftr-common-functional-services'; -import { recordVideo } from '../../helpers/record_video'; import { byTestId } from '../../helpers/utils'; import { syntheticsAppPageProvider } from '../page_objects/synthetics_app'; import { SyntheticsServices } from './services/synthetics_services'; journey(`TestNowMode`, async ({ page, params }) => { - page.setDefaultTimeout(60 * 1000); - recordVideo(page); - const syntheticsApp = syntheticsAppPageProvider({ page, kibanaUrl: params.kibanaUrl }); + const syntheticsApp = syntheticsAppPageProvider({ page, kibanaUrl: params.kibanaUrl, params }); const services = new SyntheticsServices(params); diff --git a/x-pack/plugins/observability_solution/synthetics/e2e/synthetics/journeys/test_run_details.journey.ts b/x-pack/plugins/observability_solution/synthetics/e2e/synthetics/journeys/test_run_details.journey.ts index 5c1af51caa18d..8bf7fd0f690d1 100644 --- a/x-pack/plugins/observability_solution/synthetics/e2e/synthetics/journeys/test_run_details.journey.ts +++ b/x-pack/plugins/observability_solution/synthetics/e2e/synthetics/journeys/test_run_details.journey.ts @@ -6,16 +6,12 @@ */ import { journey, step, before, after, expect } from '@elastic/synthetics'; -import { recordVideo } from '../../helpers/record_video'; import { byTestId } from '../../helpers/utils'; import { syntheticsAppPageProvider } from '../page_objects/synthetics_app'; import { SyntheticsServices } from './services/synthetics_services'; journey(`TestRunDetailsPage`, async ({ page, params }) => { - recordVideo(page); - - page.setDefaultTimeout(60 * 1000); - const syntheticsApp = syntheticsAppPageProvider({ page, kibanaUrl: params.kibanaUrl }); + const syntheticsApp = syntheticsAppPageProvider({ page, kibanaUrl: params.kibanaUrl, params }); const services = new SyntheticsServices(params); diff --git a/x-pack/plugins/observability_solution/synthetics/e2e/synthetics/page_objects/synthetics_app.tsx b/x-pack/plugins/observability_solution/synthetics/e2e/synthetics/page_objects/synthetics_app.tsx index 4e16479d10434..49aefae295b39 100644 --- a/x-pack/plugins/observability_solution/synthetics/e2e/synthetics/page_objects/synthetics_app.tsx +++ b/x-pack/plugins/observability_solution/synthetics/e2e/synthetics/page_objects/synthetics_app.tsx @@ -5,6 +5,8 @@ * 2.0. */ import { expect, Page } from '@elastic/synthetics'; +import { RetryService } from '@kbn/ftr-common-functional-services'; +import { recordVideo } from '../../helpers/record_video'; import { FormMonitorType } from '../../../common/runtime_types/monitor_management'; import { loginPageProvider } from '../../page_objects/login'; import { utilsPageProvider } from '../../page_objects/utils'; @@ -13,7 +15,15 @@ const SIXTY_SEC_TIMEOUT = { timeout: 60 * 1000, }; -export function syntheticsAppPageProvider({ page, kibanaUrl }: { page: Page; kibanaUrl: string }) { +export function syntheticsAppPageProvider({ + page, + kibanaUrl, + params, +}: { + page: Page; + kibanaUrl: string; + params: Record; +}) { const remoteKibanaUrl = process.env.SYNTHETICS_REMOTE_KIBANA_URL; const remoteUsername = process.env.SYNTHETICS_REMOTE_KIBANA_USERNAME; const remotePassword = process.env.SYNTHETICS_REMOTE_KIBANA_PASSWORD; @@ -23,6 +33,10 @@ export function syntheticsAppPageProvider({ page, kibanaUrl }: { page: Page; kib const settingsPage = `${basePath}/app/synthetics/settings`; const addMonitor = `${basePath}/app/synthetics/add-monitor`; const overview = `${basePath}/app/synthetics`; + const retry: RetryService = params?.getService('retry'); + + recordVideo(page); + page.setDefaultTimeout(60 * 1000); return { ...loginPageProvider({ @@ -162,8 +176,10 @@ export function syntheticsAppPageProvider({ page, kibanaUrl }: { page: Page; kib async selectLocationsAddEdit({ locations }: { locations: string[] }) { for (let i = 0; i < locations.length; i++) { - await page.click(this.byTestId('syntheticsMonitorConfigLocations')); - await page.click(`text=${locations[i]}`); + await retry.try(async () => { + await page.click(this.byTestId('syntheticsMonitorConfigLocations')); + await page.click(`text=${locations[i]}`); + }); } }, @@ -278,9 +294,6 @@ export function syntheticsAppPageProvider({ page, kibanaUrl }: { page: Page; kib name, inlineScript, recorderScript, - params, - username, - password, apmServiceName, locations, }: { diff --git a/x-pack/plugins/observability_solution/synthetics/public/plugin.ts b/x-pack/plugins/observability_solution/synthetics/public/plugin.ts index 1d7044a79c6bf..7c343ef795776 100644 --- a/x-pack/plugins/observability_solution/synthetics/public/plugin.ts +++ b/x-pack/plugins/observability_solution/synthetics/public/plugin.ts @@ -238,7 +238,6 @@ function registerSyntheticsRoutesWithNavigation( path: OVERVIEW_ROUTE, matchFullPath: true, ignoreTrailingSlash: true, - isNewFeature: true, }, { label: i18n.translate('xpack.synthetics.certificatesPage.heading', { diff --git a/x-pack/plugins/search_playground/kibana.jsonc b/x-pack/plugins/search_playground/kibana.jsonc index 221d5bf9e1873..28a775eca341e 100644 --- a/x-pack/plugins/search_playground/kibana.jsonc +++ b/x-pack/plugins/search_playground/kibana.jsonc @@ -21,6 +21,7 @@ ], "optionalPlugins": [ "cloud", + "console", "usageCollection", ], "requiredBundles": [ diff --git a/x-pack/plugins/search_playground/public/chat_playground_overview.tsx b/x-pack/plugins/search_playground/public/chat_playground_overview.tsx index b750a9828021d..d40996ba91455 100644 --- a/x-pack/plugins/search_playground/public/chat_playground_overview.tsx +++ b/x-pack/plugins/search_playground/public/chat_playground_overview.tsx @@ -6,7 +6,7 @@ */ import { i18n } from '@kbn/i18n'; -import React from 'react'; +import React, { useMemo } from 'react'; import { EuiBetaBadge, EuiFlexGroup, EuiFlexItem, EuiPageTemplate } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; import { PlaygroundProvider } from './providers/playground_provider'; @@ -14,8 +14,18 @@ import { PlaygroundProvider } from './providers/playground_provider'; import { App } from './components/app'; import { PlaygroundToolbar } from './embeddable'; import { PlaygroundHeaderDocs } from './components/playground_header_docs'; +import { useKibana } from './hooks/use_kibana'; export const ChatPlaygroundOverview: React.FC = () => { + const { + services: { console: consolePlugin }, + } = useKibana(); + + const embeddableConsole = useMemo( + () => (consolePlugin?.EmbeddableConsole ? : null), + [consolePlugin] + ); + return ( { rightSideItems={[, ]} /> + {embeddableConsole} ); diff --git a/x-pack/plugins/search_playground/public/types.ts b/x-pack/plugins/search_playground/public/types.ts index 6f8552d753bbb..84edcf1b07e05 100644 --- a/x-pack/plugins/search_playground/public/types.ts +++ b/x-pack/plugins/search_playground/public/types.ts @@ -21,6 +21,7 @@ import { CloudSetup } from '@kbn/cloud-plugin/public'; import { TriggersAndActionsUIPublicPluginStart } from '@kbn/triggers-actions-ui-plugin/public'; import { AppMountParameters } from '@kbn/core/public'; import { UsageCollectionStart } from '@kbn/usage-collection-plugin/public'; +import type { ConsolePluginStart } from '@kbn/console-plugin/public'; import { ChatRequestData } from '../common/types'; import type { App } from './components/app'; import type { PlaygroundProvider as PlaygroundProviderComponent } from './providers/playground_provider'; @@ -44,6 +45,7 @@ export interface AppPluginStartDependencies { navigation: NavigationPublicPluginStart; triggersActionsUi: TriggersAndActionsUIPublicPluginStart; share: SharePluginStart; + console?: ConsolePluginStart; } export interface AppServicesContext { @@ -53,6 +55,7 @@ export interface AppServicesContext { cloud?: CloudSetup; triggersActionsUi: TriggersAndActionsUIPublicPluginStart; usageCollection?: UsageCollectionStart; + console?: ConsolePluginStart; } export enum ChatFormFields { diff --git a/x-pack/plugins/search_playground/server/lib/fetch_indices.test.ts b/x-pack/plugins/search_playground/server/lib/fetch_indices.test.ts index 8613609b38fc4..af9c6adfc8ae2 100644 --- a/x-pack/plugins/search_playground/server/lib/fetch_indices.test.ts +++ b/x-pack/plugins/search_playground/server/lib/fetch_indices.test.ts @@ -19,8 +19,8 @@ describe('fetch indices', () => { }, 'index-2': { aliases: { - 'search-alias-1': {}, - 'search-alias-2': {}, + 'search-alias-3': {}, + 'search-alias-4': {}, }, }, 'index-3': { @@ -48,7 +48,15 @@ describe('fetch indices', () => { ); expect(indexData).toEqual({ - indexNames: ['index-1', 'index-2', 'index-3'], + indexNames: [ + 'index-1', + 'index-2', + 'index-3', + 'search-alias-1', + 'search-alias-2', + 'search-alias-3', + 'search-alias-4', + ], }); }); }); diff --git a/x-pack/plugins/search_playground/server/lib/fetch_indices.ts b/x-pack/plugins/search_playground/server/lib/fetch_indices.ts index 953e7a980a6a9..51b72790028c2 100644 --- a/x-pack/plugins/search_playground/server/lib/fetch_indices.ts +++ b/x-pack/plugins/search_playground/server/lib/fetch_indices.ts @@ -42,9 +42,24 @@ export const fetchIndices = async ( !isHidden(allIndexMatches[indexName]) && !isClosed(allIndexMatches[indexName]) ); + + const allAliases = allIndexNames.reduce((acc, indexName) => { + const aliases = allIndexMatches[indexName].aliases; + if (aliases) { + Object.keys(aliases).forEach((alias) => { + if (!acc.includes(alias)) { + acc.push(alias); + } + }); + } + return acc; + }, []); + + const allOptions = [...allIndexNames, ...allAliases]; + const indexNames = searchQuery - ? allIndexNames.filter((indexName) => indexName.includes(searchQuery.toLowerCase())) - : allIndexNames; + ? allOptions.filter((indexName) => indexName.includes(searchQuery.toLowerCase())) + : allOptions; return { indexNames, diff --git a/x-pack/plugins/search_playground/tsconfig.json b/x-pack/plugins/search_playground/tsconfig.json index 2fc516bc2ca46..96c2c1681008a 100644 --- a/x-pack/plugins/search_playground/tsconfig.json +++ b/x-pack/plugins/search_playground/tsconfig.json @@ -39,7 +39,8 @@ "@kbn/core-logging-server-mocks", "@kbn/analytics", "@kbn/usage-collection-plugin", - "@kbn/analytics-client" + "@kbn/analytics-client", + "@kbn/console-plugin" ], "exclude": [ "target/**/*", diff --git a/x-pack/plugins/security/public/management/role_combo_box/role_combo_box.test.tsx b/x-pack/plugins/security/public/management/role_combo_box/role_combo_box.test.tsx index 4003ce6233bda..f841fbca7d55a 100644 --- a/x-pack/plugins/security/public/management/role_combo_box/role_combo_box.test.tsx +++ b/x-pack/plugins/security/public/management/role_combo_box/role_combo_box.test.tsx @@ -42,6 +42,7 @@ describe('RoleComboBox', () => { }, { name: 'deprecated_role', + description: 'Deprecated role description', elasticsearch: { cluster: [], indices: [], run_as: [] }, kibana: [], metadata: { _reserved: true, _deprecated: true }, @@ -72,6 +73,7 @@ describe('RoleComboBox', () => { "label": "custom_role", "value": Object { "deprecatedReason": undefined, + "description": undefined, "isAdmin": false, "isDeprecated": false, "isReserved": false, @@ -89,6 +91,7 @@ describe('RoleComboBox', () => { "label": "reserved_role", "value": Object { "deprecatedReason": undefined, + "description": undefined, "isAdmin": false, "isDeprecated": false, "isReserved": true, @@ -106,6 +109,7 @@ describe('RoleComboBox', () => { "label": "some_admin", "value": Object { "deprecatedReason": undefined, + "description": undefined, "isAdmin": true, "isDeprecated": false, "isReserved": true, @@ -123,6 +127,7 @@ describe('RoleComboBox', () => { "label": "some_system", "value": Object { "deprecatedReason": undefined, + "description": undefined, "isAdmin": false, "isDeprecated": false, "isReserved": true, @@ -140,6 +145,7 @@ describe('RoleComboBox', () => { "label": "deprecated_role", "value": Object { "deprecatedReason": undefined, + "description": "Deprecated role description", "isAdmin": false, "isDeprecated": true, "isReserved": true, diff --git a/x-pack/plugins/security/public/management/role_combo_box/role_combo_box.tsx b/x-pack/plugins/security/public/management/role_combo_box/role_combo_box.tsx index 5e329b32c353d..c1ce607d82acf 100644 --- a/x-pack/plugins/security/public/management/role_combo_box/role_combo_box.tsx +++ b/x-pack/plugins/security/public/management/role_combo_box/role_combo_box.tsx @@ -6,7 +6,14 @@ */ import type { EuiComboBoxOptionOption, EuiComboBoxProps } from '@elastic/eui'; -import { EuiBadge, EuiComboBox, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; +import { + EuiBadge, + EuiComboBox, + EuiFlexGroup, + EuiFlexItem, + EuiText, + EuiToolTip, +} from '@elastic/eui'; import React from 'react'; import { i18n } from '@kbn/i18n'; @@ -34,6 +41,7 @@ type Option = EuiComboBoxOptionOption<{ isSystem: boolean; isAdmin: boolean; deprecatedReason?: string; + description?: string; }>; export const RoleComboBox = (props: Props) => { @@ -57,6 +65,7 @@ export const RoleComboBox = (props: Props) => { isSystem, isAdmin, deprecatedReason: roleDefinition?.metadata?._deprecated_reason, + description: roleDefinition?.description, }, }; }; @@ -134,7 +143,15 @@ export const RoleComboBox = (props: Props) => { function renderOption(option: Option) { return ( - {option.label} + + {option.value?.description ? ( + + {option.label} + + ) : ( + {option.label} + )} + {option.value?.isDeprecated ? ( diff --git a/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/edit_role_mapping_page.test.tsx b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/edit_role_mapping_page.test.tsx index 226106a5eb09d..8fdd6dce1e3db 100644 --- a/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/edit_role_mapping_page.test.tsx +++ b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/edit_role_mapping_page.test.tsx @@ -25,6 +25,7 @@ import type { Role } from '../../../../common'; import { RoleComboBox } from '../../role_combo_box'; import type { RolesAPIClient } from '../../roles'; import { rolesAPIClientMock } from '../../roles/roles_api_client.mock'; +import { securityFeaturesAPIClientMock } from '../../security_features/security_features_api_client.mock'; import { NoCompatibleRealms, PermissionDenied, SectionLoading } from '../components'; import { roleMappingsAPIClientMock } from '../role_mappings_api_client.mock'; @@ -34,6 +35,7 @@ describe('EditRoleMappingPage', () => { const renderView = ( roleMappingsAPI: ReturnType, + securityFeaturesAPI: ReturnType, name?: string, readOnly: boolean = false ) => { @@ -51,6 +53,7 @@ describe('EditRoleMappingPage', () => { action="edit" name={name} roleMappingsAPI={roleMappingsAPI} + securityFeaturesAPI={securityFeaturesAPI} rolesAPIClient={rolesAPI} notifications={coreStart.notifications} docLinks={coreStart.docLinks} @@ -72,15 +75,16 @@ describe('EditRoleMappingPage', () => { it('allows a role mapping to be created', async () => { const roleMappingsAPI = roleMappingsAPIClientMock.create(); + const securityFeaturesAPI = securityFeaturesAPIClientMock.create(); roleMappingsAPI.saveRoleMapping.mockResolvedValue(null); - roleMappingsAPI.checkRoleMappingFeatures.mockResolvedValue({ - canManageRoleMappings: true, + securityFeaturesAPI.checkFeatures.mockResolvedValue({ + canReadSecurity: true, hasCompatibleRealms: true, canUseInlineScripts: true, canUseStoredScripts: true, }); - const wrapper = renderView(roleMappingsAPI); + const wrapper = renderView(roleMappingsAPI, securityFeaturesAPI); await nextTick(); wrapper.update(); @@ -108,6 +112,7 @@ describe('EditRoleMappingPage', () => { it('allows a role mapping to be updated', async () => { const roleMappingsAPI = roleMappingsAPIClientMock.create(); + const securityFeaturesAPI = securityFeaturesAPIClientMock.create(); roleMappingsAPI.saveRoleMapping.mockResolvedValue(null); roleMappingsAPI.getRoleMapping.mockResolvedValue({ name: 'foo', @@ -125,14 +130,14 @@ describe('EditRoleMappingPage', () => { bar: 'baz', }, }); - roleMappingsAPI.checkRoleMappingFeatures.mockResolvedValue({ - canManageRoleMappings: true, + securityFeaturesAPI.checkFeatures.mockResolvedValue({ + canReadSecurity: true, hasCompatibleRealms: true, canUseInlineScripts: true, canUseStoredScripts: true, }); - const wrapper = renderView(roleMappingsAPI, 'foo'); + const wrapper = renderView(roleMappingsAPI, securityFeaturesAPI, 'foo'); await nextTick(); wrapper.update(); @@ -165,12 +170,13 @@ describe('EditRoleMappingPage', () => { it('renders a permission denied message when unauthorized to manage role mappings', async () => { const roleMappingsAPI = roleMappingsAPIClientMock.create(); - roleMappingsAPI.checkRoleMappingFeatures.mockResolvedValue({ - canManageRoleMappings: false, + const securityFeaturesAPI = securityFeaturesAPIClientMock.create(); + securityFeaturesAPI.checkFeatures.mockResolvedValue({ + canReadSecurity: false, hasCompatibleRealms: true, }); - const wrapper = renderView(roleMappingsAPI); + const wrapper = renderView(roleMappingsAPI, securityFeaturesAPI); expect(wrapper.find(SectionLoading)).toHaveLength(1); expect(wrapper.find(PermissionDenied)).toHaveLength(0); @@ -184,12 +190,13 @@ describe('EditRoleMappingPage', () => { it('renders a warning when there are no compatible realms enabled', async () => { const roleMappingsAPI = roleMappingsAPIClientMock.create(); - roleMappingsAPI.checkRoleMappingFeatures.mockResolvedValue({ - canManageRoleMappings: true, + const securityFeaturesAPI = securityFeaturesAPIClientMock.create(); + securityFeaturesAPI.checkFeatures.mockResolvedValue({ + canReadSecurity: true, hasCompatibleRealms: false, }); - const wrapper = renderView(roleMappingsAPI); + const wrapper = renderView(roleMappingsAPI, securityFeaturesAPI); expect(wrapper.find(SectionLoading)).toHaveLength(1); expect(wrapper.find(NoCompatibleRealms)).toHaveLength(0); @@ -202,6 +209,7 @@ describe('EditRoleMappingPage', () => { it('renders a message when editing a mapping with deprecated roles assigned', async () => { const roleMappingsAPI = roleMappingsAPIClientMock.create(); + const securityFeaturesAPI = securityFeaturesAPIClientMock.create(); roleMappingsAPI.getRoleMapping.mockResolvedValue({ name: 'foo', roles: ['some-deprecated-role'], @@ -210,14 +218,14 @@ describe('EditRoleMappingPage', () => { field: { username: '*' }, }, }); - roleMappingsAPI.checkRoleMappingFeatures.mockResolvedValue({ - canManageRoleMappings: true, + securityFeaturesAPI.checkFeatures.mockResolvedValue({ + canReadSecurity: true, hasCompatibleRealms: true, canUseInlineScripts: true, canUseStoredScripts: true, }); - const wrapper = renderView(roleMappingsAPI, 'foo'); + const wrapper = renderView(roleMappingsAPI, securityFeaturesAPI, 'foo'); expect(findTestSubject(wrapper, 'deprecatedRolesAssigned')).toHaveLength(0); await nextTick(); @@ -228,6 +236,7 @@ describe('EditRoleMappingPage', () => { it('renders a warning when editing a mapping with a stored role template, when stored scripts are disabled', async () => { const roleMappingsAPI = roleMappingsAPIClientMock.create(); + const securityFeaturesAPI = securityFeaturesAPIClientMock.create(); roleMappingsAPI.getRoleMapping.mockResolvedValue({ name: 'foo', role_templates: [ @@ -240,14 +249,14 @@ describe('EditRoleMappingPage', () => { field: { username: '*' }, }, }); - roleMappingsAPI.checkRoleMappingFeatures.mockResolvedValue({ - canManageRoleMappings: true, + securityFeaturesAPI.checkFeatures.mockResolvedValue({ + canReadSecurity: true, hasCompatibleRealms: true, canUseInlineScripts: true, canUseStoredScripts: false, }); - const wrapper = renderView(roleMappingsAPI, 'foo'); + const wrapper = renderView(roleMappingsAPI, securityFeaturesAPI, 'foo'); expect(findTestSubject(wrapper, 'roleMappingInlineScriptsDisabled')).toHaveLength(0); expect(findTestSubject(wrapper, 'roleMappingStoredScriptsDisabled')).toHaveLength(0); @@ -260,6 +269,7 @@ describe('EditRoleMappingPage', () => { it('renders a warning when editing a mapping with an inline role template, when inline scripts are disabled', async () => { const roleMappingsAPI = roleMappingsAPIClientMock.create(); + const securityFeaturesAPI = securityFeaturesAPIClientMock.create(); roleMappingsAPI.getRoleMapping.mockResolvedValue({ name: 'foo', role_templates: [ @@ -272,14 +282,14 @@ describe('EditRoleMappingPage', () => { field: { username: '*' }, }, }); - roleMappingsAPI.checkRoleMappingFeatures.mockResolvedValue({ - canManageRoleMappings: true, + securityFeaturesAPI.checkFeatures.mockResolvedValue({ + canReadSecurity: true, hasCompatibleRealms: true, canUseInlineScripts: false, canUseStoredScripts: true, }); - const wrapper = renderView(roleMappingsAPI, 'foo'); + const wrapper = renderView(roleMappingsAPI, securityFeaturesAPI, 'foo'); expect(findTestSubject(wrapper, 'roleMappingInlineScriptsDisabled')).toHaveLength(0); expect(findTestSubject(wrapper, 'roleMappingStoredScriptsDisabled')).toHaveLength(0); @@ -292,6 +302,7 @@ describe('EditRoleMappingPage', () => { it('renders the visual editor by default for simple rule sets', async () => { const roleMappingsAPI = roleMappingsAPIClientMock.create(); + const securityFeaturesAPI = securityFeaturesAPIClientMock.create(); roleMappingsAPI.getRoleMapping.mockResolvedValue({ name: 'foo', roles: ['superuser'], @@ -316,14 +327,14 @@ describe('EditRoleMappingPage', () => { ], }, }); - roleMappingsAPI.checkRoleMappingFeatures.mockResolvedValue({ - canManageRoleMappings: true, + securityFeaturesAPI.checkFeatures.mockResolvedValue({ + canReadSecurity: true, hasCompatibleRealms: true, canUseInlineScripts: true, canUseStoredScripts: true, }); - const wrapper = renderView(roleMappingsAPI, 'foo'); + const wrapper = renderView(roleMappingsAPI, securityFeaturesAPI, 'foo'); await nextTick(); wrapper.update(); @@ -355,20 +366,21 @@ describe('EditRoleMappingPage', () => { }; const roleMappingsAPI = roleMappingsAPIClientMock.create(); + const securityFeaturesAPI = securityFeaturesAPIClientMock.create(); roleMappingsAPI.getRoleMapping.mockResolvedValue({ name: 'foo', roles: ['superuser'], enabled: true, rules: createRule(10), }); - roleMappingsAPI.checkRoleMappingFeatures.mockResolvedValue({ - canManageRoleMappings: true, + securityFeaturesAPI.checkFeatures.mockResolvedValue({ + canReadSecurity: true, hasCompatibleRealms: true, canUseInlineScripts: true, canUseStoredScripts: true, }); - const wrapper = renderView(roleMappingsAPI, 'foo'); + const wrapper = renderView(roleMappingsAPI, securityFeaturesAPI, 'foo'); await nextTick(); wrapper.update(); @@ -378,6 +390,7 @@ describe('EditRoleMappingPage', () => { it('renders a readonly view when not enough privileges', async () => { const roleMappingsAPI = roleMappingsAPIClientMock.create(); + const securityFeaturesAPI = securityFeaturesAPIClientMock.create(); roleMappingsAPI.saveRoleMapping.mockResolvedValue(null); roleMappingsAPI.getRoleMapping.mockResolvedValue({ name: 'foo', @@ -395,14 +408,14 @@ describe('EditRoleMappingPage', () => { bar: 'baz', }, }); - roleMappingsAPI.checkRoleMappingFeatures.mockResolvedValue({ - canManageRoleMappings: true, + securityFeaturesAPI.checkFeatures.mockResolvedValue({ + canReadSecurity: true, hasCompatibleRealms: true, canUseInlineScripts: true, canUseStoredScripts: true, }); - const wrapper = renderView(roleMappingsAPI, 'foo', true); + const wrapper = renderView(roleMappingsAPI, securityFeaturesAPI, 'foo', true); await nextTick(); wrapper.update(); diff --git a/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/edit_role_mapping_page.tsx b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/edit_role_mapping_page.tsx index c3dc778643dea..647cbd27b3921 100644 --- a/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/edit_role_mapping_page.tsx +++ b/x-pack/plugins/security/public/management/role_mappings/edit_role_mapping/edit_role_mapping_page.tsx @@ -28,6 +28,7 @@ import { RuleEditorPanel } from './rule_editor_panel'; import { validateRoleMappingForSave } from './services/role_mapping_validation'; import type { RoleMapping } from '../../../../common'; import type { RolesAPIClient } from '../../roles'; +import type { SecurityFeaturesAPIClient } from '../../security_features'; import { DeleteProvider, NoCompatibleRealms, @@ -55,6 +56,7 @@ interface Props { name?: string; roleMappingsAPI: PublicMethodsOf; rolesAPIClient: PublicMethodsOf; + securityFeaturesAPI: PublicMethodsOf; notifications: NotificationsStart; docLinks: DocLinksStart; history: ScopedHistory; @@ -361,7 +363,7 @@ export class EditRoleMappingPage extends Component { private async loadAppData() { try { const [features, roleMapping] = await Promise.all([ - this.props.roleMappingsAPI.checkRoleMappingFeatures(), + this.props.securityFeaturesAPI.checkFeatures(), this.editingExistingRoleMapping() || this.cloningExistingRoleMapping() ? this.props.roleMappingsAPI.getRoleMapping(this.props.name!) : Promise.resolve({ @@ -374,15 +376,10 @@ export class EditRoleMappingPage extends Component { }), ]); - const { - canManageRoleMappings, - canUseStoredScripts, - canUseInlineScripts, - hasCompatibleRealms, - } = features; + const { canReadSecurity, canUseStoredScripts, canUseInlineScripts, hasCompatibleRealms } = + features; - const canLoad = canManageRoleMappings || this.props.readOnly; - const loadState: State['loadState'] = canLoad ? 'ready' : 'permissionDenied'; + const loadState: State['loadState'] = canReadSecurity ? 'ready' : 'permissionDenied'; this.setState({ loadState, diff --git a/x-pack/plugins/security/public/management/role_mappings/role_mappings_api_client.mock.ts b/x-pack/plugins/security/public/management/role_mappings/role_mappings_api_client.mock.ts index b0aefea248cf0..e004edbe1d854 100644 --- a/x-pack/plugins/security/public/management/role_mappings/role_mappings_api_client.mock.ts +++ b/x-pack/plugins/security/public/management/role_mappings/role_mappings_api_client.mock.ts @@ -7,7 +7,6 @@ export const roleMappingsAPIClientMock = { create: () => ({ - checkRoleMappingFeatures: jest.fn(), getRoleMappings: jest.fn(), getRoleMapping: jest.fn(), saveRoleMapping: jest.fn(), diff --git a/x-pack/plugins/security/public/management/role_mappings/role_mappings_api_client.ts b/x-pack/plugins/security/public/management/role_mappings/role_mappings_api_client.ts index c2b1f08d90319..5aa16fde32a24 100644 --- a/x-pack/plugins/security/public/management/role_mappings/role_mappings_api_client.ts +++ b/x-pack/plugins/security/public/management/role_mappings/role_mappings_api_client.ts @@ -9,15 +9,6 @@ import type { HttpStart } from '@kbn/core/public'; import type { RoleMapping } from '../../../common'; -export interface CheckRoleMappingFeaturesResponse { - canManageRoleMappings: boolean; - canUseInlineScripts: boolean; - canUseStoredScripts: boolean; - hasCompatibleRealms: boolean; - canUseRemoteIndices: boolean; - canUseRemoteClusters: boolean; -} - type DeleteRoleMappingsResponse = Array<{ name: string; success: boolean; @@ -27,10 +18,6 @@ type DeleteRoleMappingsResponse = Array<{ export class RoleMappingsAPIClient { constructor(private readonly http: HttpStart) {} - public async checkRoleMappingFeatures(): Promise { - return this.http.get(`/internal/security/_check_role_mapping_features`); - } - public async getRoleMappings(): Promise { return this.http.get(`/internal/security/role_mapping`); } diff --git a/x-pack/plugins/security/public/management/role_mappings/role_mappings_grid/role_mappings_grid_page.test.tsx b/x-pack/plugins/security/public/management/role_mappings/role_mappings_grid/role_mappings_grid_page.test.tsx index 7f2182e1a7e67..a9d770c50a1dd 100644 --- a/x-pack/plugins/security/public/management/role_mappings/role_mappings_grid/role_mappings_grid_page.test.tsx +++ b/x-pack/plugins/security/public/management/role_mappings/role_mappings_grid/role_mappings_grid_page.test.tsx @@ -17,6 +17,7 @@ import { findTestSubject, mountWithIntl, nextTick } from '@kbn/test-jest-helpers import { EmptyPrompt } from './empty_prompt'; import { RoleMappingsGridPage } from './role_mappings_grid_page'; import { rolesAPIClientMock } from '../../roles/index.mock'; +import { securityFeaturesAPIClientMock } from '../../security_features/security_features_api_client.mock'; import { NoCompatibleRealms, PermissionDenied, SectionLoading } from '../components'; import { roleMappingsAPIClientMock } from '../role_mappings_api_client.mock'; @@ -26,6 +27,7 @@ describe('RoleMappingsGridPage', () => { const renderView = ( roleMappingsAPI: ReturnType, + securityFeaturesAPI: ReturnType, rolesAPI: ReturnType = rolesAPIClientMock.create(), readOnly: boolean = false ) => { @@ -40,6 +42,7 @@ describe('RoleMappingsGridPage', () => { { it('renders a create prompt when no role mappings exist', async () => { const roleMappingsAPI = roleMappingsAPIClientMock.create(); + const securityFeaturesAPI = securityFeaturesAPIClientMock.create(); roleMappingsAPI.getRoleMappings.mockResolvedValue([]); - roleMappingsAPI.checkRoleMappingFeatures.mockResolvedValue({ - canManageRoleMappings: true, + securityFeaturesAPI.checkFeatures.mockResolvedValue({ + canReadSecurity: true, hasCompatibleRealms: true, }); - const wrapper = renderView(roleMappingsAPI); + const wrapper = renderView(roleMappingsAPI, securityFeaturesAPI); expect(wrapper.find(SectionLoading)).toHaveLength(1); expect(wrapper.find(EmptyPrompt)).toHaveLength(0); @@ -88,12 +92,13 @@ describe('RoleMappingsGridPage', () => { it('renders a permission denied message when unauthorized to manage role mappings', async () => { const roleMappingsAPI = roleMappingsAPIClientMock.create(); - roleMappingsAPI.checkRoleMappingFeatures.mockResolvedValue({ - canManageRoleMappings: false, + const securityFeaturesAPI = securityFeaturesAPIClientMock.create(); + securityFeaturesAPI.checkFeatures.mockResolvedValue({ + canReadSecurity: false, hasCompatibleRealms: true, }); - const wrapper = renderView(roleMappingsAPI); + const wrapper = renderView(roleMappingsAPI, securityFeaturesAPI); expect(wrapper.find(SectionLoading)).toHaveLength(1); expect(wrapper.find(PermissionDenied)).toHaveLength(0); @@ -107,6 +112,7 @@ describe('RoleMappingsGridPage', () => { it('renders a warning when there are no compatible realms enabled', async () => { const roleMappingsAPI = roleMappingsAPIClientMock.create(); + const securityFeaturesAPI = securityFeaturesAPIClientMock.create(); roleMappingsAPI.getRoleMappings.mockResolvedValue([ { name: 'some realm', @@ -115,12 +121,12 @@ describe('RoleMappingsGridPage', () => { rules: { field: { username: '*' } }, }, ]); - roleMappingsAPI.checkRoleMappingFeatures.mockResolvedValue({ - canManageRoleMappings: true, + securityFeaturesAPI.checkFeatures.mockResolvedValue({ + canReadSecurity: true, hasCompatibleRealms: false, }); - const wrapper = renderView(roleMappingsAPI); + const wrapper = renderView(roleMappingsAPI, securityFeaturesAPI); expect(wrapper.find(SectionLoading)).toHaveLength(1); expect(wrapper.find(NoCompatibleRealms)).toHaveLength(0); @@ -133,6 +139,7 @@ describe('RoleMappingsGridPage', () => { it('renders links to mapped roles, even if the roles API call returns nothing', async () => { const roleMappingsAPI = roleMappingsAPIClientMock.create(); + const securityFeaturesAPI = securityFeaturesAPIClientMock.create(); roleMappingsAPI.getRoleMappings.mockResolvedValue([ { name: 'some realm', @@ -141,12 +148,12 @@ describe('RoleMappingsGridPage', () => { rules: { field: { username: '*' } }, }, ]); - roleMappingsAPI.checkRoleMappingFeatures.mockResolvedValue({ - canManageRoleMappings: true, + securityFeaturesAPI.checkFeatures.mockResolvedValue({ + canReadSecurity: true, hasCompatibleRealms: true, }); - const wrapper = renderView(roleMappingsAPI); + const wrapper = renderView(roleMappingsAPI, securityFeaturesAPI); await nextTick(); wrapper.update(); @@ -157,6 +164,7 @@ describe('RoleMappingsGridPage', () => { it('describes the number of mapped role templates', async () => { const roleMappingsAPI = roleMappingsAPIClientMock.create(); + const securityFeaturesAPI = securityFeaturesAPIClientMock.create(); roleMappingsAPI.getRoleMappings.mockResolvedValue([ { name: 'some realm', @@ -165,12 +173,12 @@ describe('RoleMappingsGridPage', () => { rules: { field: { username: '*' } }, }, ]); - roleMappingsAPI.checkRoleMappingFeatures.mockResolvedValue({ - canManageRoleMappings: true, + securityFeaturesAPI.checkFeatures.mockResolvedValue({ + canReadSecurity: true, hasCompatibleRealms: true, }); - const wrapper = renderView(roleMappingsAPI); + const wrapper = renderView(roleMappingsAPI, securityFeaturesAPI); await nextTick(); wrapper.update(); @@ -181,6 +189,7 @@ describe('RoleMappingsGridPage', () => { it('allows role mappings to be deleted, refreshing the grid after', async () => { const roleMappingsAPI = roleMappingsAPIClientMock.create(); + const securityFeaturesAPI = securityFeaturesAPIClientMock.create(); roleMappingsAPI.getRoleMappings.mockResolvedValue([ { name: 'some-realm', @@ -189,8 +198,8 @@ describe('RoleMappingsGridPage', () => { rules: { field: { username: '*' } }, }, ]); - roleMappingsAPI.checkRoleMappingFeatures.mockResolvedValue({ - canManageRoleMappings: true, + securityFeaturesAPI.checkFeatures.mockResolvedValue({ + canReadSecurity: true, hasCompatibleRealms: true, }); roleMappingsAPI.deleteRoleMappings.mockResolvedValue([ @@ -200,7 +209,7 @@ describe('RoleMappingsGridPage', () => { }, ]); - const wrapper = renderView(roleMappingsAPI); + const wrapper = renderView(roleMappingsAPI, securityFeaturesAPI); await nextTick(); wrapper.update(); @@ -224,6 +233,7 @@ describe('RoleMappingsGridPage', () => { it('renders a warning when a mapping is assigned a deprecated role', async () => { const roleMappingsAPI = roleMappingsAPIClientMock.create(); + const securityFeaturesAPI = securityFeaturesAPIClientMock.create(); roleMappingsAPI.getRoleMappings.mockResolvedValue([ { name: 'some-realm', @@ -232,8 +242,8 @@ describe('RoleMappingsGridPage', () => { rules: { field: { username: '*' } }, }, ]); - roleMappingsAPI.checkRoleMappingFeatures.mockResolvedValue({ - canManageRoleMappings: true, + securityFeaturesAPI.checkFeatures.mockResolvedValue({ + canReadSecurity: true, hasCompatibleRealms: true, }); roleMappingsAPI.deleteRoleMappings.mockResolvedValue([ @@ -254,7 +264,7 @@ describe('RoleMappingsGridPage', () => { }, ]); - const wrapper = renderView(roleMappingsAPI, roleAPIClient); + const wrapper = renderView(roleMappingsAPI, securityFeaturesAPI, roleAPIClient); await nextTick(); wrapper.update(); @@ -269,6 +279,7 @@ describe('RoleMappingsGridPage', () => { it('renders role mapping actions as appropriate', async () => { const roleMappingsAPI = roleMappingsAPIClientMock.create(); + const securityFeaturesAPI = securityFeaturesAPIClientMock.create(); roleMappingsAPI.getRoleMappings.mockResolvedValue([ { name: 'some-realm', @@ -277,8 +288,8 @@ describe('RoleMappingsGridPage', () => { rules: { field: { username: '*' } }, }, ]); - roleMappingsAPI.checkRoleMappingFeatures.mockResolvedValue({ - canManageRoleMappings: true, + securityFeaturesAPI.checkFeatures.mockResolvedValue({ + canReadSecurity: true, hasCompatibleRealms: true, }); roleMappingsAPI.deleteRoleMappings.mockResolvedValue([ @@ -288,7 +299,7 @@ describe('RoleMappingsGridPage', () => { }, ]); - const wrapper = renderView(roleMappingsAPI); + const wrapper = renderView(roleMappingsAPI, securityFeaturesAPI); await nextTick(); wrapper.update(); @@ -315,13 +326,14 @@ describe('RoleMappingsGridPage', () => { describe('read-only', () => { it('renders an empty prompt when no role mappings exist', async () => { const roleMappingsAPI = roleMappingsAPIClientMock.create(); + const securityFeaturesAPI = securityFeaturesAPIClientMock.create(); roleMappingsAPI.getRoleMappings.mockResolvedValue([]); - roleMappingsAPI.checkRoleMappingFeatures.mockResolvedValue({ - canManageRoleMappings: true, + securityFeaturesAPI.checkFeatures.mockResolvedValue({ + canReadSecurity: true, hasCompatibleRealms: true, }); - const wrapper = renderView(roleMappingsAPI, undefined, true); + const wrapper = renderView(roleMappingsAPI, securityFeaturesAPI, undefined, true); expect(wrapper.find(SectionLoading)).toHaveLength(1); expect(wrapper.find(EmptyPrompt)).toHaveLength(0); @@ -342,6 +354,7 @@ describe('RoleMappingsGridPage', () => { it('hides controls when `readOnly` is enabled', async () => { const roleMappingsAPI = roleMappingsAPIClientMock.create(); + const securityFeaturesAPI = securityFeaturesAPIClientMock.create(); roleMappingsAPI.getRoleMappings.mockResolvedValue([ { name: 'some-realm', @@ -350,8 +363,8 @@ describe('RoleMappingsGridPage', () => { rules: { field: { username: '*' } }, }, ]); - roleMappingsAPI.checkRoleMappingFeatures.mockResolvedValue({ - canManageRoleMappings: true, + securityFeaturesAPI.checkFeatures.mockResolvedValue({ + canReadSecurity: true, hasCompatibleRealms: true, }); roleMappingsAPI.deleteRoleMappings.mockResolvedValue([ @@ -361,7 +374,7 @@ describe('RoleMappingsGridPage', () => { }, ]); - const wrapper = renderView(roleMappingsAPI, undefined, true); + const wrapper = renderView(roleMappingsAPI, securityFeaturesAPI, undefined, true); await nextTick(); wrapper.update(); diff --git a/x-pack/plugins/security/public/management/role_mappings/role_mappings_grid/role_mappings_grid_page.tsx b/x-pack/plugins/security/public/management/role_mappings/role_mappings_grid/role_mappings_grid_page.tsx index 4ddcb83abf7f3..9539fce203372 100644 --- a/x-pack/plugins/security/public/management/role_mappings/role_mappings_grid/role_mappings_grid_page.tsx +++ b/x-pack/plugins/security/public/management/role_mappings/role_mappings_grid/role_mappings_grid_page.tsx @@ -39,6 +39,7 @@ import { } from '../../management_urls'; import { RoleTableDisplay } from '../../role_table_display'; import type { RolesAPIClient } from '../../roles'; +import type { SecurityFeaturesAPIClient } from '../../security_features'; import { DeleteProvider, NoCompatibleRealms, @@ -50,6 +51,7 @@ import type { RoleMappingsAPIClient } from '../role_mappings_api_client'; interface Props { rolesAPIClient: PublicMethodsOf; roleMappingsAPI: PublicMethodsOf; + securityFeaturesAPI: PublicMethodsOf; notifications: NotificationsStart; docLinks: DocLinksStart; history: ScopedHistory; @@ -447,17 +449,15 @@ export class RoleMappingsGridPage extends Component { private async checkPrivileges() { try { - const { canManageRoleMappings, hasCompatibleRealms } = - await this.props.roleMappingsAPI.checkRoleMappingFeatures(); - - const canLoad = canManageRoleMappings || this.props.readOnly; + const { canReadSecurity, hasCompatibleRealms } = + await this.props.securityFeaturesAPI.checkFeatures(); this.setState({ - loadState: canLoad ? this.state.loadState : 'permissionDenied', + loadState: canReadSecurity ? this.state.loadState : 'permissionDenied', hasCompatibleRealms, }); - if (canLoad) { + if (canReadSecurity) { this.performInitialLoad(); } } catch (e) { diff --git a/x-pack/plugins/security/public/management/role_mappings/role_mappings_management_app.test.tsx b/x-pack/plugins/security/public/management/role_mappings/role_mappings_management_app.test.tsx index 2f0ad8f240fa3..94fb0de42543f 100644 --- a/x-pack/plugins/security/public/management/role_mappings/role_mappings_management_app.test.tsx +++ b/x-pack/plugins/security/public/management/role_mappings/role_mappings_management_app.test.tsx @@ -90,7 +90,7 @@ describe('roleMappingsManagementApp', () => { expect(docTitle.reset).not.toHaveBeenCalled(); expect(container).toMatchInlineSnapshot(`
- Role Mappings Page: {"notifications":{"toasts":{}},"rolesAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":"","assetsHrefBase":""},"anonymousPaths":{},"externalUrl":{},"staticAssets":{}}},"roleMappingsAPI":{"http":{"basePath":{"basePath":"","serverBasePath":"","assetsHrefBase":""},"anonymousPaths":{},"externalUrl":{},"staticAssets":{}}},"docLinks":{},"history":{"action":"PUSH","length":1,"location":{"pathname":"/","search":"","hash":""}},"readOnly":false} + Role Mappings Page: {"notifications":{"toasts":{}},"rolesAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":"","assetsHrefBase":""},"anonymousPaths":{},"externalUrl":{},"staticAssets":{}}},"roleMappingsAPI":{"http":{"basePath":{"basePath":"","serverBasePath":"","assetsHrefBase":""},"anonymousPaths":{},"externalUrl":{},"staticAssets":{}}},"securityFeaturesAPI":{"http":{"basePath":{"basePath":"","serverBasePath":"","assetsHrefBase":""},"anonymousPaths":{},"externalUrl":{},"staticAssets":{}}},"docLinks":{},"history":{"action":"PUSH","length":1,"location":{"pathname":"/","search":"","hash":""}},"readOnly":false}
`); @@ -112,7 +112,7 @@ describe('roleMappingsManagementApp', () => { expect(docTitle.reset).not.toHaveBeenCalled(); expect(container).toMatchInlineSnapshot(`
- Role Mappings Page: {"notifications":{"toasts":{}},"rolesAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":"","assetsHrefBase":""},"anonymousPaths":{},"externalUrl":{},"staticAssets":{}}},"roleMappingsAPI":{"http":{"basePath":{"basePath":"","serverBasePath":"","assetsHrefBase":""},"anonymousPaths":{},"externalUrl":{},"staticAssets":{}}},"docLinks":{},"history":{"action":"PUSH","length":1,"location":{"pathname":"/","search":"","hash":""}},"readOnly":true} + Role Mappings Page: {"notifications":{"toasts":{}},"rolesAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":"","assetsHrefBase":""},"anonymousPaths":{},"externalUrl":{},"staticAssets":{}}},"roleMappingsAPI":{"http":{"basePath":{"basePath":"","serverBasePath":"","assetsHrefBase":""},"anonymousPaths":{},"externalUrl":{},"staticAssets":{}}},"securityFeaturesAPI":{"http":{"basePath":{"basePath":"","serverBasePath":"","assetsHrefBase":""},"anonymousPaths":{},"externalUrl":{},"staticAssets":{}}},"docLinks":{},"history":{"action":"PUSH","length":1,"location":{"pathname":"/","search":"","hash":""}},"readOnly":true}
`); @@ -137,7 +137,7 @@ describe('roleMappingsManagementApp', () => { expect(docTitle.reset).not.toHaveBeenCalled(); expect(container).toMatchInlineSnapshot(`
- Role Mapping Edit Page: {"action":"edit","roleMappingsAPI":{"http":{"basePath":{"basePath":"","serverBasePath":"","assetsHrefBase":""},"anonymousPaths":{},"externalUrl":{},"staticAssets":{}}},"rolesAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":"","assetsHrefBase":""},"anonymousPaths":{},"externalUrl":{},"staticAssets":{}}},"notifications":{"toasts":{}},"docLinks":{},"history":{"action":"PUSH","length":1,"location":{"pathname":"/edit","search":"","hash":""}},"readOnly":false} + Role Mapping Edit Page: {"action":"edit","roleMappingsAPI":{"http":{"basePath":{"basePath":"","serverBasePath":"","assetsHrefBase":""},"anonymousPaths":{},"externalUrl":{},"staticAssets":{}}},"securityFeaturesAPI":{"http":{"basePath":{"basePath":"","serverBasePath":"","assetsHrefBase":""},"anonymousPaths":{},"externalUrl":{},"staticAssets":{}}},"rolesAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":"","assetsHrefBase":""},"anonymousPaths":{},"externalUrl":{},"staticAssets":{}}},"notifications":{"toasts":{}},"docLinks":{},"history":{"action":"PUSH","length":1,"location":{"pathname":"/edit","search":"","hash":""}},"readOnly":false}
`); @@ -167,7 +167,7 @@ describe('roleMappingsManagementApp', () => { expect(docTitle.reset).not.toHaveBeenCalled(); expect(container).toMatchInlineSnapshot(`
- Role Mapping Edit Page: {"action":"edit","name":"role@mapping","roleMappingsAPI":{"http":{"basePath":{"basePath":"","serverBasePath":"","assetsHrefBase":""},"anonymousPaths":{},"externalUrl":{},"staticAssets":{}}},"rolesAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":"","assetsHrefBase":""},"anonymousPaths":{},"externalUrl":{},"staticAssets":{}}},"notifications":{"toasts":{}},"docLinks":{},"history":{"action":"PUSH","length":1,"location":{"pathname":"/edit/role@mapping","search":"","hash":""}},"readOnly":false} + Role Mapping Edit Page: {"action":"edit","name":"role@mapping","roleMappingsAPI":{"http":{"basePath":{"basePath":"","serverBasePath":"","assetsHrefBase":""},"anonymousPaths":{},"externalUrl":{},"staticAssets":{}}},"securityFeaturesAPI":{"http":{"basePath":{"basePath":"","serverBasePath":"","assetsHrefBase":""},"anonymousPaths":{},"externalUrl":{},"staticAssets":{}}},"rolesAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":"","assetsHrefBase":""},"anonymousPaths":{},"externalUrl":{},"staticAssets":{}}},"notifications":{"toasts":{}},"docLinks":{},"history":{"action":"PUSH","length":1,"location":{"pathname":"/edit/role@mapping","search":"","hash":""}},"readOnly":false}
`); @@ -198,7 +198,7 @@ describe('roleMappingsManagementApp', () => { expect(docTitle.reset).not.toHaveBeenCalled(); expect(container).toMatchInlineSnapshot(`
- Role Mapping Edit Page: {"action":"edit","name":"role@mapping","roleMappingsAPI":{"http":{"basePath":{"basePath":"","serverBasePath":"","assetsHrefBase":""},"anonymousPaths":{},"externalUrl":{},"staticAssets":{}}},"rolesAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":"","assetsHrefBase":""},"anonymousPaths":{},"externalUrl":{},"staticAssets":{}}},"notifications":{"toasts":{}},"docLinks":{},"history":{"action":"PUSH","length":1,"location":{"pathname":"/edit/role@mapping","search":"","hash":""}},"readOnly":true} + Role Mapping Edit Page: {"action":"edit","name":"role@mapping","roleMappingsAPI":{"http":{"basePath":{"basePath":"","serverBasePath":"","assetsHrefBase":""},"anonymousPaths":{},"externalUrl":{},"staticAssets":{}}},"securityFeaturesAPI":{"http":{"basePath":{"basePath":"","serverBasePath":"","assetsHrefBase":""},"anonymousPaths":{},"externalUrl":{},"staticAssets":{}}},"rolesAPIClient":{"http":{"basePath":{"basePath":"","serverBasePath":"","assetsHrefBase":""},"anonymousPaths":{},"externalUrl":{},"staticAssets":{}}},"notifications":{"toasts":{}},"docLinks":{},"history":{"action":"PUSH","length":1,"location":{"pathname":"/edit/role@mapping","search":"","hash":""}},"readOnly":true}
`); diff --git a/x-pack/plugins/security/public/management/role_mappings/role_mappings_management_app.tsx b/x-pack/plugins/security/public/management/role_mappings/role_mappings_management_app.tsx index b3fc8ec71b890..d81fd1498417c 100644 --- a/x-pack/plugins/security/public/management/role_mappings/role_mappings_management_app.tsx +++ b/x-pack/plugins/security/public/management/role_mappings/role_mappings_management_app.tsx @@ -47,17 +47,20 @@ export const roleMappingsManagementApp = Object.freeze({ { EditRoleMappingPage }, { RoleMappingsAPIClient }, { RolesAPIClient }, + { SecurityFeaturesAPIClient }, ] = await Promise.all([ getStartServices(), import('./role_mappings_grid'), import('./edit_role_mapping'), import('./role_mappings_api_client'), import('../roles'), + import('../security_features'), ]); core.chrome.docTitle.change(title); const roleMappingsAPIClient = new RoleMappingsAPIClient(core.http); + const securityFeaturesAPIClient = new SecurityFeaturesAPIClient(core.http); const EditRoleMappingsPageWithBreadcrumbs = ({ action }: { action: 'edit' | 'clone' }) => { const { name } = useParams<{ name?: string }>(); @@ -81,6 +84,7 @@ export const roleMappingsManagementApp = Object.freeze({ action={action} name={decodedName} roleMappingsAPI={roleMappingsAPIClient} + securityFeaturesAPI={securityFeaturesAPIClient} rolesAPIClient={new RolesAPIClient(core.http)} notifications={core.notifications} docLinks={core.docLinks} @@ -114,6 +118,7 @@ export const roleMappingsManagementApp = Object.freeze({ notifications={core.notifications} rolesAPIClient={new RolesAPIClient(core.http)} roleMappingsAPI={roleMappingsAPIClient} + securityFeaturesAPI={securityFeaturesAPIClient} docLinks={core.docLinks} history={history} navigateToApp={core.application.navigateToApp} diff --git a/x-pack/plugins/security/public/management/roles/edit_role/edit_role_page.test.tsx b/x-pack/plugins/security/public/management/roles/edit_role/edit_role_page.test.tsx index 90246ccd6afe9..5f345020d6d8f 100644 --- a/x-pack/plugins/security/public/management/roles/edit_role/edit_role_page.test.tsx +++ b/x-pack/plugins/security/public/management/roles/edit_role/edit_role_page.test.tsx @@ -186,7 +186,7 @@ function getProps({ } return buildSpaces(); } - if (path === '/internal/security/_check_role_mapping_features') { + if (path === '/internal/security/_check_security_features') { return { canUseRemoteIndices }; } if (path === REMOTE_CLUSTERS_PATH) { @@ -541,6 +541,69 @@ describe('', () => { expectSaveFormButtons(wrapper); }); + it('can render a user defined role with description', async () => { + const wrapper = mountWithIntl( + + + + ); + + await waitForRender(wrapper); + + expect(wrapper.find('input[data-test-subj="roleFormDescriptionInput"]').prop('value')).toBe( + 'my custom role description' + ); + expect( + wrapper.find('input[data-test-subj="roleFormDescriptionInput"]').prop('disabled') + ).toBe(undefined); + expectSaveFormButtons(wrapper); + }); + + it('can render a reserved role with description', async () => { + const wrapper = mountWithIntl( + + + + ); + + await waitForRender(wrapper); + + expect(wrapper.find('[data-test-subj="roleFormDescriptionTooltip"]')).toHaveLength(1); + + expect(wrapper.find('input[data-test-subj="roleFormDescriptionInput"]').prop('value')).toBe( + 'my reserved role description' + ); + expect( + wrapper.find('input[data-test-subj="roleFormDescriptionInput"]').prop('disabled') + ).toBe(true); + }); + it('can render when creating a new role', async () => { const wrapper = mountWithIntl( diff --git a/x-pack/plugins/security/public/management/roles/edit_role/edit_role_page.tsx b/x-pack/plugins/security/public/management/roles/edit_role/edit_role_page.tsx index 56fb561443e82..060dc5a347fc4 100644 --- a/x-pack/plugins/security/public/management/roles/edit_role/edit_role_page.tsx +++ b/x-pack/plugins/security/public/management/roles/edit_role/edit_role_page.tsx @@ -18,6 +18,7 @@ import { EuiSpacer, EuiText, EuiTitle, + EuiToolTip, } from '@elastic/eui'; import type { ChangeEvent, FocusEvent, FunctionComponent, HTMLProps } from 'react'; import React, { Fragment, useCallback, useEffect, useRef, useState } from 'react'; @@ -68,7 +69,7 @@ import { prepareRoleClone, } from '../../../../common/model'; import { useCapabilities } from '../../../components/use_capabilities'; -import type { CheckRoleMappingFeaturesResponse } from '../../role_mappings/role_mappings_api_client'; +import type { CheckSecurityFeaturesResponse } from '../../security_features'; import type { UserAPIClient } from '../../users'; import type { IndicesAPIClient } from '../indices_api_client'; import { KibanaPrivileges } from '../model'; @@ -100,25 +101,23 @@ function useRemoteClusters(http: HttpStart) { return useAsync(() => http.get(REMOTE_CLUSTERS_PATH)); } -interface CheckRoleMappingFeaturesResponseWhenServerless { +interface CheckSecurityFeaturesResponseWhenServerless { value: boolean; } function useFeatureCheck( http: HttpStart, buildFlavor: 'serverless' -): AsyncState; +): AsyncState; function useFeatureCheck( http: HttpStart, buildFlavor: BuildFlavor -): AsyncState; +): AsyncState; function useFeatureCheck(http: HttpStart, buildFlavor?: BuildFlavor) { return useAsync(async () => { if (buildFlavor !== 'serverless') { - return http.get( - '/internal/security/_check_role_mapping_features' - ); + return http.get('/internal/security/_check_security_features'); } return { value: true }; }, [http, buildFlavor]); @@ -211,6 +210,7 @@ function useRole( ? rolesAPIClient.getRole(roleName) : Promise.resolve({ name: '', + description: '', elasticsearch: { cluster: [], indices: [], run_as: [], remote_cluster: [] }, kibana: [], _unrecognized_applications: [], @@ -452,45 +452,82 @@ export const EditRolePage: FunctionComponent = ({ return null; }; - const getRoleName = () => { + const getRoleNameAndDescription = () => { return ( - - } - helpText={ - !isEditingExistingRole ? ( - - ) : !isRoleReserved ? ( - + + + } + helpText={ + !isEditingExistingRole ? ( + + ) : !isRoleReserved ? ( + + ) : undefined + } + {...validator.validateRoleName(role)} + {...(creatingRoleAlreadyExists + ? { error: 'A role with this name already exists.', isInvalid: true } + : {})} + > + - ) : undefined - } - {...validator.validateRoleName(role)} - {...(creatingRoleAlreadyExists - ? { error: 'A role with this name already exists.', isInvalid: true } - : {})} - > - - + +
+ + + } + > + {isRoleReserved || isRoleReadOnly ? ( + + + + ) : ( + + )} + + +
); }; @@ -510,6 +547,12 @@ export const EditRolePage: FunctionComponent = ({ } }; + const onDescriptionChange = (e: ChangeEvent) => + setRole({ + ...role, + description: e.target.value.trim().length ? e.target.value : undefined, + }); + const getElasticsearchPrivileges = () => { return (
@@ -787,7 +830,7 @@ export const EditRolePage: FunctionComponent = ({ )} - {getRoleName()} + {getRoleNameAndDescription()} {getElasticsearchPrivileges()} {getKibanaPrivileges()} diff --git a/x-pack/plugins/security/public/management/roles/edit_role/validate_role.ts b/x-pack/plugins/security/public/management/roles/edit_role/validate_role.ts index bf85f80df1fc1..a425578ed98e5 100644 --- a/x-pack/plugins/security/public/management/roles/edit_role/validate_role.ts +++ b/x-pack/plugins/security/public/management/roles/edit_role/validate_role.ts @@ -85,7 +85,6 @@ export class RoleValidator { } return valid(); } - public validateRemoteClusterPrivileges(role: Role): RoleValidationResult { if (!this.shouldValidate) { return valid(); diff --git a/x-pack/plugins/security/public/management/roles/roles_grid/roles_grid_page.test.tsx b/x-pack/plugins/security/public/management/roles/roles_grid/roles_grid_page.test.tsx index ed6f28ea8321f..6b666cfd378f4 100644 --- a/x-pack/plugins/security/public/management/roles/roles_grid/roles_grid_page.test.tsx +++ b/x-pack/plugins/security/public/management/roles/roles_grid/roles_grid_page.test.tsx @@ -56,6 +56,12 @@ describe('', () => { elasticsearch: { cluster: [], indices: [], run_as: [] }, kibana: [{ base: [], spaces: [], feature: {} }], }, + { + name: 'test-role-with-description', + description: 'role-description', + elasticsearch: { cluster: [], indices: [], run_as: [] }, + kibana: [{ base: [], spaces: [], feature: {} }], + }, { name: 'reserved-role', elasticsearch: { cluster: [], indices: [], run_as: [] }, @@ -162,6 +168,10 @@ describe('', () => { expect(wrapper.find('a[data-test-subj="edit-role-action-disabled-role"]')).toHaveLength(1); expect(wrapper.find('a[data-test-subj="clone-role-action-disabled-role"]')).toHaveLength(1); + + expect(findTestSubject(wrapper, 'roleRowDescription-test-role-with-description')).toHaveLength( + 1 + ); }); it('hides reserved roles when instructed to', async () => { @@ -201,6 +211,12 @@ describe('', () => { elasticsearch: { cluster: [], indices: [], run_as: [] }, kibana: [{ base: [], spaces: [], feature: {} }], }, + { + name: 'test-role-with-description', + description: 'role-description', + elasticsearch: { cluster: [], indices: [], run_as: [] }, + kibana: [{ base: [], spaces: [], feature: {} }], + }, ]); findTestSubject(wrapper, 'showReservedRolesSwitch').simulate('click'); @@ -222,6 +238,12 @@ describe('', () => { elasticsearch: { cluster: [], indices: [], run_as: [] }, kibana: [{ base: [], spaces: [], feature: {} }], }, + { + name: 'test-role-with-description', + description: 'role-description', + elasticsearch: { cluster: [], indices: [], run_as: [] }, + kibana: [{ base: [], spaces: [], feature: {} }], + }, ]); }); diff --git a/x-pack/plugins/security/public/management/roles/roles_grid/roles_grid_page.tsx b/x-pack/plugins/security/public/management/roles/roles_grid/roles_grid_page.tsx index a21d0a1e99912..bb87cc61b0f84 100644 --- a/x-pack/plugins/security/public/management/roles/roles_grid/roles_grid_page.tsx +++ b/x-pack/plugins/security/public/management/roles/roles_grid/roles_grid_page.tsx @@ -17,6 +17,7 @@ import { EuiSpacer, EuiSwitch, EuiText, + EuiToolTip, } from '@elastic/eui'; import _ from 'lodash'; import React, { Component } from 'react'; @@ -183,7 +184,6 @@ export class RolesGridPage extends Component { { ); }, }, + { + field: 'description', + name: i18n.translate('xpack.security.management.roles.descriptionColumnName', { + defaultMessage: 'Role Description', + }), + sortable: true, + truncateText: { lines: 3 }, + render: (description: string, record: Role) => { + return ( + + + {description} + + + ); + }, + }, ]; if (this.props.buildFlavor !== 'serverless') { config.push({ diff --git a/x-pack/plugins/security/public/management/security_features/index.ts b/x-pack/plugins/security/public/management/security_features/index.ts new file mode 100644 index 0000000000000..e1e65c9216275 --- /dev/null +++ b/x-pack/plugins/security/public/management/security_features/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 { SecurityFeaturesAPIClient } from './security_features_api_client'; +export type { CheckSecurityFeaturesResponse } from './security_features_api_client'; diff --git a/x-pack/plugins/security/public/management/security_features/security_features_api_client.mock.ts b/x-pack/plugins/security/public/management/security_features/security_features_api_client.mock.ts new file mode 100644 index 0000000000000..41b234adc10f8 --- /dev/null +++ b/x-pack/plugins/security/public/management/security_features/security_features_api_client.mock.ts @@ -0,0 +1,12 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export const securityFeaturesAPIClientMock = { + create: () => ({ + checkFeatures: jest.fn(), + }), +}; diff --git a/x-pack/plugins/security/public/management/security_features/security_features_api_client.ts b/x-pack/plugins/security/public/management/security_features/security_features_api_client.ts new file mode 100644 index 0000000000000..ededbdcc251ea --- /dev/null +++ b/x-pack/plugins/security/public/management/security_features/security_features_api_client.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 { HttpStart } from '@kbn/core/public'; + +export interface CheckSecurityFeaturesResponse { + canReadSecurity: boolean; + canUseInlineScripts: boolean; + canUseStoredScripts: boolean; + hasCompatibleRealms: boolean; + canUseRemoteIndices: boolean; + canUseRemoteClusters: boolean; +} + +export class SecurityFeaturesAPIClient { + constructor(private readonly http: HttpStart) {} + + public async checkFeatures(): Promise { + return this.http.get(`/internal/security/_check_security_features`); + } +} diff --git a/x-pack/plugins/security/server/routes/role_mapping/feature_check.test.ts b/x-pack/plugins/security/server/routes/feature_check/feature_check.test.ts similarity index 89% rename from x-pack/plugins/security/server/routes/role_mapping/feature_check.test.ts rename to x-pack/plugins/security/server/routes/feature_check/feature_check.test.ts index c0bf0041ed0ac..953f65afa9a7c 100644 --- a/x-pack/plugins/security/server/routes/role_mapping/feature_check.test.ts +++ b/x-pack/plugins/security/server/routes/feature_check/feature_check.test.ts @@ -9,12 +9,12 @@ import { kibanaResponseFactory } from '@kbn/core/server'; import { coreMock, httpServerMock } from '@kbn/core/server/mocks'; import type { LicenseCheck } from '@kbn/licensing-plugin/server'; -import { defineRoleMappingFeatureCheckRoute } from './feature_check'; +import { defineSecurityFeatureCheckRoute } from './feature_check'; import { routeDefinitionParamsMock } from '../index.mock'; interface TestOptions { licenseCheckResult?: LicenseCheck; - canManageRoleMappings?: boolean; + canReadSecurity?: boolean; nodeSettingsResponse?: () => Record; xpackUsageResponse?: () => Record; asserts: { statusCode: number; result?: Record }; @@ -43,7 +43,7 @@ describe('GET role mappings feature check', () => { description: string, { licenseCheckResult = { state: 'valid' }, - canManageRoleMappings = true, + canReadSecurity = true, nodeSettingsResponse = () => ({}), xpackUsageResponse = () => defaultXpackUsageResponse, asserts, @@ -68,16 +68,16 @@ describe('GET role mappings feature check', () => { (async () => xpackUsageResponse()) as any ); mockCoreContext.elasticsearch.client.asCurrentUser.security.hasPrivileges.mockResolvedValue({ - has_all_requested: canManageRoleMappings, + has_all_requested: canReadSecurity, } as any); - defineRoleMappingFeatureCheckRoute(mockRouteDefinitionParams); + defineSecurityFeatureCheckRoute(mockRouteDefinitionParams); const [[, handler]] = mockRouteDefinitionParams.router.get.mock.calls; const headers = { authorization: 'foo' }; const mockRequest = httpServerMock.createKibanaRequest({ method: 'get', - path: `/internal/security/_check_role_mapping_features`, + path: `/internal/security/_check_security_features`, headers, }); @@ -93,7 +93,7 @@ describe('GET role mappings feature check', () => { asserts: { statusCode: 200, result: { - canManageRoleMappings: true, + canReadSecurity: true, canUseInlineScripts: true, canUseStoredScripts: true, hasCompatibleRealms: true, @@ -118,7 +118,7 @@ describe('GET role mappings feature check', () => { asserts: { statusCode: 200, result: { - canManageRoleMappings: true, + canReadSecurity: true, canUseInlineScripts: true, canUseStoredScripts: true, hasCompatibleRealms: true, @@ -138,7 +138,7 @@ describe('GET role mappings feature check', () => { asserts: { statusCode: 200, result: { - canManageRoleMappings: true, + canReadSecurity: true, canUseInlineScripts: true, canUseStoredScripts: true, hasCompatibleRealms: true, @@ -164,7 +164,7 @@ describe('GET role mappings feature check', () => { asserts: { statusCode: 200, result: { - canManageRoleMappings: true, + canReadSecurity: true, canUseInlineScripts: true, canUseStoredScripts: false, hasCompatibleRealms: true, @@ -189,7 +189,7 @@ describe('GET role mappings feature check', () => { asserts: { statusCode: 200, result: { - canManageRoleMappings: true, + canReadSecurity: true, canUseInlineScripts: false, canUseStoredScripts: true, hasCompatibleRealms: true, @@ -218,7 +218,7 @@ describe('GET role mappings feature check', () => { asserts: { statusCode: 200, result: { - canManageRoleMappings: true, + canReadSecurity: true, canUseInlineScripts: true, canUseStoredScripts: true, hasCompatibleRealms: false, @@ -228,12 +228,12 @@ describe('GET role mappings feature check', () => { }, }); - getFeatureCheckTest('indicates canManageRoleMappings=false for users without `manage_security`', { - canManageRoleMappings: false, + getFeatureCheckTest('indicates canReadSecurity=false for users without `read_security`', { + canReadSecurity: false, asserts: { statusCode: 200, result: { - canManageRoleMappings: false, + canReadSecurity: false, }, }, }); @@ -250,7 +250,7 @@ describe('GET role mappings feature check', () => { asserts: { statusCode: 200, result: { - canManageRoleMappings: true, + canReadSecurity: true, canUseInlineScripts: true, canUseStoredScripts: true, hasCompatibleRealms: false, diff --git a/x-pack/plugins/security/server/routes/role_mapping/feature_check.ts b/x-pack/plugins/security/server/routes/feature_check/feature_check.ts similarity index 80% rename from x-pack/plugins/security/server/routes/role_mapping/feature_check.ts rename to x-pack/plugins/security/server/routes/feature_check/feature_check.ts index 6aca083dab1e2..442f040398962 100644 --- a/x-pack/plugins/security/server/routes/role_mapping/feature_check.ts +++ b/x-pack/plugins/security/server/routes/feature_check/feature_check.ts @@ -39,49 +39,49 @@ interface XPackUsageResponse { const INCOMPATIBLE_REALMS = ['file', 'native']; -export function defineRoleMappingFeatureCheckRoute({ router, logger }: RouteDefinitionParams) { +export function defineSecurityFeatureCheckRoute({ router, logger }: RouteDefinitionParams) { router.get( { - path: '/internal/security/_check_role_mapping_features', + path: '/internal/security/_check_security_features', validate: false, }, createLicensedRouteHandler(async (context, request, response) => { const esClient = (await context.core).elasticsearch.client; - const { has_all_requested: canManageRoleMappings } = + const { has_all_requested: canReadSecurity } = await esClient.asCurrentUser.security.hasPrivileges({ - body: { cluster: ['manage_security'] }, + body: { cluster: ['read_security'] }, }); - if (!canManageRoleMappings) { + if (!canReadSecurity) { return response.ok({ body: { - canManageRoleMappings, + canReadSecurity, }, }); } - const enabledFeatures = await getEnabledRoleMappingsFeatures(esClient.asInternalUser, logger); + const enabledFeatures = await getEnabledSecurityFeatures(esClient.asInternalUser, logger); return response.ok({ body: { ...enabledFeatures, - canManageRoleMappings, + canReadSecurity, }, }); }) ); } -async function getEnabledRoleMappingsFeatures(esClient: ElasticsearchClient, logger: Logger) { - logger.debug(`Retrieving role mappings features`); +async function getEnabledSecurityFeatures(esClient: ElasticsearchClient, logger: Logger) { + logger.debug(`Retrieving security features`); const nodeScriptSettingsPromise = esClient.nodes .info({ filter_path: 'nodes.*.settings.script' }) .catch((error) => { // fall back to assuming that node settings are unset/at their default values. - // this will allow the role mappings UI to permit both role template script types, + // this will allow the UI to permit both role template script types, // even if ES will disallow it at mapping evaluation time. - logger.error(`Error retrieving node settings for role mappings: ${error}`); + logger.error(`Error retrieving node settings for security feature check: ${error}`); return {}; }); @@ -94,7 +94,7 @@ async function getEnabledRoleMappingsFeatures(esClient: ElasticsearchClient, log // fall back to no external realms configured. // this will cause a warning in the UI about no compatible realms being enabled, but will otherwise allow // the mappings screen to function correctly. - logger.error(`Error retrieving XPack usage info for role mappings: ${error}`); + logger.error(`Error retrieving XPack usage info for security feature check: ${error}`); return { security: { realms: {}, diff --git a/x-pack/plugins/security/server/routes/feature_check/index.ts b/x-pack/plugins/security/server/routes/feature_check/index.ts new file mode 100644 index 0000000000000..b482139fd83d5 --- /dev/null +++ b/x-pack/plugins/security/server/routes/feature_check/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. + */ + +import { defineSecurityFeatureCheckRoute } from './feature_check'; +import type { RouteDefinitionParams } from '..'; + +export function defineSecurityFeatureRoutes(params: RouteDefinitionParams) { + defineSecurityFeatureCheckRoute(params); +} diff --git a/x-pack/plugins/security/server/routes/index.ts b/x-pack/plugins/security/server/routes/index.ts index 99739208e6b7a..212cf6768d1aa 100644 --- a/x-pack/plugins/security/server/routes/index.ts +++ b/x-pack/plugins/security/server/routes/index.ts @@ -18,6 +18,7 @@ import { defineApiKeysRoutes } from './api_keys'; import { defineAuthenticationRoutes } from './authentication'; import { defineAuthorizationRoutes } from './authorization'; import { defineDeprecationsRoutes } from './deprecations'; +import { defineSecurityFeatureRoutes } from './feature_check'; import { defineIndicesRoutes } from './indices'; import { defineRoleMappingRoutes } from './role_mapping'; import { defineSecurityCheckupGetStateRoutes } from './security_checkup'; @@ -74,6 +75,7 @@ export function defineRoutes(params: RouteDefinitionParams) { defineDeprecationsRoutes(params); // deprecated kibana user roles are not applicable, these HTTP APIs are not needed defineIndicesRoutes(params); // the ES privileges form used to help define roles (only consumer) is disabled, so there is no need for these HTTP APIs defineRoleMappingRoutes(params); // role mappings are managed internally, based on configurations in control plane, these HTTP APIs are not needed + defineSecurityFeatureRoutes(params); defineSecurityCheckupGetStateRoutes(params); // security checkup is not applicable, these HTTP APIs are not needed // defineUsersRoutes(params); // the native realm is not enabled (there is only Elastic cloud SAML), no user HTTP API routes are needed } diff --git a/x-pack/plugins/security/server/routes/role_mapping/index.ts b/x-pack/plugins/security/server/routes/role_mapping/index.ts index 49ad928c0b7e4..46db773ded991 100644 --- a/x-pack/plugins/security/server/routes/role_mapping/index.ts +++ b/x-pack/plugins/security/server/routes/role_mapping/index.ts @@ -6,13 +6,11 @@ */ import { defineRoleMappingDeleteRoutes } from './delete'; -import { defineRoleMappingFeatureCheckRoute } from './feature_check'; import { defineRoleMappingGetRoutes } from './get'; import { defineRoleMappingPostRoutes } from './post'; import type { RouteDefinitionParams } from '..'; export function defineRoleMappingRoutes(params: RouteDefinitionParams) { - defineRoleMappingFeatureCheckRoute(params); defineRoleMappingGetRoutes(params); defineRoleMappingPostRoutes(params); defineRoleMappingDeleteRoutes(params); diff --git a/x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema/common_attributes.gen.ts b/x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema/common_attributes.gen.ts index 6b6bc018c8e5c..ac6eb3dd18a7e 100644 --- a/x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema/common_attributes.gen.ts +++ b/x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema/common_attributes.gen.ts @@ -303,13 +303,40 @@ export const TimestampOverride = z.string(); export type TimestampOverrideFallbackDisabled = z.infer; export const TimestampOverrideFallbackDisabled = z.boolean(); +/** + * Describes an Elasticsearch field that is needed for the rule to function + */ export type RequiredField = z.infer; export const RequiredField = z.object({ + /** + * Name of an Elasticsearch field + */ name: NonEmptyString, + /** + * Type of the Elasticsearch field + */ type: NonEmptyString, + /** + * Whether the field is an ECS field + */ ecs: z.boolean(), }); +/** + * Input parameters to create a RequiredField. Does not include the `ecs` field, because `ecs` is calculated on the backend based on the field name and type. + */ +export type RequiredFieldInput = z.infer; +export const RequiredFieldInput = z.object({ + /** + * Name of an Elasticsearch field + */ + name: NonEmptyString, + /** + * Type of an Elasticsearch field + */ + type: NonEmptyString, +}); + export type RequiredFieldArray = z.infer; export const RequiredFieldArray = z.array(RequiredField); diff --git a/x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema/common_attributes.schema.yaml b/x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema/common_attributes.schema.yaml index fadb38ef1ce5f..cd5e238723f6a 100644 --- a/x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema/common_attributes.schema.yaml +++ b/x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema/common_attributes.schema.yaml @@ -315,18 +315,36 @@ components: RequiredField: type: object + description: Describes an Elasticsearch field that is needed for the rule to function properties: name: $ref: '../../../model/primitives.schema.yaml#/components/schemas/NonEmptyString' + description: Name of an Elasticsearch field type: $ref: '../../../model/primitives.schema.yaml#/components/schemas/NonEmptyString' + description: Type of the Elasticsearch field ecs: type: boolean + description: Whether the field is an ECS field required: - name - type - ecs + RequiredFieldInput: + type: object + description: Input parameters to create a RequiredField. Does not include the `ecs` field, because `ecs` is calculated on the backend based on the field name and type. + properties: + name: + $ref: '../../../model/primitives.schema.yaml#/components/schemas/NonEmptyString' + description: Name of an Elasticsearch field + type: + $ref: '../../../model/primitives.schema.yaml#/components/schemas/NonEmptyString' + description: Type of an Elasticsearch field + required: + - name + - type + RequiredFieldArray: type: array items: diff --git a/x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema/rule_schemas.gen.ts b/x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema/rule_schemas.gen.ts index d05a272337534..d2523a9a5c557 100644 --- a/x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema/rule_schemas.gen.ts +++ b/x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema/rule_schemas.gen.ts @@ -54,6 +54,7 @@ import { ThreatArray, SetupGuide, RelatedIntegrationArray, + RequiredFieldInput, RuleObjectId, RuleSignatureId, IsRuleImmutable, @@ -137,6 +138,7 @@ export const BaseDefaultableFields = z.object({ threat: ThreatArray.optional(), setup: SetupGuide.optional(), related_integrations: RelatedIntegrationArray.optional(), + required_fields: z.array(RequiredFieldInput).optional(), }); export type BaseCreateProps = z.infer; diff --git a/x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema/rule_schemas.schema.yaml b/x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema/rule_schemas.schema.yaml index f8998624f99b1..ae1a5657d2ab4 100644 --- a/x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema/rule_schemas.schema.yaml +++ b/x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema/rule_schemas.schema.yaml @@ -117,12 +117,15 @@ components: author: $ref: './common_attributes.schema.yaml#/components/schemas/RuleAuthorArray' + # False positive examples false_positives: $ref: './common_attributes.schema.yaml#/components/schemas/RuleFalsePositiveArray' + # Reference URLs references: $ref: './common_attributes.schema.yaml#/components/schemas/RuleReferenceArray' + # Max alerts per run max_signals: $ref: './common_attributes.schema.yaml#/components/schemas/MaxSignals' threat: @@ -130,9 +133,16 @@ components: setup: $ref: './common_attributes.schema.yaml#/components/schemas/SetupGuide' + # Related integrations related_integrations: $ref: './common_attributes.schema.yaml#/components/schemas/RelatedIntegrationArray' + # Required fields + required_fields: + type: array + items: + $ref: './common_attributes.schema.yaml#/components/schemas/RequiredFieldInput' + BaseCreateProps: x-inline: true allOf: diff --git a/x-pack/plugins/security_solution/common/api/detection_engine/rule_management/import_rules/rule_to_import.ts b/x-pack/plugins/security_solution/common/api/detection_engine/rule_management/import_rules/rule_to_import.ts index 9634d773b121d..9dc1e218f6ceb 100644 --- a/x-pack/plugins/security_solution/common/api/detection_engine/rule_management/import_rules/rule_to_import.ts +++ b/x-pack/plugins/security_solution/common/api/detection_engine/rule_management/import_rules/rule_to_import.ts @@ -9,6 +9,7 @@ import * as z from 'zod'; import { BaseCreateProps, ResponseFields, + RequiredFieldInput, RuleSignatureId, TypeSpecificCreateProps, } from '../../model/rule_schema'; @@ -29,5 +30,13 @@ export const RuleToImport = BaseCreateProps.and(TypeSpecificCreateProps).and( ResponseFields.partial().extend({ rule_id: RuleSignatureId, immutable: z.literal(false).default(false), + /* + Overriding `required_fields` from ResponseFields because + in ResponseFields `required_fields` has the output type, + but for importing rules, we need to use the input type. + Otherwise importing rules without the "ecs" property in + `required_fields` will fail. + */ + required_fields: z.array(RequiredFieldInput).optional(), }) ); diff --git a/x-pack/plugins/security_solution/common/endpoint/types/index.ts b/x-pack/plugins/security_solution/common/endpoint/types/index.ts index 7eed9b47fb2d3..7b33c5a3606a5 100644 --- a/x-pack/plugins/security_solution/common/endpoint/types/index.ts +++ b/x-pack/plugins/security_solution/common/endpoint/types/index.ts @@ -1123,7 +1123,7 @@ export interface BlocklistFields { } export interface OnWriteScanFields { - on_write_scan?: boolean; + on_write_scan: boolean; } /** Policy protection mode options */ diff --git a/x-pack/plugins/security_solution/common/entity_analytics/risk_engine/constants.ts b/x-pack/plugins/security_solution/common/entity_analytics/risk_engine/constants.ts index dc23dceadd642..5a0a6541791ba 100644 --- a/x-pack/plugins/security_solution/common/entity_analytics/risk_engine/constants.ts +++ b/x-pack/plugins/security_solution/common/entity_analytics/risk_engine/constants.ts @@ -23,7 +23,8 @@ export const RISK_ENGINE_REQUIRED_ES_CLUSTER_PRIVILEGES = [ export const RISK_SCORE_INDEX_PATTERN = 'risk-score.risk-score-*'; -type RiskEngineIndexPrivilege = 'read' | 'write'; +export type RiskEngineIndexPrivilege = 'read' | 'write'; + export const RISK_ENGINE_REQUIRED_ES_INDEX_PRIVILEGES = Object.freeze({ [RISK_SCORE_INDEX_PATTERN]: ['read', 'write'] as RiskEngineIndexPrivilege[], }); diff --git a/x-pack/plugins/security_solution/common/entity_analytics/risk_engine/privileges.ts b/x-pack/plugins/security_solution/common/entity_analytics/risk_engine/privileges.ts index a375f5cb9195b..b0bbc39609b3b 100644 --- a/x-pack/plugins/security_solution/common/entity_analytics/risk_engine/privileges.ts +++ b/x-pack/plugins/security_solution/common/entity_analytics/risk_engine/privileges.ts @@ -5,7 +5,9 @@ * 2.0. */ +import type { NonEmptyArray } from 'fp-ts/NonEmptyArray'; import type { EntityAnalyticsPrivileges } from '../../api/entity_analytics/asset_criticality/get_asset_criticality_privileges.gen'; +import type { RiskEngineIndexPrivilege } from './constants'; import { RISK_ENGINE_REQUIRED_ES_CLUSTER_PRIVILEGES, RISK_ENGINE_REQUIRED_ES_INDEX_PRIVILEGES, @@ -20,7 +22,8 @@ export interface MissingPrivileges { } export const getMissingIndexPrivileges = ( - privileges: EntityAnalyticsPrivileges['privileges']['elasticsearch']['index'] + privileges: EntityAnalyticsPrivileges['privileges']['elasticsearch']['index'], + required: NonEmptyArray = ['read', 'write'] ): MissingIndexPrivileges => { const missingIndexPrivileges: MissingIndexPrivileges = []; @@ -28,10 +31,10 @@ export const getMissingIndexPrivileges = ( return missingIndexPrivileges; } - for (const [indexName, requiredPrivileges] of Object.entries( + for (const [indexName, defaultRequiredPrivileges] of Object.entries( RISK_ENGINE_REQUIRED_ES_INDEX_PRIVILEGES )) { - const missingPrivileges = requiredPrivileges.filter( + const missingPrivileges = (required || defaultRequiredPrivileges).filter( (privilege) => !privileges[indexName][privilege] ); @@ -44,9 +47,13 @@ export const getMissingIndexPrivileges = ( }; export const getMissingRiskEnginePrivileges = ( - privileges: EntityAnalyticsPrivileges['privileges'] + privileges: EntityAnalyticsPrivileges['privileges'], + required?: NonEmptyArray ): MissingPrivileges => { - const missingIndexPrivileges = getMissingIndexPrivileges(privileges.elasticsearch.index); + const missingIndexPrivileges = getMissingIndexPrivileges( + privileges.elasticsearch.index, + required + ); const missingClusterPrivileges = RISK_ENGINE_REQUIRED_ES_CLUSTER_PRIVILEGES.filter( (privilege) => !privileges.elasticsearch.cluster?.[privilege] ); diff --git a/x-pack/plugins/security_solution/common/experimental_features.ts b/x-pack/plugins/security_solution/common/experimental_features.ts index 84d1061f9eda9..4b083b4034385 100644 --- a/x-pack/plugins/security_solution/common/experimental_features.ts +++ b/x-pack/plugins/security_solution/common/experimental_features.ts @@ -255,7 +255,12 @@ export const allowedExperimentalValues = Object.freeze({ /** * Makes Elastic Defend integration's Malware On-Write Scan option available to edit. */ - malwareOnWriteScanOptionAvailable: false, + malwareOnWriteScanOptionAvailable: true, + + /** + * Enables unified manifest that replaces existing user artifacts manifest SO with a new approach of creating a SO per package policy. + */ + unifiedManifestEnabled: false, /** * Enables Security AI Assistant's Flyout mode diff --git a/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/view_in_ai_assistant/use_view_in_ai_assistant.ts b/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/view_in_ai_assistant/use_view_in_ai_assistant.ts index 228f882863777..58f66b1b2a0dd 100644 --- a/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/view_in_ai_assistant/use_view_in_ai_assistant.ts +++ b/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/view_in_ai_assistant/use_view_in_ai_assistant.ts @@ -12,8 +12,6 @@ import { useAssistantAvailability } from '../../../assistant/use_assistant_avail import { getAttackDiscoveryMarkdown } from '../../get_attack_discovery_markdown/get_attack_discovery_markdown'; import type { AttackDiscovery } from '../../types'; -const useAssistantNoop = () => ({ promptContextId: undefined, showAssistantOverlay: () => {} }); - /** * This category is provided in the prompt context for the assistant */ @@ -25,12 +23,7 @@ export const useViewInAiAssistant = ({ attackDiscovery: AttackDiscovery; replacements?: Replacements; }) => { - const { hasAssistantPrivilege } = useAssistantAvailability(); - - const useAssistantHook = useMemo( - () => (hasAssistantPrivilege ? useAssistantOverlay : useAssistantNoop), - [hasAssistantPrivilege] - ); + const { hasAssistantPrivilege, isAssistantEnabled } = useAssistantAvailability(); // the prompt context for this insight: const getPromptContext = useCallback( @@ -41,7 +34,7 @@ export const useViewInAiAssistant = ({ }), [attackDiscovery] ); - const { promptContextId, showAssistantOverlay: showOverlay } = useAssistantHook( + const { promptContextId, showAssistantOverlay: showOverlay } = useAssistantOverlay( category, attackDiscovery.title, // conversation title attackDiscovery.title, // description used in context pill @@ -49,6 +42,7 @@ export const useViewInAiAssistant = ({ attackDiscovery.id, // accept the UUID default for this prompt context null, // suggestedUserPrompt null, // tooltip + isAssistantEnabled, replacements ?? null ); diff --git a/x-pack/plugins/security_solution/public/attack_discovery/pages/loading_callout/countdown/index.tsx b/x-pack/plugins/security_solution/public/attack_discovery/pages/loading_callout/countdown/index.tsx index e49050c54c954..8a61704ef7361 100644 --- a/x-pack/plugins/security_solution/public/attack_discovery/pages/loading_callout/countdown/index.tsx +++ b/x-pack/plugins/security_solution/public/attack_discovery/pages/loading_callout/countdown/index.tsx @@ -9,6 +9,7 @@ import { EuiButtonIcon, EuiFlexGroup, EuiFlexItem, + EuiOutsideClickDetector, EuiPopover, EuiText, useEuiTheme, @@ -80,15 +81,17 @@ const CountdownComponent: React.FC = ({ approximateFutureTime, connectorI justifyContent="spaceBetween" > - - - + closePopover()}> + + + + diff --git a/x-pack/plugins/security_solution/public/attack_discovery/pages/session_storage/index.test.ts b/x-pack/plugins/security_solution/public/attack_discovery/pages/session_storage/index.test.ts new file mode 100644 index 0000000000000..dd5932bbb3dd7 --- /dev/null +++ b/x-pack/plugins/security_solution/public/attack_discovery/pages/session_storage/index.test.ts @@ -0,0 +1,180 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license 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 { GenerationInterval } from '../../types'; +import { + encodeGenerationIntervals, + decodeGenerationIntervals, + getLocalStorageGenerationIntervals, + setLocalStorageGenerationIntervals, +} from '.'; + +const key = 'elasticAssistantDefault.attackDiscovery.default.generationIntervals'; + +const generationIntervals: Record = { + 'test-connector-1': [ + { + connectorId: 'test-connector-1', + date: new Date('2024-05-16T14:13:09.838Z'), + durationMs: 173648, + }, + { + connectorId: 'test-connector-1', + date: new Date('2024-05-16T13:59:49.620Z'), + durationMs: 146605, + }, + { + connectorId: 'test-connector-1', + date: new Date('2024-05-16T13:47:00.629Z'), + durationMs: 255163, + }, + ], + testConnector2: [ + { + connectorId: 'testConnector2', + date: new Date('2024-05-16T14:26:25.273Z'), + durationMs: 130447, + }, + ], + testConnector3: [ + { + connectorId: 'testConnector3', + date: new Date('2024-05-16T14:36:53.171Z'), + durationMs: 46614, + }, + { + connectorId: 'testConnector3', + date: new Date('2024-05-16T14:27:17.187Z'), + durationMs: 44129, + }, + ], +}; + +describe('storage', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + describe('encodeGenerationIntervals', () => { + it('returns null when generationIntervals is invalid', () => { + const invalidGenerationIntervals: Record = + 1n as unknown as Record; // <-- invalid + + const result = encodeGenerationIntervals(invalidGenerationIntervals); + + expect(result).toBeNull(); + }); + + it('returns the expected encoded generationIntervals', () => { + const result = encodeGenerationIntervals(generationIntervals); + + expect(result).toEqual(JSON.stringify(generationIntervals)); + }); + }); + + describe('decodeGenerationIntervals', () => { + it('returns null when generationIntervals is invalid', () => { + const invalidGenerationIntervals = 'invalid generation intervals'; // <-- invalid + + const result = decodeGenerationIntervals(invalidGenerationIntervals); + + expect(result).toBeNull(); + }); + + it('returns the expected decoded generation intervals', () => { + const encoded = encodeGenerationIntervals(generationIntervals) ?? ''; // <-- valid intervals + + const result = decodeGenerationIntervals(encoded); + + expect(result).toEqual(generationIntervals); + }); + + it('parses date strings into Date objects', () => { + const encoded = JSON.stringify({ + 'test-connector-1': [ + { + connectorId: 'test-connector-1', + date: '2024-05-16T14:13:09.838Z', + durationMs: 173648, + }, + ], + }); + + const result = decodeGenerationIntervals(encoded); + + expect(result).toEqual({ + 'test-connector-1': [ + { + connectorId: 'test-connector-1', + date: new Date('2024-05-16T14:13:09.838Z'), + durationMs: 173648, + }, + ], + }); + }); + + it('returns null when date is not a string', () => { + const encoded = JSON.stringify({ + 'test-connector-1': [ + { + connectorId: 'test-connector-1', + date: 1234, // <-- invalid + durationMs: 173648, + }, + ], + }); + + const result = decodeGenerationIntervals(encoded); + + expect(result).toBeNull(); + }); + }); + + describe('getLocalStorageGenerationIntervals', () => { + it('returns null when the key is empty', () => { + const result = getLocalStorageGenerationIntervals(''); // <-- empty key + + expect(result).toBeNull(); + }); + + it('returns null the key is unknown', () => { + const result = getLocalStorageGenerationIntervals('unknown key'); // <-- unknown key + + expect(result).toBeNull(); + }); + + it('returns null when the generation intervals are invalid', () => { + localStorage.setItem(key, 'invalid generation intervals'); // <-- invalid + + const result = getLocalStorageGenerationIntervals(key); + + expect(result).toBeNull(); + }); + + it('returns the expected decoded generation intervals', () => { + const encoded = encodeGenerationIntervals(generationIntervals) ?? ''; // <-- valid intervals + localStorage.setItem(key, encoded); + + const decoded = decodeGenerationIntervals(encoded); + const result = getLocalStorageGenerationIntervals(key); + + expect(result).toEqual(decoded); + }); + }); + + describe('setLocalStorageGenerationIntervals', () => { + const localStorageSetItemSpy = jest.spyOn(Storage.prototype, 'setItem'); + + it('sets the encoded generation intervals in localStorage', () => { + const encoded = encodeGenerationIntervals(generationIntervals) ?? ''; + + setLocalStorageGenerationIntervals({ key, generationIntervals }); + + expect(localStorageSetItemSpy).toHaveBeenCalledWith(key, encoded); + }); + }); +}); diff --git a/x-pack/plugins/security_solution/public/attack_discovery/pages/session_storage/index.ts b/x-pack/plugins/security_solution/public/attack_discovery/pages/session_storage/index.ts index c959374167504..8c8c49b482650 100644 --- a/x-pack/plugins/security_solution/public/attack_discovery/pages/session_storage/index.ts +++ b/x-pack/plugins/security_solution/public/attack_discovery/pages/session_storage/index.ts @@ -76,8 +76,18 @@ export const encodeGenerationIntervals = ( export const decodeGenerationIntervals = ( generationIntervals: string ): Record | null => { + const parseDate = (key: string, value: unknown) => { + if (key === 'date' && typeof value === 'string') { + return new Date(value); + } else if (key === 'date' && typeof value !== 'string') { + throw new Error('Invalid date'); + } else { + return value; + } + }; + try { - return JSON.parse(generationIntervals); + return JSON.parse(generationIntervals, parseDate); } catch { return null; } @@ -87,7 +97,7 @@ export const getLocalStorageGenerationIntervals = ( key: string ): Record | null => { if (!isEmpty(key)) { - return decodeGenerationIntervals(sessionStorage.getItem(key) ?? ''); + return decodeGenerationIntervals(localStorage.getItem(key) ?? ''); } return null; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_creation/components/related_integrations/related_integration_field.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_creation/components/related_integrations/related_integration_field.tsx index c24220923441b..fb6e89fb44acc 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_creation/components/related_integrations/related_integration_field.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_creation/components/related_integrations/related_integration_field.tsx @@ -24,7 +24,6 @@ import type { FieldHook } from '../../../../shared_imports'; import type { Integration, RelatedIntegration } from '../../../../../common/api/detection_engine'; import { useIntegrations } from '../../../../detections/components/rules/related_integrations/use_integrations'; import { IntegrationStatusBadge } from './integration_status_badge'; -import { DEFAULT_RELATED_INTEGRATION } from './default_related_integration'; import * as i18n from './translations'; interface RelatedIntegrationItemFormProps { @@ -95,16 +94,6 @@ export function RelatedIntegrationField({ ); const hasError = Boolean(packageErrorMessage) || Boolean(versionErrorMessage); - const isLastField = relatedIntegrations.length === 1; - const isLastEmptyField = isLastField && field.value.package === ''; - const handleRemove = useCallback(() => { - if (isLastField) { - field.setValue(DEFAULT_RELATED_INTEGRATION); - return; - } - - onRemove(); - }, [onRemove, field, isLastField]); return ( ({ docLinks: { links: { securitySolution: { - ruleUiAdvancedParams: 'http://link-to-docs', + createDetectionRules: 'http://link-to-docs', }, }, }, @@ -669,82 +669,6 @@ describe('RelatedIntegrations form part', () => { }); }); }); - - describe('sticky last form row', () => { - it('does not remove the last item', async () => { - render(, { wrapper: createReactQueryWrapper() }); - - await addRelatedIntegrationRow(); - await removeLastRelatedIntegrationRow(); - - expect(screen.getAllByTestId(RELATED_INTEGRATION_ROW)).toHaveLength(1); - }); - - it('disables remove button after clicking remove button on the last item', async () => { - render(, { wrapper: createReactQueryWrapper() }); - - await addRelatedIntegrationRow(); - await removeLastRelatedIntegrationRow(); - - expect(screen.getByTestId(REMOVE_INTEGRATION_ROW_BUTTON_TEST_ID)).toBeDisabled(); - }); - - it('clears selected integration when clicking remove the last form row button', async () => { - render(, { wrapper: createReactQueryWrapper() }); - - await addRelatedIntegrationRow(); - await selectFirstEuiComboBoxOption({ - comboBoxToggleButton: getLastByTestId(COMBO_BOX_TOGGLE_BUTTON_TEST_ID), - }); - await removeLastRelatedIntegrationRow(); - - expect(screen.queryByTestId(COMBO_BOX_SELECTION_TEST_ID)).not.toBeInTheDocument(); - }); - - it('submits an empty integration after clicking remove the last form row button', async () => { - const handleSubmit = jest.fn(); - - render(, { wrapper: createReactQueryWrapper() }); - - await addRelatedIntegrationRow(); - await selectFirstEuiComboBoxOption({ - comboBoxToggleButton: getLastByTestId(COMBO_BOX_TOGGLE_BUTTON_TEST_ID), - }); - await removeLastRelatedIntegrationRow(); - await submitForm(); - await waitFor(() => { - expect(handleSubmit).toHaveBeenCalled(); - }); - - expect(handleSubmit).toHaveBeenCalledWith({ - data: [{ package: '', version: '' }], - isValid: true, - }); - }); - - it('submits an empty integration after previously saved integrations were removed', async () => { - const initialRelatedIntegrations: RelatedIntegration[] = [ - { package: 'package-a', version: '^1.2.3' }, - ]; - const handleSubmit = jest.fn(); - - render(, { - wrapper: createReactQueryWrapper(), - }); - - await waitForIntegrationsToBeLoaded(); - await removeLastRelatedIntegrationRow(); - await submitForm(); - await waitFor(() => { - expect(handleSubmit).toHaveBeenCalled(); - }); - - expect(handleSubmit).toHaveBeenCalledWith({ - data: [{ package: '', version: '' }], - isValid: true, - }); - }); - }); }); }); @@ -778,11 +702,6 @@ function TestForm({ initialState, onSubmit }: TestFormProps): JSX.Element { ); } -function getLastByTestId(testId: string): HTMLElement { - // getAllByTestId throws an error when there are no `testId` elements found - return screen.getAllByTestId(testId).at(-1)!; -} - function waitForIntegrationsToBeLoaded(): Promise { return waitForElementToBeRemoved(screen.queryAllByRole('progressbar')); } diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_creation/components/related_integrations/related_integrations_help_info.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_creation/components/related_integrations/related_integrations_help_info.tsx index b694d17a80435..08c4a8e22edfd 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_creation/components/related_integrations/related_integrations_help_info.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_creation/components/related_integrations/related_integrations_help_info.tsx @@ -40,7 +40,7 @@ export function RelatedIntegrationsHelpInfo(): JSX.Element { defaultMessage="Choose the {integrationsDocLink} this rule depends on, and correct if necessary each integration’s version constraint in {semverLink} format. Only tilde, caret, and plain versions are supported, such as ~1.2.3, ^1.2.3, or 1.2.3." values={{ integrationsDocLink: ( - + > + ): ReturnType> | undefined { + const [{ value, path, form }] = args; + + const formData = form.getFormData(); + const parentFieldData: RequiredFieldInput[] = formData[parentFieldPath]; + + const isFieldNameUsedMoreThanOnce = + parentFieldData.filter((field) => field.name === value.name).length > 1; + + if (isFieldNameUsedMoreThanOnce) { + return { + code: 'ERR_FIELD_FORMAT', + path: `${path}.name`, + message: i18n.FIELD_NAME_USED_MORE_THAN_ONCE(value.name), + }; + } + + /* Allow empty rows. They are going to be removed before submission. */ + if (value.name.trim().length === 0 && value.type.trim().length === 0) { + return; + } + + if (value.name.trim().length === 0) { + return { + code: 'ERR_FIELD_MISSING', + path: `${path}.name`, + message: i18n.FIELD_NAME_REQUIRED, + }; + } + + if (value.type.trim().length === 0) { + return { + code: 'ERR_FIELD_MISSING', + path: `${path}.type`, + message: i18n.FIELD_TYPE_REQUIRED, + }; + } + }; +} diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_creation/components/required_fields/name_combobox.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_creation/components/required_fields/name_combobox.tsx new file mode 100644 index 0000000000000..848e3c9a3c558 --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_creation/components/required_fields/name_combobox.tsx @@ -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 React, { useCallback, useMemo, useState, useEffect } from 'react'; +import { EuiComboBox, EuiIcon } from '@elastic/eui'; +import type { EuiComboBoxOptionOption } from '@elastic/eui'; +import { euiThemeVars } from '@kbn/ui-theme'; +import type { FieldHook } from '../../../../shared_imports'; +import type { RequiredFieldInput } from '../../../../../common/api/detection_engine/model/rule_schema/common_attributes.gen'; +import { pickTypeForName } from './utils'; +import * as i18n from './translations'; + +interface NameComboBoxProps { + field: FieldHook; + itemId: string; + availableFieldNames: string[]; + typesByFieldName: Record; + nameWarning: string; + nameError: { message: string } | undefined; +} + +export function NameComboBox({ + field, + itemId, + availableFieldNames, + typesByFieldName, + nameWarning, + nameError, +}: NameComboBoxProps) { + const { value, setValue } = field; + + const selectableNameOptions: Array> = useMemo( + () => + /* Not adding an empty string to the list of selectable field names */ + (value.name ? [value.name] : []).concat(availableFieldNames).map((name) => ({ + label: name, + value: name, + })), + [availableFieldNames, value.name] + ); + + /* + Using a state for `selectedNameOptions` instead of using the field value directly + to fix the issue where pressing the backspace key in combobox input would clear the field value + and trigger a validation error. By using a separate state, we can clear the selected option + without clearing the field value. + */ + const [selectedNameOption, setSelectedNameOption] = useState< + EuiComboBoxOptionOption | undefined + >(selectableNameOptions.find((option) => option.label === value.name)); + + useEffect(() => { + /* Re-computing the new selected name option when the field value changes */ + setSelectedNameOption(selectableNameOptions.find((option) => option.label === value.name)); + }, [value.name, selectableNameOptions]); + + const handleNameChange = useCallback( + (selectedOptions: Array>) => { + const newlySelectedOption: EuiComboBoxOptionOption | undefined = selectedOptions[0]; + + if (!newlySelectedOption) { + /* This occurs when the user hits backspace in combobox */ + setSelectedNameOption(undefined); + return; + } + + const updatedName = newlySelectedOption?.value || ''; + + const updatedType = pickTypeForName({ + name: updatedName, + type: value.type, + typesByFieldName, + }); + + const updatedFieldValue: RequiredFieldInput = { + name: updatedName, + type: updatedType, + }; + + setValue(updatedFieldValue); + }, + [setValue, value.type, typesByFieldName] + ); + + const handleAddCustomName = useCallback( + (newName: string) => { + const updatedFieldValue: RequiredFieldInput = { + name: newName, + type: pickTypeForName({ name: newName, type: value.type, typesByFieldName }), + }; + + setValue(updatedFieldValue); + }, + [setValue, value.type, typesByFieldName] + ); + + return ( + + ) : undefined + } + /> + ); +} diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_creation/components/required_fields/required_fields.test.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_creation/components/required_fields/required_fields.test.tsx new file mode 100644 index 0000000000000..2812c147d9c2d --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_creation/components/required_fields/required_fields.test.tsx @@ -0,0 +1,724 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license 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 { I18nProvider } from '@kbn/i18n-react'; +import { screen, render, act, fireEvent, waitFor } from '@testing-library/react'; +import { Form, useForm } from '../../../../shared_imports'; + +import type { DataViewFieldBase } from '@kbn/es-query'; +import { RequiredFields } from './required_fields'; +import type { RequiredFieldInput } from '../../../../../common/api/detection_engine'; + +const ADD_REQUIRED_FIELD_BUTTON_TEST_ID = 'addRequiredFieldButton'; +const REQUIRED_FIELDS_GENERAL_WARNING_TEST_ID = 'requiredFieldsGeneralWarning'; + +describe('RequiredFields form part', () => { + it('displays the required fields label', () => { + render(); + + expect(screen.getByText('Required fields')); + }); + + it('displays previously saved required fields', () => { + const initialState = [ + { name: 'field1', type: 'string' }, + { name: 'field2', type: 'number' }, + ]; + + render(); + + expect(screen.getByDisplayValue('field1')).toBeVisible(); + expect(screen.getByDisplayValue('string')).toBeVisible(); + + expect(screen.getByDisplayValue('field2')).toBeVisible(); + expect(screen.getByDisplayValue('number')).toBeVisible(); + }); + + it('user can add a new required field to an empty form', async () => { + const indexPatternFields: DataViewFieldBase[] = [ + createIndexPatternField({ name: 'field1', esTypes: ['string'] }), + ]; + + render(); + + await addRequiredFieldRow(); + await selectFirstEuiComboBoxOption({ + comboBoxToggleButton: getSelectToggleButtonForName('empty'), + }); + + expect(screen.getByDisplayValue('field1')).toBeVisible(); + expect(screen.getByDisplayValue('string')).toBeVisible(); + }); + + it('user can add a new required field to a previously saved form', async () => { + const initialState = [{ name: 'field1', type: 'string' }]; + + const indexPatternFields: DataViewFieldBase[] = [ + createIndexPatternField({ name: 'field2', esTypes: ['keyword'] }), + ]; + + render(); + + await addRequiredFieldRow(); + + await selectFirstEuiComboBoxOption({ + comboBoxToggleButton: getSelectToggleButtonForName('empty'), + }); + + expect(screen.getByDisplayValue('field2')).toBeVisible(); + expect(screen.getByDisplayValue('keyword')).toBeVisible(); + }); + + it('user can select any field name that is available in index patterns', async () => { + const indexPatternFields: DataViewFieldBase[] = [ + createIndexPatternField({ name: 'field1', esTypes: ['string'] }), + createIndexPatternField({ name: 'field2', esTypes: ['keyword'] }), + ]; + + render(); + + await addRequiredFieldRow(); + + await selectEuiComboBoxOption({ + comboBoxToggleButton: getSelectToggleButtonForName('empty'), + optionIndex: 0, + }); + + expect(screen.getByDisplayValue('field1')).toBeVisible(); + expect(screen.getByDisplayValue('string')).toBeVisible(); + + await addRequiredFieldRow(); + + await selectEuiComboBoxOption({ + comboBoxToggleButton: getSelectToggleButtonForName('empty'), + optionIndex: 0, + }); + + expect(screen.getByDisplayValue('field2')).toBeVisible(); + expect(screen.getByDisplayValue('keyword')).toBeVisible(); + }); + + it('user can add his own custom field name and type', async () => { + render(); + + await addRequiredFieldRow(); + + await typeInCustomComboBoxOption({ + comboBoxToggleButton: getSelectToggleButtonForName('empty'), + optionText: 'customField', + }); + + expect(screen.getByDisplayValue('customField')).toBeVisible(); + + await typeInCustomComboBoxOption({ + comboBoxToggleButton: getSelectToggleButtonForType('empty'), + optionText: 'customType', + }); + + expect(screen.getByDisplayValue('customType')).toBeVisible(); + expect(screen.queryByTestId(REQUIRED_FIELDS_GENERAL_WARNING_TEST_ID)).toBeVisible(); + }); + + it('field type dropdown allows to choose from options if multiple types are available', async () => { + const initialState = [{ name: 'field1', type: 'string' }]; + + const indexPatternFields: DataViewFieldBase[] = [ + createIndexPatternField({ name: 'field1', esTypes: ['string', 'keyword'] }), + ]; + + render(); + + await selectEuiComboBoxOption({ + comboBoxToggleButton: getSelectToggleButtonForType('string'), + optionText: 'keyword', + }); + + expect(screen.getByDisplayValue('keyword')).toBeVisible(); + }); + + it('user can remove a required field', async () => { + const initialState = [{ name: 'field1', type: 'string' }]; + + const indexPatternFields: DataViewFieldBase[] = [ + createIndexPatternField({ name: 'field1', esTypes: ['string'] }), + ]; + + render(); + + await act(async () => { + fireEvent.click(screen.getByTestId('removeRequiredFieldButton-field1')); + }); + + expect(screen.queryByDisplayValue('field1')).toBeNull(); + }); + + it('user can not select the same field twice', async () => { + const initialState = [{ name: 'field1', type: 'string' }]; + + const indexPatternFields: DataViewFieldBase[] = [ + createIndexPatternField({ name: 'field1', esTypes: ['string'] }), + createIndexPatternField({ name: 'field2', esTypes: ['keyword'] }), + createIndexPatternField({ name: 'field3', esTypes: ['date'] }), + ]; + + render(); + + await addRequiredFieldRow(); + + const emptyRowOptions = await getDropdownOptions(getSelectToggleButtonForName('empty')); + expect(emptyRowOptions).toEqual(['field2', 'field3']); + + await selectEuiComboBoxOption({ + comboBoxToggleButton: getSelectToggleButtonForName('empty'), + optionText: 'field2', + }); + + const firstRowNameOptions = await getDropdownOptions(getSelectToggleButtonForName('field1')); + expect(firstRowNameOptions).toEqual(['field1', 'field3']); + }); + + it('adding a new required field is disabled when index patterns are loading', async () => { + render(); + + expect(screen.getByTestId(ADD_REQUIRED_FIELD_BUTTON_TEST_ID)).toBeDisabled(); + }); + + it('adding a new required field is disabled when an empty row is already displayed', async () => { + const indexPatternFields: DataViewFieldBase[] = [ + createIndexPatternField({ name: 'field1', esTypes: ['string'] }), + ]; + + render(); + + expect(screen.getByTestId(ADD_REQUIRED_FIELD_BUTTON_TEST_ID)).toBeEnabled(); + + await addRequiredFieldRow(); + + expect(screen.getByTestId(ADD_REQUIRED_FIELD_BUTTON_TEST_ID)).toBeDisabled(); + }); + + describe('warnings', () => { + it('displays a warning when a selected field name is not found within index patterns', async () => { + const initialState = [{ name: 'field-that-does-not-exist', type: 'keyword' }]; + + const indexPatternFields: DataViewFieldBase[] = [ + createIndexPatternField({ name: 'field1', esTypes: ['string'] }), + ]; + + render(); + + expect(screen.getByTestId(REQUIRED_FIELDS_GENERAL_WARNING_TEST_ID)).toBeVisible(); + + expect( + screen.getByText( + `Field "field-that-does-not-exist" is not found within the rule's specified index patterns` + ) + ).toBeVisible(); + + const nameWarningIcon = screen + .getByTestId(`requiredFieldNameSelect-field-that-does-not-exist`) + .querySelector('[data-euiicon-type="warning"]'); + + expect(nameWarningIcon).toBeVisible(); + + /* Make sure only one warning icon is displayed - the one for name */ + expect(document.querySelectorAll('[data-test-subj="warningIcon"]')).toHaveLength(1); + }); + + it('displays a warning when a selected field type is not found within index patterns', async () => { + const initialState = [{ name: 'field1', type: 'type-that-does-not-exist' }]; + + const indexPatternFields: DataViewFieldBase[] = [ + createIndexPatternField({ name: 'field1', esTypes: ['string'] }), + ]; + + render(); + + expect(screen.getByTestId(REQUIRED_FIELDS_GENERAL_WARNING_TEST_ID)).toBeVisible(); + + expect( + screen.getByText( + `Field "field1" with type "type-that-does-not-exist" is not found within the rule's specified index patterns` + ) + ).toBeVisible(); + + const typeWarningIcon = screen + .getByTestId(`requiredFieldTypeSelect-type-that-does-not-exist`) + .querySelector('[data-euiicon-type="warning"]'); + + expect(typeWarningIcon).toBeVisible(); + + /* Make sure only one warning icon is displayed - the one for type */ + expect(document.querySelectorAll('[data-test-subj="warningIcon"]')).toHaveLength(1); + }); + + it('displays a warning only for field name when both field name and type are not found within index patterns', async () => { + const initialState = [ + { name: 'field-that-does-not-exist', type: 'type-that-does-not-exist' }, + ]; + + const indexPatternFields: DataViewFieldBase[] = [ + createIndexPatternField({ name: 'field1', esTypes: ['string'] }), + ]; + + render(); + + expect(screen.getByTestId(REQUIRED_FIELDS_GENERAL_WARNING_TEST_ID)).toBeVisible(); + + expect( + screen.getByText( + `Field "field-that-does-not-exist" is not found within the rule's specified index patterns` + ) + ).toBeVisible(); + + const nameWarningIcon = screen + .getByTestId(`requiredFieldNameSelect-field-that-does-not-exist`) + .querySelector('[data-euiicon-type="warning"]'); + + expect(nameWarningIcon).toBeVisible(); + + /* Make sure only one warning icon is displayed - the one for name */ + expect(document.querySelectorAll('[data-test-subj="warningIcon"]')).toHaveLength(1); + }); + + it(`doesn't display a warning when all selected fields are found within index patterns`, async () => { + const initialState = [{ name: 'field1', type: 'string' }]; + + const indexPatternFields: DataViewFieldBase[] = [ + createIndexPatternField({ name: 'field1', esTypes: ['string'] }), + ]; + + render(); + + expect(screen.queryByTestId(REQUIRED_FIELDS_GENERAL_WARNING_TEST_ID)).toBeNull(); + }); + + it(`doesn't display a warning for an empty row`, async () => { + const indexPatternFields: DataViewFieldBase[] = [ + createIndexPatternField({ name: 'field1', esTypes: ['string'] }), + ]; + + render(); + + await addRequiredFieldRow(); + + expect(screen.queryByTestId(REQUIRED_FIELDS_GENERAL_WARNING_TEST_ID)).toBeNull(); + }); + + it(`doesn't display a warning when field is invalid`, async () => { + render(); + + await addRequiredFieldRow(); + + await typeInCustomComboBoxOption({ + comboBoxToggleButton: getSelectToggleButtonForName('empty'), + optionText: 'customField', + }); + + expect(screen.getByText('Field type is required')).toBeVisible(); + + expect(screen.queryByTestId(`customField-warningText`)).toBeNull(); + }); + }); + + describe('validation', () => { + it('form is invalid when only field name is empty', async () => { + render(); + + await addRequiredFieldRow(); + + await typeInCustomComboBoxOption({ + comboBoxToggleButton: getSelectToggleButtonForType('empty'), + optionText: 'customType', + }); + + expect(screen.getByText('Field name is required')).toBeVisible(); + + await typeInCustomComboBoxOption({ + comboBoxToggleButton: getSelectToggleButtonForName('empty'), + optionText: 'customField', + }); + + expect(screen.queryByText('Field name is required')).toBeNull(); + }); + + it('form is invalid when only field type is empty', async () => { + render(); + + await addRequiredFieldRow(); + + await typeInCustomComboBoxOption({ + comboBoxToggleButton: getSelectToggleButtonForName('empty'), + optionText: 'customField', + }); + + expect(screen.getByText('Field type is required')).toBeVisible(); + + await typeInCustomComboBoxOption({ + comboBoxToggleButton: getSelectToggleButtonForType('empty'), + optionText: 'customType', + }); + + expect(screen.queryByText('Field type is required')).toBeNull(); + }); + + it('form is invalid when same field name is selected more than once', async () => { + const initialState = [{ name: 'field1', type: 'string' }]; + + const indexPatternFields: DataViewFieldBase[] = [ + createIndexPatternField({ name: 'field1', esTypes: ['string'] }), + createIndexPatternField({ name: 'field2', esTypes: ['string'] }), + ]; + + render(); + + await addRequiredFieldRow(); + + await typeInCustomComboBoxOption({ + comboBoxToggleButton: getSelectToggleButtonForName('empty'), + optionText: 'field1', + }); + + expect(screen.getByText('Field name "field1" is already used')).toBeVisible(); + + await typeInCustomComboBoxOption({ + comboBoxToggleButton: getLastSelectToggleButtonForName(), + optionText: 'field2', + }); + + expect(screen.queryByText('Field name "field1" is already used')).toBeNull(); + }); + + it('form is valid when both field name and type are empty', async () => { + const handleSubmit = jest.fn(); + + render(); + + await addRequiredFieldRow(); + + await submitForm(); + + expect(handleSubmit).toHaveBeenCalledWith({ + data: [{ name: '', type: '' }], + isValid: true, + }); + }); + }); + + describe('form submission', () => { + it('submits undefined when no required fields are selected', async () => { + const handleSubmit = jest.fn(); + + render(); + + await submitForm(); + + await waitFor(() => { + expect(handleSubmit).toHaveBeenCalledWith({ + data: undefined, + isValid: true, + }); + }); + }); + + it('submits undefined when all selected fields were removed', async () => { + const initialState = [{ name: 'field1', type: 'string' }]; + + const handleSubmit = jest.fn(); + + render(); + + await act(async () => { + fireEvent.click(screen.getByTestId('removeRequiredFieldButton-field1')); + }); + + await submitForm(); + + await waitFor(() => { + expect(handleSubmit).toHaveBeenCalledWith({ + data: undefined, + isValid: true, + }); + }); + }); + + it('submits newly added required fields', async () => { + const indexPatternFields: DataViewFieldBase[] = [ + createIndexPatternField({ name: 'field1', esTypes: ['string'] }), + ]; + + const handleSubmit = jest.fn(); + + render(); + + await addRequiredFieldRow(); + + await selectFirstEuiComboBoxOption({ + comboBoxToggleButton: getSelectToggleButtonForName('empty'), + }); + + await submitForm(); + + expect(handleSubmit).toHaveBeenCalledWith({ + data: [{ name: 'field1', type: 'string' }], + isValid: true, + }); + }); + + it('submits previously saved required fields', async () => { + const initialState = [{ name: 'field1', type: 'string' }]; + + const indexPatternFields: DataViewFieldBase[] = [ + createIndexPatternField({ name: 'field1', esTypes: ['string'] }), + ]; + + const handleSubmit = jest.fn(); + + render( + + ); + + await submitForm(); + + expect(handleSubmit).toHaveBeenCalledWith({ + data: [{ name: 'field1', type: 'string' }], + isValid: true, + }); + }); + + it('submits updated required fields', async () => { + const initialState = [{ name: 'field1', type: 'string' }]; + + const indexPatternFields: DataViewFieldBase[] = [ + createIndexPatternField({ name: 'field1', esTypes: ['string'] }), + createIndexPatternField({ name: 'field2', esTypes: ['keyword', 'date'] }), + ]; + + const handleSubmit = jest.fn(); + + render( + + ); + + await selectEuiComboBoxOption({ + comboBoxToggleButton: getSelectToggleButtonForName('field1'), + optionText: 'field2', + }); + + await selectEuiComboBoxOption({ + comboBoxToggleButton: getSelectToggleButtonForType('keyword'), + optionText: 'date', + }); + + await submitForm(); + + expect(handleSubmit).toHaveBeenCalledWith({ + data: [{ name: 'field2', type: 'date' }], + isValid: true, + }); + }); + + it('submits a form with warnings', async () => { + const initialState = [{ name: 'name-that-does-not-exist', type: 'type-that-does-not-exist' }]; + + const indexPatternFields: DataViewFieldBase[] = [ + createIndexPatternField({ name: 'field1', esTypes: ['string'] }), + ]; + + const handleSubmit = jest.fn(); + + render( + + ); + + expect(screen.queryByTestId(REQUIRED_FIELDS_GENERAL_WARNING_TEST_ID)).toBeVisible(); + + await submitForm(); + + expect(handleSubmit).toHaveBeenCalledWith({ + data: [{ name: 'name-that-does-not-exist', type: 'type-that-does-not-exist' }], + isValid: true, + }); + }); + }); +}); + +export function createIndexPatternField(overrides: Partial): DataViewFieldBase { + return { + name: 'one', + type: 'string', + esTypes: [], + ...overrides, + }; +} + +async function getDropdownOptions(dropdownToggleButton: HTMLElement): Promise { + await showEuiComboBoxOptions(dropdownToggleButton); + + const options = screen.getAllByRole('option').map((option) => option.textContent) as string[]; + + fireEvent.click(dropdownToggleButton); + + return options; +} + +export function addRequiredFieldRow(): Promise { + return act(async () => { + fireEvent.click(screen.getByText('Add required field')); + }); +} + +function showEuiComboBoxOptions(comboBoxToggleButton: HTMLElement): Promise { + fireEvent.click(comboBoxToggleButton); + + return waitFor(() => { + const listWithOptionsElement = document.querySelector('[role="listbox"]'); + const emptyListElement = document.querySelector('.euiComboBoxOptionsList__empty'); + + expect(listWithOptionsElement || emptyListElement).toBeInTheDocument(); + }); +} + +type SelectEuiComboBoxOptionParameters = + | { + comboBoxToggleButton: HTMLElement; + optionIndex: number; + optionText?: undefined; + } + | { + comboBoxToggleButton: HTMLElement; + optionText: string; + optionIndex?: undefined; + }; + +function selectEuiComboBoxOption({ + comboBoxToggleButton, + optionIndex, + optionText, +}: SelectEuiComboBoxOptionParameters): Promise { + return act(async () => { + await showEuiComboBoxOptions(comboBoxToggleButton); + + const options = Array.from( + document.querySelectorAll('[data-test-subj*="comboBoxOptionsList"] [role="option"]') + ); + + if (typeof optionText === 'string') { + const optionToSelect = options.find((option) => option.textContent === optionText); + + if (!optionToSelect) { + throw new Error( + `Could not find option with text "${optionText}". Available options: ${options + .map((option) => option.textContent) + .join(', ')}` + ); + } + + fireEvent.click(optionToSelect); + } else { + fireEvent.click(options[optionIndex]); + } + }); +} + +function selectFirstEuiComboBoxOption({ + comboBoxToggleButton, +}: { + comboBoxToggleButton: HTMLElement; +}): Promise { + return selectEuiComboBoxOption({ comboBoxToggleButton, optionIndex: 0 }); +} + +function typeInCustomComboBoxOption({ + comboBoxToggleButton, + optionText, +}: { + comboBoxToggleButton: HTMLElement; + optionText: string; +}) { + return act(async () => { + await showEuiComboBoxOptions(comboBoxToggleButton); + + fireEvent.change(document.activeElement as HTMLInputElement, { target: { value: optionText } }); + fireEvent.keyDown(document.activeElement as HTMLInputElement, { key: 'Enter' }); + }); +} + +function getLastSelectToggleButtonForName(): HTMLElement { + const allNameSelects = screen.getAllByTestId(/requiredFieldNameSelect-.*/); + const lastNameSelect = allNameSelects[allNameSelects.length - 1]; + + return lastNameSelect.querySelector('[data-test-subj="comboBoxToggleListButton"]') as HTMLElement; +} + +export function getSelectToggleButtonForName(value: string): HTMLElement { + return screen + .getByTestId(`requiredFieldNameSelect-${value}`) + .querySelector('[data-test-subj="comboBoxToggleListButton"]') as HTMLElement; +} + +function getSelectToggleButtonForType(value: string): HTMLElement { + return screen + .getByTestId(`requiredFieldTypeSelect-${value}`) + .querySelector('[data-test-subj="comboBoxToggleListButton"]') as HTMLElement; +} + +function submitForm(): Promise { + return act(async () => { + fireEvent.click(screen.getByText('Submit')); + }); +} + +interface TestFormProps { + initialState?: RequiredFieldInput[]; + onSubmit?: (args: { data: RequiredFieldInput[]; isValid: boolean }) => void; + indexPatternFields?: DataViewFieldBase[]; + isIndexPatternLoading?: boolean; +} + +function TestForm({ + indexPatternFields, + initialState = [], + isIndexPatternLoading, + onSubmit, +}: TestFormProps): JSX.Element { + const { form } = useForm({ + defaultValue: { + requiredFieldsField: initialState, + }, + onSubmit: async (formData, isValid) => + onSubmit?.({ data: formData.requiredFieldsField, isValid }), + }); + + return ( + +
+ + + +
+ ); +} diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_creation/components/required_fields/required_fields.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_creation/components/required_fields/required_fields.tsx new file mode 100644 index 0000000000000..f53c41ce98d00 --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_creation/components/required_fields/required_fields.tsx @@ -0,0 +1,213 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { useMemo } from 'react'; +import { EuiButtonEmpty, EuiCallOut, EuiFormRow, EuiSpacer, EuiText } from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n-react'; +import type { DataViewFieldBase } from '@kbn/es-query'; +import type { RequiredFieldInput } from '../../../../../common/api/detection_engine'; +import { UseArray, useFormData } from '../../../../shared_imports'; +import type { FormHook, ArrayItem } from '../../../../shared_imports'; +import { RequiredFieldsHelpInfo } from './required_fields_help_info'; +import { RequiredFieldRow } from './required_fields_row'; +import * as defineRuleI18n from '../../../rule_creation_ui/components/step_define_rule/translations'; +import * as i18n from './translations'; + +interface RequiredFieldsComponentProps { + path: string; + indexPatternFields?: DataViewFieldBase[]; + isIndexPatternLoading?: boolean; +} + +const RequiredFieldsComponent = ({ + path, + indexPatternFields = [], + isIndexPatternLoading = false, +}: RequiredFieldsComponentProps) => { + return ( + + {({ items, addItem, removeItem, form }) => ( + + )} + + ); +}; + +interface RequiredFieldsListProps { + items: ArrayItem[]; + addItem: () => void; + removeItem: (id: number) => void; + indexPatternFields: DataViewFieldBase[]; + isIndexPatternLoading: boolean; + path: string; + form: FormHook; +} + +const RequiredFieldsList = ({ + items, + addItem, + removeItem, + indexPatternFields, + isIndexPatternLoading, + path, + form, +}: RequiredFieldsListProps) => { + /* + This component should only re-render when either the "index" form field (index patterns) or the required fields change. + + By default, the `useFormData` hook triggers a re-render whenever any form field changes. + It also allows optimization by passing a "watch" array of field names. The component then only re-renders when these specified fields change. + + However, it doesn't work with fields created using the `UseArray` component. + In `useFormData`, these array fields are stored as "flattened" objects with numbered keys, like { "requiredFields[0]": { ... }, "requiredFields[1]": { ... } }. + The "watch" feature of `useFormData` only works if you pass these "flattened" field names, such as ["requiredFields[0]", "requiredFields[1]", ...], not just "requiredFields". + + To work around this, we manually construct a list of "flattened" field names to watch, based on the current state of the form. + This is a temporary solution and ideally, `useFormData` should be updated to handle this scenario. + */ + + const internalField = form.getFields()[`${path}__array__`] ?? {}; + const internalFieldValue = (internalField?.value ?? []) as ArrayItem[]; + const flattenedFieldNames = internalFieldValue.map((item) => item.path); + + /* + Not using "watch" for the initial render, to let row components render and initialize form fields. + Then we can use the "watch" feature to track their changes. + */ + const hasRenderedInitially = flattenedFieldNames.length > 0; + const fieldsToWatch = hasRenderedInitially ? ['index', ...flattenedFieldNames] : []; + + const [formData] = useFormData({ watch: fieldsToWatch }); + + const fieldValue: RequiredFieldInput[] = formData[path] ?? []; + + const typesByFieldName: Record = useMemo( + () => + indexPatternFields.reduce((accumulator, field) => { + if (field.esTypes?.length) { + accumulator[field.name] = field.esTypes; + } + return accumulator; + }, {} as Record), + [indexPatternFields] + ); + + const allFieldNames = useMemo(() => Object.keys(typesByFieldName), [typesByFieldName]); + + const selectedFieldNames = fieldValue.map(({ name }) => name); + + const availableFieldNames = allFieldNames.filter((name) => !selectedFieldNames.includes(name)); + + const nameWarnings = fieldValue.reduce>((warnings, { name }) => { + if ( + !isIndexPatternLoading && + /* Creating a warning only if "name" value is filled in */ + name !== '' && + !allFieldNames.includes(name) + ) { + warnings[name] = i18n.FIELD_NAME_NOT_FOUND_WARNING(name); + } + return warnings; + }, {}); + + const typeWarnings = fieldValue.reduce>((warnings, { name, type }) => { + if ( + !isIndexPatternLoading && + /* Creating a warning for "type" only if "name" value is filled in */ + name !== '' && + typesByFieldName[name] && + !typesByFieldName[name].includes(type) + ) { + warnings[`${name}-${type}`] = i18n.FIELD_TYPE_NOT_FOUND_WARNING(name, type); + } + return warnings; + }, {}); + + const getWarnings = ({ name, type }: { name: string; type: string }) => ({ + nameWarning: nameWarnings[name] || '', + typeWarning: typeWarnings[`${name}-${type}`] || '', + }); + + const hasEmptyFieldName = fieldValue.some(({ name }) => name === ''); + + const hasWarnings = Object.keys(nameWarnings).length > 0 || Object.keys(typeWarnings).length > 0; + + return ( + <> + {hasWarnings && ( + +

+ {defineRuleI18n.SOURCE}, + }} + /> +

+
+ )} + + + {i18n.REQUIRED_FIELDS_LABEL} + + + } + labelAppend={ + + {i18n.OPTIONAL} + + } + hasChildLabel={false} + labelType="legend" + > + <> + {items.map((item) => ( + + ))} + + + + {i18n.ADD_REQUIRED_FIELD} + + + + + ); +}; + +export const RequiredFields = React.memo(RequiredFieldsComponent); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_creation/components/required_fields/required_fields_help_info.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_creation/components/required_fields/required_fields_help_info.tsx new file mode 100644 index 0000000000000..187f05880d205 --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_creation/components/required_fields/required_fields_help_info.tsx @@ -0,0 +1,48 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { useToggle } from 'react-use'; +import { EuiPopover, EuiText, EuiButtonIcon } from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n-react'; +import * as defineRuleI18n from '../../../rule_creation_ui/components/step_define_rule/translations'; +import * as i18n from './translations'; + +/** + * Theme doesn't expose width variables. Using provided size variables will require + * multiplying it by another magic constant. + * + * 320px width looks + * like a [commonly used width in EUI](https://github.com/search?q=repo%3Aelastic%2Feui%20320&type=code). + */ +const POPOVER_WIDTH = 320; + +export function RequiredFieldsHelpInfo(): JSX.Element { + const [isPopoverOpen, togglePopover] = useToggle(false); + + const button = ( + + ); + + return ( + + + {defineRuleI18n.SOURCE}, + }} + /> + + + ); +} diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_creation/components/required_fields/required_fields_row.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_creation/components/required_fields/required_fields_row.tsx new file mode 100644 index 0000000000000..755f1de413760 --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_creation/components/required_fields/required_fields_row.tsx @@ -0,0 +1,163 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { useCallback, useMemo } from 'react'; +import { EuiButtonIcon, EuiFlexGroup, EuiFlexItem, EuiFormRow, EuiTextColor } from '@elastic/eui'; +import { UseField } from '../../../../shared_imports'; +import { NameComboBox } from './name_combobox'; +import { TypeComboBox } from './type_combobox'; +import { makeValidateRequiredField } from './make_validate_required_field'; +import * as i18n from './translations'; + +import type { ArrayItem, FieldConfig, FieldHook } from '../../../../shared_imports'; +import type { + RequiredField, + RequiredFieldInput, +} from '../../../../../common/api/detection_engine/model/rule_schema/common_attributes.gen'; + +interface RequiredFieldRowProps { + item: ArrayItem; + removeItem: (id: number) => void; + typesByFieldName: Record; + availableFieldNames: string[]; + getWarnings: ({ name, type }: { name: string; type: string }) => { + nameWarning: string; + typeWarning: string; + }; + parentFieldPath: string; +} + +export const RequiredFieldRow = ({ + item, + removeItem, + typesByFieldName, + availableFieldNames, + getWarnings, + parentFieldPath, +}: RequiredFieldRowProps) => { + const handleRemove = useCallback(() => removeItem(item.id), [removeItem, item.id]); + + const rowFieldConfig: FieldConfig = + useMemo( + () => ({ + deserializer: (value) => { + const rowValueWithoutEcs: RequiredFieldInput = { + name: value.name, + type: value.type, + }; + + return rowValueWithoutEcs; + }, + validations: [{ validator: makeValidateRequiredField(parentFieldPath) }], + defaultValue: { name: '', type: '' }, + }), + [parentFieldPath] + ); + + return ( + + ); +}; + +interface RequiredFieldFieldProps { + field: FieldHook; + onRemove: () => void; + typesByFieldName: Record; + availableFieldNames: string[]; + getWarnings: ({ name, type }: { name: string; type: string }) => { + nameWarning: string; + typeWarning: string; + }; + itemId: string; +} + +const RequiredFieldField = ({ + field, + typesByFieldName, + onRemove, + availableFieldNames, + getWarnings, + itemId, +}: RequiredFieldFieldProps) => { + const { nameWarning, typeWarning } = getWarnings(field.value); + const warningMessage = nameWarning || typeWarning; + + const [nameError, typeError] = useMemo(() => { + return [ + field.errors.find((error) => 'path' in error && error.path === `${field.path}.name`), + field.errors.find((error) => 'path' in error && error.path === `${field.path}.type`), + ]; + }, [field.path, field.errors]); + const hasError = Boolean(nameError) || Boolean(typeError); + const errorMessage = nameError?.message || typeError?.message; + + return ( + + {warningMessage} + + ) : ( + '' + ) + } + color="warning" + > + + + + + + + + + + + + + ); +}; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_creation/components/required_fields/translations.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_creation/components/required_fields/translations.ts new file mode 100644 index 0000000000000..bed9a4ea0024c --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_creation/components/required_fields/translations.ts @@ -0,0 +1,105 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { i18n } from '@kbn/i18n'; + +export const REQUIRED_FIELDS_LABEL = i18n.translate( + 'xpack.securitySolution.detectionEngine.ruleDescription.requiredFields.requiredFieldsLabel', + { + defaultMessage: 'Required fields', + } +); + +export const FIELD_NAME = i18n.translate( + 'xpack.securitySolution.detectionEngine.ruleDescription.requiredFields.fieldNameLabel', + { + defaultMessage: 'Field name', + } +); + +export const FIELD_TYPE = i18n.translate( + 'xpack.securitySolution.detectionEngine.ruleDescription.requiredFields.fieldTypeLabel', + { + defaultMessage: 'Field type', + } +); + +export const OPEN_HELP_POPOVER_ARIA_LABEL = i18n.translate( + 'xpack.securitySolution.detectionEngine.ruleDescription.requiredFields.openHelpPopoverAriaLabel', + { + defaultMessage: 'Open help popover', + } +); + +export const REQUIRED_FIELDS_GENERAL_WARNING_TITLE = i18n.translate( + 'xpack.securitySolution.detectionEngine.ruleDescription.requiredFields.generalWarningTitle', + { + defaultMessage: `Some fields aren't found within the rule's specified index patterns.`, + } +); + +export const OPTIONAL = i18n.translate( + 'xpack.securitySolution.detectionEngine.ruleDescription.requiredFields.optionalText', + { + defaultMessage: 'Optional', + } +); + +export const REMOVE_REQUIRED_FIELD_BUTTON_ARIA_LABEL = i18n.translate( + 'xpack.securitySolution.detectionEngine.ruleDescription.requiredFields.removeRequiredFieldButtonAriaLabel', + { + defaultMessage: 'Remove required field', + } +); + +export const ADD_REQUIRED_FIELD = i18n.translate( + 'xpack.securitySolution.detectionEngine.ruleDescription.requiredFields.addRequiredFieldButtonLabel', + { + defaultMessage: 'Add required field', + } +); + +export const FIELD_NAME_NOT_FOUND_WARNING = (name: string) => + i18n.translate( + 'xpack.securitySolution.detectionEngine.ruleDescription.requiredFields.fieldNameNotFoundWarning', + { + values: { name }, + defaultMessage: `Field "{name}" is not found within the rule's specified index patterns`, + } + ); + +export const FIELD_TYPE_NOT_FOUND_WARNING = (name: string, type: string) => + i18n.translate( + 'xpack.securitySolution.detectionEngine.ruleDescription.requiredFields.fieldTypeNotFoundWarning', + { + values: { name, type }, + defaultMessage: `Field "{name}" with type "{type}" is not found within the rule's specified index patterns`, + } + ); + +export const FIELD_NAME_REQUIRED = i18n.translate( + 'xpack.securitySolution.detectionEngine.ruleDescription.requiredFields.validation.fieldNameRequired', + { + defaultMessage: 'Field name is required', + } +); + +export const FIELD_TYPE_REQUIRED = i18n.translate( + 'xpack.securitySolution.detectionEngine.ruleDescription.requiredFields.validation.fieldTypeRequired', + { + defaultMessage: 'Field type is required', + } +); + +export const FIELD_NAME_USED_MORE_THAN_ONCE = (name: string) => + i18n.translate( + 'xpack.securitySolution.detectionEngine.ruleDescription.requiredFields.validation.fieldNameUsedMoreThanOnce', + { + values: { name }, + defaultMessage: 'Field name "{name}" is already used', + } + ); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_creation/components/required_fields/type_combobox.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_creation/components/required_fields/type_combobox.tsx new file mode 100644 index 0000000000000..48d5a009c4abe --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_creation/components/required_fields/type_combobox.tsx @@ -0,0 +1,151 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { useCallback, useMemo, useState, useEffect } from 'react'; +import { EuiComboBox, EuiIcon } from '@elastic/eui'; +import type { EuiComboBoxOptionOption } from '@elastic/eui'; +import { euiThemeVars } from '@kbn/ui-theme'; +import type { FieldHook } from '../../../../shared_imports'; +import type { RequiredFieldInput } from '../../../../../common/api/detection_engine/model/rule_schema/common_attributes.gen'; +import * as i18n from './translations'; + +interface TypeComboBoxProps { + field: FieldHook; + itemId: string; + typesByFieldName: Record; + typeWarning: string; + typeError: { message: string } | undefined; +} + +export function TypeComboBox({ + field, + itemId, + typesByFieldName, + typeWarning, + typeError, +}: TypeComboBoxProps) { + const { value, setValue } = field; + + const selectableTypeOptions: Array> = useMemo(() => { + const typesAvailableForSelectedName = typesByFieldName[value.name]; + const isSelectedTypeAvailable = (typesAvailableForSelectedName || []).includes(value.type); + + if (typesAvailableForSelectedName && isSelectedTypeAvailable) { + /* + Case: name is available, type is not available + Selected field name is present in index patterns, so it has one or more types available for it. + Allowing the user to select from them. + */ + + return typesAvailableForSelectedName.map((type) => ({ + label: type, + value: type, + })); + } else if (typesAvailableForSelectedName) { + /* + Case: name is available, type is not available + Selected field name is present in index patterns, but the selected type doesn't exist for it. + Adding the selected type to the list of selectable options since it was selected before. + */ + return typesAvailableForSelectedName + .map((type) => ({ + label: type, + value: type, + })) + .concat({ label: value.type, value: value.type }); + } else if (value.name) { + /* + Case: name is not available (so the type is also not available) + Field name is set (not an empty string), but it's not present in index patterns. + In such case the only selectable type option is the currenty selected type. + */ + return [ + { + label: value.type, + value: value.type, + }, + ]; + } + + return []; + }, [value.name, value.type, typesByFieldName]); + + /* + Using a state for `selectedTypeOptions` instead of using the field value directly + to fix the issue where pressing the backspace key in combobox input would clear the field value + and trigger a validation error. By using a separate state, we can clear the selected option + without clearing the field value. + */ + const [selectedTypeOption, setSelectedTypeOption] = useState< + EuiComboBoxOptionOption | undefined + >(selectableTypeOptions.find((option) => option.value === value.type)); + + useEffect(() => { + /* Re-computing the new selected type option when the field value changes */ + setSelectedTypeOption(selectableTypeOptions.find((option) => option.value === value.type)); + }, [value.type, selectableTypeOptions]); + + const handleTypeChange = useCallback( + (selectedOptions: Array>) => { + const newlySelectedOption: EuiComboBoxOptionOption | undefined = selectedOptions[0]; + + if (!newlySelectedOption) { + /* This occurs when the user hits backspace in combobox */ + setSelectedTypeOption(undefined); + return; + } + + const updatedType = newlySelectedOption?.value || ''; + + const updatedFieldValue: RequiredFieldInput = { + name: value.name, + type: updatedType, + }; + + setValue(updatedFieldValue); + }, + [value.name, setValue] + ); + + const handleAddCustomType = useCallback( + (newType: string) => { + const updatedFieldValue: RequiredFieldInput = { + name: value.name, + type: newType, + }; + + setValue(updatedFieldValue); + }, + [value.name, setValue] + ); + + return ( + + ) : undefined + } + /> + ); +} diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_creation/components/required_fields/utils.test.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_creation/components/required_fields/utils.test.tsx new file mode 100644 index 0000000000000..235da2208a43b --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_creation/components/required_fields/utils.test.tsx @@ -0,0 +1,58 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { pickTypeForName } from './utils'; + +describe('pickTypeForName', () => { + it('returns the current type if it is available for the current name', () => { + const typesByFieldName = { + name1: ['text', 'keyword'], + }; + + expect( + pickTypeForName({ + name: 'name1', + type: 'keyword', + typesByFieldName, + }) + ).toEqual('keyword'); + }); + + it('returns the first available type if the current type is not available for the current name', () => { + const typesByFieldName = { + name1: ['text', 'keyword'], + }; + + expect( + pickTypeForName({ + name: 'name1', + type: 'long', + typesByFieldName, + }) + ).toEqual('text'); + }); + + it('returns the current type if no types are available for the current name', () => { + expect( + pickTypeForName({ + name: 'name1', + type: 'keyword', + typesByFieldName: {}, + }) + ).toEqual('keyword'); + + expect( + pickTypeForName({ + name: 'name1', + type: 'keyword', + typesByFieldName: { + name1: [], + }, + }) + ).toEqual('keyword'); + }); +}); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_creation/components/required_fields/utils.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_creation/components/required_fields/utils.ts new file mode 100644 index 0000000000000..55beca264e120 --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_creation/components/required_fields/utils.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. + */ + +interface PickTypeForNameParameters { + name: string; + type: string; + typesByFieldName?: Record; +} + +export function pickTypeForName({ name, type, typesByFieldName = {} }: PickTypeForNameParameters) { + const typesAvailableForName = typesByFieldName[name] || []; + const isCurrentTypeAvailableForNewName = typesAvailableForName.includes(type); + + /* First try to keep the type if it's available for the name */ + if (isCurrentTypeAvailableForNewName) { + return type; + } + + /* + If current type is not available, pick the first available type. + If no type is available, use the current type. + */ + return typesAvailableForName[0] ?? type; +} diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_creation_ui/components/description_step/helpers.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_creation_ui/components/description_step/helpers.tsx index aaf588edd3099..8ef2a3751a036 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_creation_ui/components/description_step/helpers.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_creation_ui/components/description_step/helpers.tsx @@ -18,12 +18,9 @@ import { } from '@elastic/eui'; import { ALERT_RISK_SCORE } from '@kbn/rule-data-utils'; -import { castEsToKbnFieldTypeName } from '@kbn/field-types'; - import { isEmpty } from 'lodash/fp'; import React from 'react'; import styled from 'styled-components'; -import { FieldIcon } from '@kbn/react-field'; import type { ThreatMapping, Type, Threats } from '@kbn/securitysolution-io-ts-alerting-types'; import { FilterBadgeGroup } from '@kbn/unified-search-plugin/public'; @@ -50,8 +47,10 @@ import type { } from '../../../../detections/pages/detection_engine/rules/types'; import { GroupByOptions } from '../../../../detections/pages/detection_engine/rules/types'; import { defaultToEmptyTag } from '../../../../common/components/empty_value'; +import { RequiredFieldIcon } from '../../../rule_management/components/rule_details/required_field_icon'; import { ThreatEuiFlexGroup } from './threat_description'; import { AlertSuppressionLabel } from './alert_suppression_label'; + const NoteDescriptionContainer = styled(EuiFlexItem)` height: 105px; overflow-y: hidden; @@ -566,11 +565,7 @@ export const buildRequiredFieldsDescription = ( - + diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_creation_ui/components/step_define_rule/index.test.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_creation_ui/components/step_define_rule/index.test.tsx index de34718ef050f..be1306d706357 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_creation_ui/components/step_define_rule/index.test.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_creation_ui/components/step_define_rule/index.test.tsx @@ -8,6 +8,7 @@ import React, { useEffect, useState } from 'react'; import { screen, fireEvent, render, within, act, waitFor } from '@testing-library/react'; import type { Type as RuleType } from '@kbn/securitysolution-io-ts-alerting-types'; +import type { DataViewBase } from '@kbn/es-query'; import { StepDefineRule, aggregatableFields } from '.'; import { mockBrowserFields } from '../../../../common/containers/source/mock'; import { useRuleFromTimeline } from '../../../../detections/containers/detection_engine/rules/use_rule_from_timeline'; @@ -18,6 +19,11 @@ import type { FormSubmitHandler } from '../../../../shared_imports'; import { useForm } from '../../../../shared_imports'; import type { DefineStepRule } from '../../../../detections/pages/detection_engine/rules/types'; import { fleetIntegrationsApi } from '../../../fleet_integrations/api/__mocks__'; +import { + addRequiredFieldRow, + createIndexPatternField, + getSelectToggleButtonForName, +} from '../../../rule_creation/components/required_fields/required_fields.test'; // Mocks integrations jest.mock('../../../fleet_integrations/api'); @@ -410,6 +416,116 @@ describe('StepDefineRule', () => { }); }); + describe('required fields', () => { + it('submits a form without selected required fields', async () => { + const initialState = { + index: ['test-index'], + queryBar: { + query: { query: '*:*', language: 'kuery' }, + filters: [], + saved_id: null, + }, + }; + const handleSubmit = jest.fn(); + + render(, { + wrapper: TestProviders, + }); + + await submitForm(); + + await waitFor(() => { + expect(handleSubmit).toHaveBeenCalled(); + }); + + expect(handleSubmit).toHaveBeenCalledWith( + expect.not.objectContaining({ + requiredFields: expect.anything(), + }), + true + ); + }); + + it('submits saved early required fields without the "ecs" property', async () => { + const initialState = { + index: ['test-index'], + queryBar: { + query: { query: '*:*', language: 'kuery' }, + filters: [], + saved_id: null, + }, + requiredFields: [{ name: 'host.name', type: 'string', ecs: false }], + }; + + const handleSubmit = jest.fn(); + + render(, { + wrapper: TestProviders, + }); + + await submitForm(); + + await waitFor(() => { + expect(handleSubmit).toHaveBeenCalled(); + }); + + expect(handleSubmit).toHaveBeenCalledWith( + expect.objectContaining({ + requiredFields: [{ name: 'host.name', type: 'string' }], + }), + true + ); + }); + + it('submits newly added required fields', async () => { + const initialState = { + index: ['test-index'], + queryBar: { + query: { query: '*:*', language: 'kuery' }, + filters: [], + saved_id: null, + }, + }; + + const indexPattern: DataViewBase = { + fields: [createIndexPatternField({ name: 'host.name', esTypes: ['string'] })], + title: '', + }; + + const handleSubmit = jest.fn(); + + render( + , + { + wrapper: TestProviders, + } + ); + + await addRequiredFieldRow(); + + await selectFirstEuiComboBoxOption({ + comboBoxToggleButton: getSelectToggleButtonForName('empty'), + }); + + await submitForm(); + + await waitFor(() => { + expect(handleSubmit).toHaveBeenCalled(); + }); + + expect(handleSubmit).toHaveBeenCalledWith( + expect.objectContaining({ + requiredFields: [{ name: 'host.name', type: 'string' }], + }), + true + ); + }); + }); + describe('handleSetRuleFromTimeline', () => { it('updates KQL query correctly', () => { const kqlQuery = { @@ -497,14 +613,16 @@ describe('StepDefineRule', () => { }); interface TestFormProps { - ruleType?: RuleType; initialState?: Partial; + ruleType?: RuleType; + indexPattern?: DataViewBase; onSubmit?: FormSubmitHandler; } function TestForm({ - ruleType = stepDefineDefaultValue.ruleType, initialState, + ruleType = stepDefineDefaultValue.ruleType, + indexPattern = { fields: [], title: '' }, onSubmit, }: TestFormProps): JSX.Element { const [selectedEqlOptions, setSelectedEqlOptions] = useState(stepDefineDefaultValue.eqlOptions); @@ -524,7 +642,7 @@ function TestForm({ threatIndicesConfig={[]} optionsSelected={selectedEqlOptions} setOptionsSelected={setSelectedEqlOptions} - indexPattern={{ fields: [], title: '' }} + indexPattern={indexPattern} isIndexPatternLoading={false} browserFields={{}} isQueryBarValid={true} @@ -560,32 +678,71 @@ function addRelatedIntegrationRow(): Promise { }); } +function setVersion({ input, value }: { input: HTMLInputElement; value: string }): Promise { + return act(async () => { + fireEvent.input(input, { + target: { value }, + }); + }); +} + function showEuiComboBoxOptions(comboBoxToggleButton: HTMLElement): Promise { fireEvent.click(comboBoxToggleButton); return waitFor(() => { - expect(screen.getByRole('listbox')).toBeInTheDocument(); + const listWithOptionsElement = document.querySelector('[role="listbox"]'); + const emptyListElement = document.querySelector('.euiComboBoxOptionsList__empty'); + + expect(listWithOptionsElement || emptyListElement).toBeInTheDocument(); }); } +type SelectEuiComboBoxOptionParameters = + | { + comboBoxToggleButton: HTMLElement; + optionIndex: number; + optionText?: undefined; + } + | { + comboBoxToggleButton: HTMLElement; + optionText: string; + optionIndex?: undefined; + }; + function selectEuiComboBoxOption({ comboBoxToggleButton, optionIndex, -}: { - comboBoxToggleButton: HTMLElement; - optionIndex: number; -}): Promise { + optionText, +}: SelectEuiComboBoxOptionParameters): Promise { return act(async () => { await showEuiComboBoxOptions(comboBoxToggleButton); - fireEvent.click(within(screen.getByRole('listbox')).getAllByRole('option')[optionIndex]); + const options = Array.from( + document.querySelectorAll('[data-test-subj*="comboBoxOptionsList"] [role="option"]') + ); + + if (typeof optionText === 'string') { + const optionToSelect = options.find((option) => option.textContent === optionText); + + if (optionToSelect) { + fireEvent.click(optionToSelect); + } else { + throw new Error( + `Could not find option with text "${optionText}". Available options: ${options + .map((option) => option.textContent) + .join(', ')}` + ); + } + } else { + fireEvent.click(options[optionIndex]); + } }); } -function setVersion({ input, value }: { input: HTMLInputElement; value: string }): Promise { - return act(async () => { - fireEvent.input(input, { - target: { value }, - }); - }); +function selectFirstEuiComboBoxOption({ + comboBoxToggleButton, +}: { + comboBoxToggleButton: HTMLElement; +}): Promise { + return selectEuiComboBoxOption({ comboBoxToggleButton, optionIndex: 0 }); } diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_creation_ui/components/step_define_rule/index.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_creation_ui/components/step_define_rule/index.tsx index f0dcadc056315..56073e2a6af59 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_creation_ui/components/step_define_rule/index.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_creation_ui/components/step_define_rule/index.tsx @@ -90,6 +90,7 @@ import type { BrowserField } from '../../../../common/containers/source'; import { useFetchIndex } from '../../../../common/containers/source'; import { NewTermsFields } from '../new_terms_fields'; import { ScheduleItem } from '../../../rule_creation/components/schedule_item_form'; +import { RequiredFields } from '../../../rule_creation/components/required_fields'; import { DocLink } from '../../../../common/components/links_to_docs/doc_link'; import { defaultCustomQuery } from '../../../../detections/pages/detection_engine/rules/utils'; import { MultiSelectFieldsAutocomplete } from '../multi_select_fields'; @@ -915,7 +916,6 @@ const StepDefineRuleComponent: FC = ({ )} - {isQueryRule(ruleType) && ( <> @@ -940,7 +940,6 @@ const StepDefineRuleComponent: FC = ({ )} - <> = ({ /> - <> @@ -1116,6 +1114,19 @@ const StepDefineRuleComponent: FC = ({ + + + {!isMlRule(ruleType) && ( + <> + + + + )} + = { }, relatedIntegrations: { type: FIELD_TYPES.JSON, + label: i18n.translate( + 'xpack.securitySolution.detectionEngine.createRule.stepAboutRule.fieldRelatedIntegrationsLabel', + { + defaultMessage: 'Related integrations', + } + ), }, requiredFields: { label: i18n.translate( diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_creation_ui/hooks/use_esql_index.test.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_creation_ui/hooks/use_esql_index.test.ts index dc4394be257e5..2f5065eb113be 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_creation_ui/hooks/use_esql_index.test.ts +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_creation_ui/hooks/use_esql_index.test.ts @@ -10,29 +10,28 @@ import { useEsqlIndex } from './use_esql_index'; const validEsqlQuery = 'from auditbeat* metadata _id, _index, _version'; describe('useEsqlIndex', () => { - it('should return empty array if isQueryReadEnabled is undefined', () => { - const { result } = renderHook(() => useEsqlIndex(validEsqlQuery, 'esql', undefined)); + it('should return parsed index array from a valid query', async () => { + const { result } = renderHook(() => useEsqlIndex(validEsqlQuery, 'esql')); - expect(result.current).toEqual([]); + expect(result.current).toEqual(['auditbeat*']); }); - it('should return empty array if isQueryReadEnabled is false', () => { - const { result } = renderHook(() => useEsqlIndex(validEsqlQuery, 'esql', false)); + it('should return empty array if rule type is not esql', async () => { + const { result } = renderHook(() => useEsqlIndex(validEsqlQuery, 'query')); expect(result.current).toEqual([]); }); - it('should return empty array if rule type is not esql', () => { - const { result } = renderHook(() => useEsqlIndex(validEsqlQuery, 'query', true)); - expect(result.current).toEqual([]); - }); - it('should return empty array if query is empty', () => { - const { result } = renderHook(() => useEsqlIndex('', 'esql', true)); + it('should return empty array if query is empty', async () => { + const { result } = renderHook(() => useEsqlIndex('', 'esql')); expect(result.current).toEqual([]); }); - it('should return parsed index array from a valid query', () => { - const { result } = renderHook(() => useEsqlIndex(validEsqlQuery, 'esql', true)); - expect(result.current).toEqual(['auditbeat*']); + it('should return empty array if invalid query is causing a TypeError in ES|QL parser', async () => { + const typeErrorCausingQuery = 'from auditbeat* []'; + + const { result } = renderHook(() => useEsqlIndex(typeErrorCausingQuery, 'esql')); + + expect(result.current).toEqual([]); }); }); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_creation_ui/hooks/use_esql_index.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_creation_ui/hooks/use_esql_index.ts index 508f2272b69ab..358c1fc70a945 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_creation_ui/hooks/use_esql_index.ts +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_creation_ui/hooks/use_esql_index.ts @@ -4,7 +4,8 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import { useMemo } from 'react'; +import { useMemo, useState } from 'react'; +import useDebounce from 'react-use/lib/useDebounce'; import { getIndexPatternFromESQLQuery } from '@kbn/esql-utils'; import { getIndexListFromIndexString } from '@kbn/securitysolution-utils'; @@ -15,23 +16,39 @@ import { isEsqlRule } from '../../../../common/detection_engine/utils'; /** * parses ES|QL query and returns memoized array of indices - * @param query - ES|QL query to retrieve index from + * @param query - ES|QL query to retrieve indices from * @param ruleType - rule type value - * @param isQueryReadEnabled - if not enabled, return empty array. Useful if we know form or query is not valid and we don't want to retrieve index - * @returns + * @returns string[] - array of indices. Array is empty if query is invalid or ruleType is not 'esql'. */ -export const useEsqlIndex = ( - query: Query['query'], - ruleType: Type, - isQueryReadEnabled: boolean | undefined -) => { +export const useEsqlIndex = (query: Query['query'], ruleType: Type): string[] => { + const [debouncedQuery, setDebouncedQuery] = useState(query); + + useDebounce( + () => { + /* + Triggerring the ES|QL parser a few moments after the user has finished typing + to avoid unnecessary calls to the parser. + */ + setDebouncedQuery(query); + }, + 300, + [query] + ); + const indexString = useMemo(() => { - if (!isQueryReadEnabled) { + const esqlQuery = + typeof debouncedQuery === 'string' && isEsqlRule(ruleType) ? debouncedQuery : undefined; + + try { + return getIndexPatternFromESQLQuery(esqlQuery); + } catch (error) { + /* + Some invalid queries cause ES|QL parser to throw a TypeError. + Treating such cases as if parser returned an empty string. + */ return ''; } - const esqlQuery = typeof query === 'string' && isEsqlRule(ruleType) ? query : undefined; - return getIndexPatternFromESQLQuery(esqlQuery); - }, [query, isQueryReadEnabled, ruleType]); + }, [debouncedQuery, ruleType]); const index = useMemo(() => getIndexListFromIndexString(indexString), [indexString]); return index; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_creation_ui/pages/rule_creation/helpers.test.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_creation_ui/pages/rule_creation/helpers.test.ts index 20a432cdc1420..b61cdbc386ee1 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_creation_ui/pages/rule_creation/helpers.test.ts +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_creation_ui/pages/rule_creation/helpers.test.ts @@ -140,6 +140,7 @@ describe('helpers', () => { version: '^1.2.3', }, ], + required_fields: [{ name: 'host.name', type: 'keyword' }], }; expect(result).toEqual(expected); @@ -178,6 +179,20 @@ describe('helpers', () => { }); }); + test('filters out empty required fields', () => { + const result = formatDefineStepData({ + ...mockData, + requiredFields: [ + { name: 'host.name', type: 'keyword' }, + { name: '', type: '' }, + ], + }); + + expect(result).toMatchObject({ + required_fields: [{ name: 'host.name', type: 'keyword' }], + }); + }); + describe('saved_query and query rule types', () => { test('returns query rule if savedId provided but shouldLoadQueryDynamically != true', () => { const mockStepData: DefineStepRule = { @@ -567,6 +582,7 @@ describe('helpers', () => { version: '^1.2.3', }, ], + required_fields: [{ name: 'host.name', type: 'keyword' }], }; expect(result).toEqual(expected); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_creation_ui/pages/rule_creation/helpers.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_creation_ui/pages/rule_creation/helpers.ts index 3054a894d0df1..11da431e3e602 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_creation_ui/pages/rule_creation/helpers.ts +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_creation_ui/pages/rule_creation/helpers.ts @@ -48,6 +48,7 @@ import { import type { RuleCreateProps, AlertSuppression, + RequiredFieldInput, } from '../../../../../common/api/detection_engine/model/rule_schema'; import { stepActionsDefaultValue } from '../../../rule_creation/components/step_rule_actions'; import { DEFAULT_SUPPRESSION_MISSING_FIELDS_STRATEGY } from '../../../../../common/detection_engine/constants'; @@ -395,6 +396,12 @@ export const getStepDataDataSource = ( return copiedStepData; }; +/** + * Strips away form rows that were not filled out by the user + */ +const removeEmptyRequiredFields = (requiredFields: RequiredFieldInput[]): RequiredFieldInput[] => + requiredFields.filter((field) => field.name !== '' && field.type !== ''); + export const formatDefineStepData = (defineStepData: DefineStepRule): DefineStepRuleJson => { const stepData = getStepDataDataSource(defineStepData); @@ -426,6 +433,8 @@ export const formatDefineStepData = (defineStepData: DefineStepRule): DefineStep } : {}; + const requiredFields = removeEmptyRequiredFields(defineStepData.requiredFields ?? []); + const typeFields = isMlFields(ruleFields) ? { anomaly_threshold: ruleFields.anomalyThreshold, @@ -438,6 +447,7 @@ export const formatDefineStepData = (defineStepData: DefineStepRule): DefineStep language: ruleFields.queryBar?.query?.language, query: ruleFields.queryBar?.query?.query as string, saved_id: ruleFields.queryBar?.saved_id ?? undefined, + required_fields: requiredFields, ...(ruleType === 'threshold' && { threshold: { field: ruleFields.threshold?.field ?? [], @@ -465,6 +475,7 @@ export const formatDefineStepData = (defineStepData: DefineStepRule): DefineStep language: ruleFields.queryBar?.query?.language, query: ruleFields.queryBar?.query?.query as string, saved_id: ruleFields.queryBar?.saved_id ?? undefined, + required_fields: requiredFields, threat_index: ruleFields.threatIndex, threat_query: ruleFields.threatQueryBar?.query?.query as string, threat_filters: ruleFields.threatQueryBar?.filters, @@ -479,6 +490,7 @@ export const formatDefineStepData = (defineStepData: DefineStepRule): DefineStep language: ruleFields.queryBar?.query?.language, query: ruleFields.queryBar?.query?.query as string, saved_id: ruleFields.queryBar?.saved_id ?? undefined, + required_fields: requiredFields, timestamp_field: ruleFields.eqlOptions?.timestampField, event_category_override: ruleFields.eqlOptions?.eventCategoryField, tiebreaker_field: ruleFields.eqlOptions?.tiebreakerField, @@ -490,6 +502,7 @@ export const formatDefineStepData = (defineStepData: DefineStepRule): DefineStep filters: ruleFields.queryBar?.filters, language: ruleFields.queryBar?.query?.language, query: ruleFields.queryBar?.query?.query as string, + required_fields: requiredFields, new_terms_fields: ruleFields.newTermsFields, history_window_start: `now-${ruleFields.historyWindowSize}`, ...alertSuppressionFields, @@ -498,6 +511,7 @@ export const formatDefineStepData = (defineStepData: DefineStepRule): DefineStep ? { language: ruleFields.queryBar?.query?.language, query: ruleFields.queryBar?.query?.query as string, + required_fields: requiredFields, } : { ...alertSuppressionFields, @@ -506,6 +520,7 @@ export const formatDefineStepData = (defineStepData: DefineStepRule): DefineStep language: ruleFields.queryBar?.query?.language, query: ruleFields.queryBar?.query?.query as string, saved_id: undefined, + required_fields: requiredFields, type: 'query' as const, // rule only be updated as saved_query type if it has saved_id and shouldLoadQueryDynamically checkbox checked ...(['query', 'saved_query'].includes(ruleType) && diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_creation_ui/pages/rule_creation/index.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_creation_ui/pages/rule_creation/index.tsx index d57198522b388..806ea9f336bd5 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_creation_ui/pages/rule_creation/index.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_creation_ui/pages/rule_creation/index.tsx @@ -210,11 +210,9 @@ const CreateRulePageComponent: React.FC = () => { const [isThreatQueryBarValid, setIsThreatQueryBarValid] = useState(false); const esqlQueryForAboutStep = useEsqlQueryForAboutStep({ defineStepData, activeStep }); - const esqlIndex = useEsqlIndex( - defineStepData.queryBar.query.query, - ruleType, - defineStepForm.isValid - ); + + const esqlIndex = useEsqlIndex(defineStepData.queryBar.query.query, ruleType); + const memoizedIndex = useMemo( () => (isEsqlRuleValue ? esqlIndex : defineStepData.index), [defineStepData.index, esqlIndex, isEsqlRuleValue] diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_creation_ui/pages/rule_editing/index.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_creation_ui/pages/rule_editing/index.tsx index 768b5a9903691..47b67c8ed720a 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_creation_ui/pages/rule_editing/index.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_creation_ui/pages/rule_editing/index.tsx @@ -150,13 +150,9 @@ const EditRulePageComponent: FC<{ rule: RuleResponse }> = ({ rule }) => { }); const esqlQueryForAboutStep = useEsqlQueryForAboutStep({ defineStepData, activeStep }); - const esqlIndex = useEsqlIndex( - defineStepData.queryBar.query.query, - defineStepData.ruleType, - // allow to compute index from query only when query is valid or user switched to another tab - // to prevent multiple data view initiations with partly typed index names - defineStepForm.isValid || activeStep !== RuleStep.defineRule - ); + + const esqlIndex = useEsqlIndex(defineStepData.queryBar.query.query, defineStepData.ruleType); + const memoizedIndex = useMemo( () => (isEsqlRule(defineStepData.ruleType) ? esqlIndex : defineStepData.index), [defineStepData.index, esqlIndex, defineStepData.ruleType] diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/required_field_icon.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/required_field_icon.tsx new file mode 100644 index 0000000000000..0001bae25dd89 --- /dev/null +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/required_field_icon.tsx @@ -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 React from 'react'; +import { ES_FIELD_TYPES } from '@kbn/field-types'; +import { FieldIcon } from '@kbn/field-utils'; +import type { FieldIconProps } from '@kbn/field-utils'; + +function mapEsTypesToIconProps(type: string) { + switch (type) { + case ES_FIELD_TYPES._ID: + case ES_FIELD_TYPES._INDEX: + /* In Discover "_id" and "_index" have the "keyword" icon. Doing same here for consistency */ + return { type: 'keyword' }; + case ES_FIELD_TYPES.OBJECT: + return { type, iconType: 'tokenObject' }; + case ES_FIELD_TYPES.DATE_NANOS: + return { type: 'date' }; + case ES_FIELD_TYPES.FLOAT: + case ES_FIELD_TYPES.HALF_FLOAT: + case ES_FIELD_TYPES.SCALED_FLOAT: + case ES_FIELD_TYPES.DOUBLE: + case ES_FIELD_TYPES.INTEGER: + case ES_FIELD_TYPES.LONG: + case ES_FIELD_TYPES.SHORT: + case ES_FIELD_TYPES.UNSIGNED_LONG: + case ES_FIELD_TYPES.AGGREGATE_METRIC_DOUBLE: + case ES_FIELD_TYPES.FLOAT_RANGE: + case ES_FIELD_TYPES.DOUBLE_RANGE: + case ES_FIELD_TYPES.INTEGER_RANGE: + case ES_FIELD_TYPES.LONG_RANGE: + case ES_FIELD_TYPES.BYTE: + case ES_FIELD_TYPES.TOKEN_COUNT: + return { type: 'number' }; + default: + return { type }; + } +} + +interface RequiredFieldIconProps extends FieldIconProps { + type: string; + label?: string; + 'data-test-subj': string; +} + +/** + * `FieldIcon` component with addtional icons for types that are not handled by the `FieldIcon` component. + */ +export function RequiredFieldIcon({ + type, + label = type, + 'data-test-subj': dataTestSubj, + ...props +}: RequiredFieldIconProps) { + return ( + + ); +} diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/rule_definition_section.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/rule_definition_section.tsx index 912af1b0c4589..35f429f776fab 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/rule_definition_section.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management/components/rule_details/rule_definition_section.tsx @@ -24,8 +24,6 @@ import type { Filter } from '@kbn/es-query'; import type { SavedQuery } from '@kbn/data-plugin/public'; import { mapAndFlattenFilters } from '@kbn/data-plugin/public'; import type { DataView } from '@kbn/data-views-plugin/public'; -import { FieldIcon } from '@kbn/react-field'; -import { castEsToKbnFieldTypeName } from '@kbn/field-types'; import { FilterItems } from '@kbn/unified-search-plugin/public'; import type { AlertSuppressionMissingFieldsStrategy, @@ -53,6 +51,7 @@ import { BadgeList } from './badge_list'; import { DEFAULT_DESCRIPTION_LIST_COLUMN_WIDTHS } from './constants'; import * as i18n from './translations'; import { useAlertSuppression } from '../../logic/use_alert_suppression'; +import { RequiredFieldIcon } from './required_field_icon'; import { filtersStyles, queryStyles, @@ -254,17 +253,14 @@ interface RequiredFieldsProps { const RequiredFields = ({ requiredFields }: RequiredFieldsProps) => { const styles = useRequiredFieldsStyles(); + return ( {requiredFields.map((rF, index) => ( - + ({ dataViewId: undefined, queryBar: mockQueryBar, threatQueryBar: mockQueryBar, - requiredFields: [], + requiredFields: [{ name: 'host.name', type: 'keyword' }], relatedIntegrations: [ { package: 'aws', diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/rules_table_toolbar.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/rules_table_toolbar.tsx index fb2c17ddb2fa1..e3618a1383598 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/rules_table_toolbar.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/rules_table_toolbar.tsx @@ -78,7 +78,7 @@ export const RulesTableToolbar = React.memo(() => { ); // Assistant integration for using selected rules as prompt context - const { hasAssistantPrivilege } = useAssistantAvailability(); + const { hasAssistantPrivilege, isAssistantEnabled } = useAssistantAvailability(); const { state: { rules, selectedRuleIds }, } = useRulesTableContext(); @@ -105,6 +105,7 @@ export const RulesTableToolbar = React.memo(() => { getPromptContext={getPromptContext} suggestedUserPrompt={i18nAssistant.EXPLAIN_THEN_SUMMARIZE_RULE_DETAILS} tooltip={i18nAssistant.RULE_MANAGEMENT_CONTEXT_TOOLTIP} + isAssistantEnabled={isAssistantEnabled} /> )} diff --git a/x-pack/plugins/security_solution/public/detections/components/rules/rule_execution_status/rule_status_failed_callout.tsx b/x-pack/plugins/security_solution/public/detections/components/rules/rule_execution_status/rule_status_failed_callout.tsx index ba7f57aba5648..170cdaf265d4a 100644 --- a/x-pack/plugins/security_solution/public/detections/components/rules/rule_execution_status/rule_status_failed_callout.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/rules/rule_execution_status/rule_status_failed_callout.tsx @@ -33,7 +33,7 @@ const RuleStatusFailedCallOutComponent: React.FC = message, status, }) => { - const { hasAssistantPrivilege } = useAssistantAvailability(); + const { hasAssistantPrivilege, isAssistantEnabled } = useAssistantAvailability(); const { shouldBeDisplayed, color, title } = getPropsByStatus(status); const getPromptContext = useCallback( async () => @@ -84,6 +84,7 @@ const RuleStatusFailedCallOutComponent: React.FC = getPromptContext={getPromptContext} suggestedUserPrompt={i18n.ASK_ASSISTANT_USER_PROMPT} tooltip={i18n.ASK_ASSISTANT_TOOLTIP} + isAssistantEnabled={isAssistantEnabled} > {i18n.ASK_ASSISTANT_ERROR_BUTTON} diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/types.ts b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/types.ts index 4757c9f29dfdc..1bf915e1a122f 100644 --- a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/types.ts +++ b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/types.ts @@ -26,7 +26,6 @@ import type { FieldValueThreshold } from '../../../../detection_engine/rule_crea import type { BuildingBlockType, RelatedIntegrationArray, - RequiredFieldArray, RuleAuthorArray, RuleLicense, RuleNameOverride, @@ -38,6 +37,7 @@ import type { AlertSuppression, ThresholdAlertSuppression, RelatedIntegration, + RequiredFieldInput, } from '../../../../../common/api/detection_engine/model/rule_schema'; import type { SortOrder } from '../../../../../common/api/detection_engine'; import type { EqlOptionsSelected } from '../../../../../common/search_strategy'; @@ -147,7 +147,7 @@ export interface DefineStepRule { dataViewId?: string; dataViewTitle?: string; relatedIntegrations?: RelatedIntegrationArray; - requiredFields: RequiredFieldArray; + requiredFields?: RequiredFieldInput[]; ruleType: Type; timeline: FieldValueTimeline; threshold: FieldValueThreshold; @@ -226,6 +226,7 @@ export interface DefineStepRuleJson { tiebreaker_field?: string; alert_suppression?: AlertSuppression | ThresholdAlertSuppression; related_integrations?: RelatedIntegration[]; + required_fields?: RequiredFieldInput[]; } export interface AboutStepRuleJson { diff --git a/x-pack/plugins/security_solution/public/entity_analytics/components/entity_analytics_risk_score/index.tsx b/x-pack/plugins/security_solution/public/entity_analytics/components/entity_analytics_risk_score/index.tsx index 71ab20090ff01..edf7bce0a9938 100644 --- a/x-pack/plugins/security_solution/public/entity_analytics/components/entity_analytics_risk_score/index.tsx +++ b/x-pack/plugins/security_solution/public/entity_analytics/components/entity_analytics_risk_score/index.tsx @@ -160,7 +160,7 @@ const EntityAnalyticsRiskScoresComponent = ({ riskEntity }: { riskEntity: RiskSc const refreshPage = useRefetchQueries(); - const privileges = useMissingRiskEnginePrivileges(); + const privileges = useMissingRiskEnginePrivileges(['read']); if (!isAuthorized) { return null; diff --git a/x-pack/plugins/security_solution/public/entity_analytics/hooks/use_missing_risk_engine_privileges.ts b/x-pack/plugins/security_solution/public/entity_analytics/hooks/use_missing_risk_engine_privileges.ts index d51c2b2dfb49d..9fa4c8d4b3881 100644 --- a/x-pack/plugins/security_solution/public/entity_analytics/hooks/use_missing_risk_engine_privileges.ts +++ b/x-pack/plugins/security_solution/public/entity_analytics/hooks/use_missing_risk_engine_privileges.ts @@ -6,9 +6,13 @@ */ import { useMemo } from 'react'; +import type { NonEmptyArray } from 'fp-ts/lib/NonEmptyArray'; import { useRiskEnginePrivileges } from '../api/hooks/use_risk_engine_privileges'; import { getMissingRiskEnginePrivileges } from '../../../common/entity_analytics/risk_engine'; -import type { MissingPrivileges } from '../../../common/entity_analytics/risk_engine'; +import type { + MissingPrivileges, + RiskEngineIndexPrivilege, +} from '../../../common/entity_analytics/risk_engine'; export type RiskEngineMissingPrivilegesResponse = | { isLoading: true } | { isLoading: false; hasAllRequiredPrivileges: true } @@ -18,7 +22,9 @@ export type RiskEngineMissingPrivilegesResponse = hasAllRequiredPrivileges: false; }; -export const useMissingRiskEnginePrivileges = (): RiskEngineMissingPrivilegesResponse => { +export const useMissingRiskEnginePrivileges = ( + required: NonEmptyArray = ['read', 'write'] +): RiskEngineMissingPrivilegesResponse => { const { data: privilegesResponse, isLoading } = useRiskEnginePrivileges(); return useMemo(() => { @@ -36,9 +42,19 @@ export const useMissingRiskEnginePrivileges = (): RiskEngineMissingPrivilegesRes } const { indexPrivileges, clusterPrivileges } = getMissingRiskEnginePrivileges( - privilegesResponse.privileges + privilegesResponse.privileges, + required ); + // privilegesResponse.has_all_required` is slightly misleading, it checks if it has *all* default required privileges. + // Here we check if there are no missing privileges of the provided set of required privileges + if (indexPrivileges.every(([_, missingPrivileges]) => missingPrivileges.length === 0)) { + return { + isLoading: false, + hasAllRequiredPrivileges: true, + }; + } + return { isLoading: false, hasAllRequiredPrivileges: false, @@ -47,5 +63,5 @@ export const useMissingRiskEnginePrivileges = (): RiskEngineMissingPrivilegesRes clusterPrivileges, }, }; - }, [isLoading, privilegesResponse]); + }, [isLoading, privilegesResponse, required]); }; diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/right/hooks/use_assistant.ts b/x-pack/plugins/security_solution/public/flyout/document_details/right/hooks/use_assistant.ts index 185591ff43a2d..2196674964cfe 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/right/hooks/use_assistant.ts +++ b/x-pack/plugins/security_solution/public/flyout/document_details/right/hooks/use_assistant.ts @@ -56,7 +56,7 @@ export const useAssistant = ({ dataFormattedForFieldBrowser, isAlert, }: UseAssistantParams): UseAssistantResult => { - const { hasAssistantPrivilege } = useAssistantAvailability(); + const { hasAssistantPrivilege, isAssistantEnabled } = useAssistantAvailability(); const useAssistantHook = hasAssistantPrivilege ? useAssistantOverlay : useAssistantNoop; const getPromptContext = useCallback( async () => getRawData(dataFormattedForFieldBrowser ?? []), @@ -73,7 +73,8 @@ export const useAssistant = ({ isAlert ? PROMPT_CONTEXTS[PROMPT_CONTEXT_ALERT_CATEGORY].suggestedUserPrompt : PROMPT_CONTEXTS[PROMPT_CONTEXT_EVENT_CATEGORY].suggestedUserPrompt, - isAlert ? ALERT_SUMMARY_VIEW_CONTEXT_TOOLTIP : EVENT_SUMMARY_VIEW_CONTEXT_TOOLTIP + isAlert ? ALERT_SUMMARY_VIEW_CONTEXT_TOOLTIP : EVENT_SUMMARY_VIEW_CONTEXT_TOOLTIP, + isAssistantEnabled ); return { diff --git a/x-pack/plugins/security_solution/public/management/cypress/cypress_base.config.ts b/x-pack/plugins/security_solution/public/management/cypress/cypress_base.config.ts index 6d8136fe2f22d..a2755f360d833 100644 --- a/x-pack/plugins/security_solution/public/management/cypress/cypress_base.config.ts +++ b/x-pack/plugins/security_solution/public/management/cypress/cypress_base.config.ts @@ -27,6 +27,7 @@ export const getCypressBaseConfig = ( configFile: './public/management/reporter_config.json', }, + chromeWebSecurity: false, defaultCommandTimeout: 60000, execTimeout: 120000, pageLoadTimeout: 12000, @@ -42,8 +43,8 @@ export const getCypressBaseConfig = ( video: true, videoCompression: 15, videosFolder: '../../../target/kibana-security-solution/public/management/cypress/videos', - viewportHeight: 900, - viewportWidth: 1440, + viewportHeight: 1200, + viewportWidth: 1920, experimentalStudio: true, env: { @@ -80,6 +81,18 @@ export const getCypressBaseConfig = ( experimentalMemoryManagement: true, experimentalInteractiveRunEvents: true, setupNodeEvents: (on: Cypress.PluginEvents, config: Cypress.PluginConfigOptions) => { + on('before:browser:launch', (browser, launchOptions) => { + if (browser.name === 'chrome' && browser.isHeadless) { + launchOptions.args.push('--window-size=1920,1200'); + return launchOptions; + } + if (browser.family === 'chromium') { + launchOptions.args.push( + '--js-flags="--max_old_space_size=4096 --max_semi_space_size=1024"' + ); + } + return launchOptions; + }); registerDataSession(on, config); // IMPORTANT: setting the log level should happen before any tooling is called setupToolingLogLevel(config); 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 dedbbf607b3f0..4aa8085fbf571 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 @@ -83,7 +83,9 @@ describe( }); for (const testData of getArtifactsListTestsData()) { - describe(`${testData.title} tab`, () => { + // FLAKY: https://github.com/elastic/kibana/issues/183670 + // FLAKY: https://github.com/elastic/kibana/issues/183671 + describe.skip(`${testData.title} tab`, () => { beforeEach(() => { login(); removeExceptionsList(testData.createRequestBody.list_id); diff --git a/x-pack/plugins/security_solution/public/management/cypress/e2e/artifacts/artifacts_mocked_data.cy.ts b/x-pack/plugins/security_solution/public/management/cypress/e2e/artifacts/artifacts_mocked_data.cy.ts index 9227eb80153fb..22a796767a530 100644 --- a/x-pack/plugins/security_solution/public/management/cypress/e2e/artifacts/artifacts_mocked_data.cy.ts +++ b/x-pack/plugins/security_solution/public/management/cypress/e2e/artifacts/artifacts_mocked_data.cy.ts @@ -50,7 +50,10 @@ describe('Artifacts pages', { tags: ['@ess', '@serverless', '@skipInServerlessMK }); for (const testData of getArtifactsListTestsData()) { - describe(`When on the ${testData.title} entries list`, () => { + // FLAKY: https://github.com/elastic/kibana/issues/183718 + // FLAKY: https://github.com/elastic/kibana/issues/183719 + // FLAKY: https://github.com/elastic/kibana/issues/183720 + describe.skip(`When on the ${testData.title} entries list`, () => { it(`no access - should show no privileges callout`, () => { loginWithoutAccess(`/app/security/administration/${testData.urlPath}`); cy.getByTestSubj('noPrivilegesPage').should('exist'); diff --git a/x-pack/plugins/security_solution/public/management/cypress/e2e/endpoint_list/endpoints.cy.ts b/x-pack/plugins/security_solution/public/management/cypress/e2e/endpoint_list/endpoints.cy.ts index 0aeb46b32fb43..4396937e57228 100644 --- a/x-pack/plugins/security_solution/public/management/cypress/e2e/endpoint_list/endpoints.cy.ts +++ b/x-pack/plugins/security_solution/public/management/cypress/e2e/endpoint_list/endpoints.cy.ts @@ -28,8 +28,7 @@ import { createEndpointHost } from '../../tasks/create_endpoint_host'; import { deleteAllLoadedEndpointData } from '../../tasks/delete_all_endpoint_data'; import { enableAllPolicyProtections } from '../../tasks/endpoint_policy'; -// FLAKY: https://github.com/elastic/kibana/issues/168284 -describe.skip('Endpoints page', { tags: ['@ess', '@serverless'] }, () => { +describe('Endpoints page', { tags: ['@ess', '@serverless'] }, () => { let indexedPolicy: IndexedFleetEndpointPolicyResponse; let policy: PolicyData; let createdHost: CreateAndEnrollEndpointHostResponse; diff --git a/x-pack/plugins/security_solution/public/management/cypress/e2e/policy/policy_details.cy.ts b/x-pack/plugins/security_solution/public/management/cypress/e2e/policy/policy_details.cy.ts index 0bc6e907fe827..c587c9b9cf8e2 100644 --- a/x-pack/plugins/security_solution/public/management/cypress/e2e/policy/policy_details.cy.ts +++ b/x-pack/plugins/security_solution/public/management/cypress/e2e/policy/policy_details.cy.ts @@ -38,6 +38,17 @@ describe( }, }, () => { + const getAutomaticUpdatesToggle = () => cy.getByTestSubj('protection-updates-manifest-switch'); + const clickAutomaticUpdatesToggle = () => getAutomaticUpdatesToggle().click(); + + const getProtectionUpdatesSaveButton = () => cy.getByTestSubj('protectionUpdatesSaveButton'); + const clickProtectionUpdatesSaveButton = () => getProtectionUpdatesSaveButton().click(); + + const [expectSavedButtonToBeDisabled, expectSavedButtonToBeEnabled] = [ + () => getProtectionUpdatesSaveButton().should('be.disabled'), + () => getProtectionUpdatesSaveButton().should('be.enabled'), + ]; + describe('Protection updates', () => { const loadProtectionUpdatesUrl = (policyId: string) => loadPage(`/app/security/administration/policy/${policyId}/protectionUpdates`); @@ -71,11 +82,10 @@ describe( loadProtectionUpdatesUrl(policy.id); cy.getByTestSubj('protection-updates-warning-callout'); cy.getByTestSubj('protection-updates-automatic-updates-enabled'); - cy.getByTestSubj('protection-updates-manifest-switch'); + getAutomaticUpdatesToggle(); cy.getByTestSubj('protection-updates-manifest-name-title'); - cy.getByTestSubj('protectionUpdatesSaveButton').should('be.disabled'); - - cy.getByTestSubj('protection-updates-manifest-switch').click(); + expectSavedButtonToBeDisabled(); + clickAutomaticUpdatesToggle(); cy.getByTestSubj('protection-updates-manifest-name-deployed-version-title'); cy.getByTestSubj('protection-updates-deployed-version').contains('latest'); @@ -85,12 +95,12 @@ describe( }); cy.getByTestSubj('protection-updates-manifest-name-note-title'); cy.getByTestSubj('protection-updates-manifest-note'); - cy.getByTestSubj('protectionUpdatesSaveButton').should('be.enabled'); + expectSavedButtonToBeEnabled(); }); it('should display warning modal when user has unsaved changes', () => { loadProtectionUpdatesUrl(policy.id); - cy.getByTestSubj('protection-updates-manifest-switch').click(); + clickAutomaticUpdatesToggle(); cy.getByTestSubj('policySettingsTab').click(); cy.getByTestSubj('policyDetailsUnsavedChangesModal').within(() => { cy.getByTestSubj('confirmModalCancelButton').click(); @@ -104,17 +114,25 @@ describe( }); it('should successfully update the manifest version to custom date', () => { + const todayMinusTwoDays = moment.utc().subtract(2, 'days'); + loadProtectionUpdatesUrl(policy.id); - cy.getByTestSubj('protectionUpdatesSaveButton').should('be.disabled'); - cy.getByTestSubj('protection-updates-manifest-switch').click(); + expectSavedButtonToBeDisabled(); + clickAutomaticUpdatesToggle(); cy.getByTestSubj('protection-updates-manifest-note').type(testNote); + cy.getByTestSubj('protection-updates-version-to-deploy-picker').find('input').clear(); + + cy.getByTestSubj('protection-updates-version-to-deploy-picker') + .find('input') + .type(todayMinusTwoDays.format('MMMM DD, YYYY')); + cy.intercept('PUT', `/api/fleet/package_policies/${policy.id}`).as('policy'); cy.intercept('POST', `/api/endpoint/protection_updates_note/${policy.id}`).as('note'); - cy.getByTestSubj('protectionUpdatesSaveButton').click(); + clickProtectionUpdatesSaveButton(); cy.wait('@policy').then(({ request, response }) => { expect(request.body.inputs[0].config.policy.value.global_manifest_version).to.equal( - defaultDate.format('YYYY-MM-DD') + todayMinusTwoDays.format('YYYY-MM-DD') ); expect(response?.statusCode).to.equal(200); }); @@ -125,9 +143,23 @@ describe( }); cy.getByTestSubj('protectionUpdatesSuccessfulMessage'); - cy.getByTestSubj('protection-updates-deployed-version').contains(formattedDefaultDate); + cy.getByTestSubj('protection-updates-deployed-version').contains( + todayMinusTwoDays.format('MMMM DD, YYYY') + ); + cy.getByTestSubj('protection-updates-manifest-note').contains(testNote); + expectSavedButtonToBeDisabled(); + + // Reload page, make sure the changes are persisted + loadProtectionUpdatesUrl(policy.id); + // Date shouldn't match today, so the button should be enabled + expectSavedButtonToBeEnabled(); + cy.getByTestSubj('protection-updates-deployed-version').contains( + todayMinusTwoDays.format('MMMM DD, YYYY') + ); cy.getByTestSubj('protection-updates-manifest-note').contains(testNote); - cy.getByTestSubj('protectionUpdatesSaveButton').should('be.disabled'); + + clickProtectionUpdatesSaveButton(); + expectSavedButtonToBeDisabled(); }); }); @@ -155,14 +187,23 @@ describe( } }); - it('should update manifest version to latest when enabling automatic updates', () => { + it('should NOT display warning modal when user enters the page with previously selected custom date', () => { loadProtectionUpdatesUrl(policy.id); - cy.getByTestSubj('protectionUpdatesSaveButton').should('be.disabled'); + // The button is enabled because today is not the same as the date in the policy + expectSavedButtonToBeEnabled(); + + cy.getByTestSubj('policySettingsTab').click(); + cy.getByTestSubj('policyDetailsUnsavedChangesModal').should('not.exist'); + cy.url().should('include', 'settings'); + }); - cy.getByTestSubj('protection-updates-manifest-switch').click(); + it('should update manifest version to latest when enabling automatic updates', () => { + loadProtectionUpdatesUrl(policy.id); + expectSavedButtonToBeEnabled(); + clickAutomaticUpdatesToggle(); cy.intercept('PUT', `/api/fleet/package_policies/${policy.id}`).as('policy_latest'); - cy.getByTestSubj('protectionUpdatesSaveButton').click(); + clickProtectionUpdatesSaveButton(); cy.wait('@policy_latest').then(({ request, response }) => { expect(request.body.inputs[0].config.policy.value.global_manifest_version).to.equal( @@ -172,7 +213,7 @@ describe( }); cy.getByTestSubj('protectionUpdatesSuccessfulMessage'); cy.getByTestSubj('protection-updates-automatic-updates-enabled'); - cy.getByTestSubj('protectionUpdatesSaveButton').should('be.disabled'); + expectSavedButtonToBeDisabled(); }); }); @@ -203,7 +244,7 @@ describe( it('should update note on save', () => { loadProtectionUpdatesUrl(policy.id); - cy.getByTestSubj('protectionUpdatesSaveButton').should('be.disabled'); + expectSavedButtonToBeEnabled(); cy.getByTestSubj('protection-updates-manifest-note').contains(testNote); cy.getByTestSubj('protection-updates-manifest-note').clear(); @@ -212,14 +253,14 @@ describe( cy.intercept('POST', `/api/endpoint/protection_updates_note/${policy.id}`).as( 'note_updated' ); - cy.getByTestSubj('protectionUpdatesSaveButton').click(); + clickProtectionUpdatesSaveButton(); cy.wait('@note_updated').then(({ request, response }) => { expect(request.body.note).to.equal(updatedTestNote); expect(response?.statusCode).to.equal(200); }); cy.getByTestSubj('protectionUpdatesSuccessfulMessage'); cy.getByTestSubj('protection-updates-manifest-note').contains(updatedTestNote); - cy.getByTestSubj('protectionUpdatesSaveButton').should('be.disabled'); + expectSavedButtonToBeDisabled(); loadProtectionUpdatesUrl(policy.id); cy.getByTestSubj('protection-updates-manifest-note').contains(updatedTestNote); @@ -256,7 +297,7 @@ describe( it('should render the protection updates tab content', () => { loadProtectionUpdatesUrl(policy.id); - cy.getByTestSubj('protection-updates-manifest-switch').should('not.exist'); + getAutomaticUpdatesToggle().should('not.exist'); cy.getByTestSubj('protection-updates-state-view-mode'); cy.getByTestSubj('protection-updates-manifest-name-title'); @@ -271,7 +312,7 @@ describe( cy.getByTestSubj('protection-updates-manifest-name-note-title'); cy.getByTestSubj('protection-updates-manifest-note').should('not.exist'); cy.getByTestSubj('protection-updates-manifest-note-view-mode').contains(testNote); - cy.getByTestSubj('protectionUpdatesSaveButton').should('be.disabled'); + expectSavedButtonToBeDisabled(); }); }); @@ -303,7 +344,7 @@ describe( it('should render the protection updates tab content', () => { loadProtectionUpdatesUrl(policy.id); - cy.getByTestSubj('protection-updates-manifest-switch').should('not.exist'); + getAutomaticUpdatesToggle().should('not.exist'); cy.getByTestSubj('protection-updates-state-view-mode'); cy.getByTestSubj('protection-updates-manifest-name-title'); @@ -318,7 +359,7 @@ describe( cy.getByTestSubj('protection-updates-manifest-name-note-title').should('not.exist'); cy.getByTestSubj('protection-updates-manifest-note').should('not.exist'); cy.getByTestSubj('protection-updates-manifest-note-view-mode').should('not.exist'); - cy.getByTestSubj('protectionUpdatesSaveButton').should('be.disabled'); + expectSavedButtonToBeDisabled(); }); }); }); diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_settings_form/components/cards/malware_protections_card.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_settings_form/components/cards/malware_protections_card.tsx index 65be904ec649b..f1eda1ac0915e 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_settings_form/components/cards/malware_protections_card.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_settings_form/components/cards/malware_protections_card.tsx @@ -180,7 +180,7 @@ export const MalwareProtectionsCard = React.memo( mode={mode} data-test-subj={getTestId('onWriteScan')} labels={ON_WRITE_SCAN_LABELS} - checked={policy.windows.malware.on_write_scan ?? true} + checked={policy.windows.malware.on_write_scan} adjustSubfeatureOnProtectionSwitch={adjustOnWriteSettingsOnProtectionSwitch} /> diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/protection_updates/protection_updates_layout.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/protection_updates/protection_updates_layout.tsx index 5d244884c1068..7c9b637a8b8c8 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/protection_updates/protection_updates_layout.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/protection_updates/protection_updates_layout.tsx @@ -72,7 +72,6 @@ export const ProtectionUpdatesLayout = React.memo( const policy = _policy as PolicyData; const deployedVersion = policy.inputs[0].config.policy.value.global_manifest_version; - const [manifestVersion, setManifestVersion] = useState(deployedVersion); const today = moment.utc(); const defaultDate = today.clone().subtract(1, 'days'); @@ -93,27 +92,47 @@ export const ProtectionUpdatesLayout = React.memo( } }, [fetchedNote, getNoteInProgress]); - const automaticUpdatesEnabled = manifestVersion === 'latest'; const internalDateFormat = 'YYYY-MM-DD'; const displayDateFormat = 'MMMM DD, YYYY'; const formattedDate = moment.utc(deployedVersion, internalDateFormat).format(displayDateFormat); const cutoffDate = getControlledArtifactCutoffDate(); // Earliest selectable date + const [selectedManifestVersion, setSelectedManifestVersion] = useState( + deployedVersion === 'latest' ? 'latest' : selectedDate.format(internalDateFormat) + ); + const automaticUpdatesEnabled = selectedManifestVersion === 'latest'; + const viewModeSwitchLabel = automaticUpdatesEnabled ? AUTOMATIC_UPDATES_CHECKBOX_LABEL : AUTOMATIC_UPDATES_OFF_CHECKBOX_LABEL; const saveButtonEnabled = (fetchedNote ? note !== fetchedNote.note : note !== '') || - manifestVersion !== deployedVersion; + selectedManifestVersion !== deployedVersion; useEffect(() => { + // Prevent unsaved changes modal from showing when the user has not made any changes + if ( + selectedDate.isSame(defaultDate.toISOString(), 'day') && + deployedVersion !== 'latest' && + !automaticUpdatesEnabled && + !moment.utc(deployedVersion, internalDateFormat).isSame(selectedDate.toISOString(), 'days') + ) { + return; + } setUnsavedChanges(saveButtonEnabled); - }, [saveButtonEnabled, setUnsavedChanges]); + }, [ + automaticUpdatesEnabled, + defaultDate, + deployedVersion, + saveButtonEnabled, + selectedDate, + setUnsavedChanges, + ]); const onSave = useCallback(() => { const update = cloneDeep(policy); - update.inputs[0].config.policy.value.global_manifest_version = manifestVersion; + update.inputs[0].config.policy.value.global_manifest_version = selectedManifestVersion; sendPolicyUpdate({ policy: update }) .then(({ item: policyItem }) => { toasts.addSuccess({ @@ -173,7 +192,7 @@ export const ProtectionUpdatesLayout = React.memo( } }, [ policy, - manifestVersion, + selectedManifestVersion, sendPolicyUpdate, fetchedNote, note, @@ -187,13 +206,13 @@ export const ProtectionUpdatesLayout = React.memo( const { checked } = event.target; if (checked && !automaticUpdatesEnabled) { - setManifestVersion('latest'); + setSelectedManifestVersion('latest'); // Clear selected date on user enabling automatic updates if (selectedDate !== defaultDate) { setSelectedDate(defaultDate); } } else { - setManifestVersion(selectedDate.format(internalDateFormat)); + setSelectedManifestVersion(selectedDate.format(internalDateFormat)); } }, [automaticUpdatesEnabled, selectedDate, defaultDate] @@ -203,7 +222,7 @@ export const ProtectionUpdatesLayout = React.memo( (date: Moment | null) => { if (date?.isAfter(cutoffDate) && date?.isSameOrBefore(defaultDate)) { setSelectedDate(date || defaultDate); - setManifestVersion(date?.format(internalDateFormat) || 'latest'); + setSelectedManifestVersion(date?.format(internalDateFormat) || 'latest'); } }, [cutoffDate, defaultDate] diff --git a/x-pack/plugins/security_solution/public/overview/pages/data_quality.tsx b/x-pack/plugins/security_solution/public/overview/pages/data_quality.tsx index 5c74c0e334180..587cf9377c5f0 100644 --- a/x-pack/plugins/security_solution/public/overview/pages/data_quality.tsx +++ b/x-pack/plugins/security_solution/public/overview/pages/data_quality.tsx @@ -131,7 +131,7 @@ const renderOption = ( ); const DataQualityComponent: React.FC = () => { - const { hasAssistantPrivilege } = useAssistantAvailability(); + const { isAssistantEnabled } = useAssistantAvailability(); const httpFetch = KibanaServices.get().http.fetch; const { baseTheme, theme } = useThemes(); const toasts = useToasts(); @@ -284,7 +284,7 @@ const DataQualityComponent: React.FC = () => { reportDataQualityIndexChecked={reportDataQualityIndexChecked} httpFetch={httpFetch} ilmPhases={ilmPhases} - isAssistantEnabled={hasAssistantPrivilege} + isAssistantEnabled={isAssistantEnabled} isILMAvailable={isILMAvailable} lastChecked={lastChecked} openCreateCaseFlyout={openCreateCaseFlyout} diff --git a/x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/index.tsx b/x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/index.tsx index 20b6341db6d91..33faddd5bea48 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/index.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/index.tsx @@ -80,7 +80,7 @@ const EventDetailsPanelComponent: React.FC = ({ scopeId, isReadOnly, }) => { - const { hasAssistantPrivilege } = useAssistantAvailability(); + const { hasAssistantPrivilege, isAssistantEnabled } = useAssistantAvailability(); // TODO: changing feature flags requires a hard refresh to take effect, but this temporary workaround technically violates the rules of hooks: const useAssistant = hasAssistantPrivilege ? useAssistantOverlay : useAssistantNoop; const currentSpaceId = useSpaceId(); @@ -122,7 +122,8 @@ const EventDetailsPanelComponent: React.FC = ({ isAlert ? PROMPT_CONTEXTS[PROMPT_CONTEXT_ALERT_CATEGORY].suggestedUserPrompt : PROMPT_CONTEXTS[PROMPT_CONTEXT_EVENT_CATEGORY].suggestedUserPrompt, - isAlert ? ALERT_SUMMARY_VIEW_CONTEXT_TOOLTIP : EVENT_SUMMARY_VIEW_CONTEXT_TOOLTIP + isAlert ? ALERT_SUMMARY_VIEW_CONTEXT_TOOLTIP : EVENT_SUMMARY_VIEW_CONTEXT_TOOLTIP, + isAssistantEnabled ); const header = useMemo( 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 ae518420531fd..73cf96b5b6864 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 @@ -10,6 +10,7 @@ import type { KbnClient } from '@kbn/test'; import execa from 'execa'; import chalk from 'chalk'; import assert from 'assert'; +import pRetry from 'p-retry'; import type { AgentPolicy, CreateAgentPolicyResponse, Output } from '@kbn/fleet-plugin/common'; import { AGENT_POLICY_API_ROUTES, @@ -137,7 +138,12 @@ export const startFleetServer = async ({ const isServerless = await isServerlessKibanaFlavor(kbnClient); const policyId = policy || !isServerless ? await getOrCreateFleetServerAgentPolicyId(kbnClient, logger) : ''; - const serviceToken = isServerless ? '' : await generateFleetServiceToken(kbnClient, logger); + const serviceToken = isServerless + ? '' + : await pRetry(async () => generateFleetServiceToken(kbnClient, logger), { + retries: 2, + forever: false, + }); const startedFleetServer = await startFleetServerWithDocker({ kbnClient, logger, diff --git a/x-pack/plugins/security_solution/scripts/endpoint/common/vagrant/Vagrantfile b/x-pack/plugins/security_solution/scripts/endpoint/common/vagrant/Vagrantfile index 59c5bf12a1627..6f08c6265ecd7 100644 --- a/x-pack/plugins/security_solution/scripts/endpoint/common/vagrant/Vagrantfile +++ b/x-pack/plugins/security_solution/scripts/endpoint/common/vagrant/Vagrantfile @@ -11,6 +11,7 @@ Vagrant.configure("2") do |config| config.vm.hostname = hostname config.vm.box = 'ubuntu/jammy64' config.vm.box_check_update = false + config.vm.boot_timeout = 600 config.vm.provider :virtualbox do |vb| vb.memory = 4096 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 e99e382598039..08c0846d2ce8e 100644 --- a/x-pack/plugins/security_solution/scripts/run_cypress/parallel.ts +++ b/x-pack/plugins/security_solution/scripts/run_cypress/parallel.ts @@ -316,100 +316,107 @@ ${JSON.stringify( ci: process.env.CI, }; - const shutdownEs = await pRetry( - async () => - runElasticsearch({ - config, - log, - name: `ftr-${esPort}`, - esFrom: config.get('esTestCluster')?.from || 'snapshot', - onEarlyExit, - }), - { retries: 2, forever: false } - ); - - await runKibanaServer({ - procs, - config, - installDir: options?.installDir, - extraKbnOpts: - options?.installDir || options?.ci || !isOpen - ? [] - : ['--dev', '--no-dev-config', '--no-dev-credentials'], - onEarlyExit, - inspect: argv.inspect, - }); - // Setup fleet if Cypress config requires it let fleetServer: void | StartedFleetServer; - if (cypressConfigFile.env?.WITH_FLEET_SERVER) { - log.info(`Setting up fleet-server for this Cypress config`); - - const kbnClient = createKbnClient({ - url: baseUrl, - username: config.get('servers.kibana.username'), - password: config.get('servers.kibana.password'), - log, + let shutdownEs; + + try { + shutdownEs = await pRetry( + async () => + runElasticsearch({ + config, + log, + name: `ftr-${esPort}`, + esFrom: config.get('esTestCluster')?.from || 'snapshot', + onEarlyExit, + }), + { retries: 2, forever: false } + ); + + await runKibanaServer({ + procs, + config, + installDir: options?.installDir, + extraKbnOpts: + options?.installDir || options?.ci || !isOpen + ? [] + : ['--dev', '--no-dev-config', '--no-dev-credentials'], + onEarlyExit, + inspect: argv.inspect, }); - fleetServer = await startFleetServer({ - kbnClient, - logger: log, - port: - fleetServerPort ?? config.has('servers.fleetserver.port') - ? (config.get('servers.fleetserver.port') as number) - : undefined, - // `force` is needed to ensure that any currently running fleet server (perhaps left - // over from an interrupted run) is killed and a new one restarted - force: true, - }); - } + if (cypressConfigFile.env?.WITH_FLEET_SERVER) { + log.info(`Setting up fleet-server for this Cypress config`); - await providers.loadAll(); + const kbnClient = createKbnClient({ + url: baseUrl, + username: config.get('servers.kibana.username'), + password: config.get('servers.kibana.password'), + log, + }); - const functionalTestRunner = new FunctionalTestRunner( - log, - config, - EsVersion.getDefault() - ); + fleetServer = await pRetry( + async () => + startFleetServer({ + kbnClient, + logger: log, + port: + fleetServerPort ?? config.has('servers.fleetserver.port') + ? (config.get('servers.fleetserver.port') as number) + : undefined, + // `force` is needed to ensure that any currently running fleet server (perhaps left + // over from an interrupted run) is killed and a new one restarted + force: true, + }), + { retries: 2, forever: false } + ); + } - const ftrEnv = await pRetry(() => functionalTestRunner.run(abortCtrl.signal), { - retries: 1, - }); + await providers.loadAll(); - log.debug( - `Env. variables returned by [functionalTestRunner.run()]:\n`, - JSON.stringify(ftrEnv, null, 2) - ); + const functionalTestRunner = new FunctionalTestRunner( + log, + config, + EsVersion.getDefault() + ); - // Normalized the set of available env vars in cypress - const cyCustomEnv = { - ...ftrEnv, + const ftrEnv = await pRetry(() => functionalTestRunner.run(abortCtrl.signal), { + retries: 1, + }); - // NOTE: - // ELASTICSEARCH_URL needs to be created here with auth because SIEM cypress setup depends on it. At some - // points we should probably try to refactor that code to use `ELASTICSEARCH_URL_WITH_AUTH` instead - ELASTICSEARCH_URL: - ftrEnv.ELASTICSEARCH_URL ?? createUrlFromFtrConfig('elasticsearch', true), - ELASTICSEARCH_URL_WITH_AUTH: createUrlFromFtrConfig('elasticsearch', true), - ELASTICSEARCH_USERNAME: - ftrEnv.ELASTICSEARCH_USERNAME ?? config.get('servers.elasticsearch.username'), - ELASTICSEARCH_PASSWORD: - ftrEnv.ELASTICSEARCH_PASSWORD ?? config.get('servers.elasticsearch.password'), + log.debug( + `Env. variables returned by [functionalTestRunner.run()]:\n`, + JSON.stringify(ftrEnv, null, 2) + ); - FLEET_SERVER_URL: createUrlFromFtrConfig('fleetserver'), + // Normalized the set of available env vars in cypress + const cyCustomEnv = { + ...ftrEnv, - KIBANA_URL: baseUrl, - KIBANA_URL_WITH_AUTH: createUrlFromFtrConfig('kibana', true), - KIBANA_USERNAME: config.get('servers.kibana.username'), - KIBANA_PASSWORD: config.get('servers.kibana.password'), + // NOTE: + // ELASTICSEARCH_URL needs to be created here with auth because SIEM cypress setup depends on it. At some + // points we should probably try to refactor that code to use `ELASTICSEARCH_URL_WITH_AUTH` instead + ELASTICSEARCH_URL: + ftrEnv.ELASTICSEARCH_URL ?? createUrlFromFtrConfig('elasticsearch', true), + ELASTICSEARCH_URL_WITH_AUTH: createUrlFromFtrConfig('elasticsearch', true), + ELASTICSEARCH_USERNAME: + ftrEnv.ELASTICSEARCH_USERNAME ?? config.get('servers.elasticsearch.username'), + ELASTICSEARCH_PASSWORD: + ftrEnv.ELASTICSEARCH_PASSWORD ?? config.get('servers.elasticsearch.password'), - IS_SERVERLESS: config.get('serverless'), + FLEET_SERVER_URL: createUrlFromFtrConfig('fleetserver'), - ...argv.env, - }; + KIBANA_URL: baseUrl, + KIBANA_URL_WITH_AUTH: createUrlFromFtrConfig('kibana', true), + KIBANA_USERNAME: config.get('servers.kibana.username'), + KIBANA_PASSWORD: config.get('servers.kibana.password'), - log.info(` + IS_SERVERLESS: config.get('serverless'), + + ...argv.env, + }; + + log.info(` ---------------------------------------------- Cypress run ENV for file: ${filePath}: ---------------------------------------------- @@ -419,20 +426,19 @@ ${JSON.stringify(cyCustomEnv, null, 2)} ---------------------------------------------- `); - if (isOpen) { - await cypress.open({ - configFile: cypressConfigFilePath, - config: { - e2e: { - baseUrl, + if (isOpen) { + await cypress.open({ + configFile: cypressConfigFilePath, + config: { + e2e: { + baseUrl, + }, + env: cyCustomEnv, }, - env: cyCustomEnv, - }, - }); - } else { - try { + }); + } else { result = await cypress.run({ - browser: 'electron', + browser: 'chrome', spec: filePath, configFile: cypressConfigFilePath, reporter: argv.reporter as string, @@ -445,13 +451,14 @@ ${JSON.stringify(cyCustomEnv, null, 2)} numTestsKeptInMemory: 0, env: cyCustomEnv, }, + runnerUi: !process.env.CI, }); if (!(result as CypressCommandLine.CypressRunResult)?.totalFailed) { _.pull(failedSpecFilePaths, filePath); } - } catch (error) { - result = error; } + } catch (error) { + log.error(error); } if (fleetServer) { @@ -459,7 +466,7 @@ ${JSON.stringify(cyCustomEnv, null, 2)} } await procs.stop('kibana'); - await shutdownEs(); + await shutdownEs?.(); cleanupServerPorts({ esPort, kibanaPort, fleetServerPort }); return result; @@ -509,12 +516,11 @@ ${JSON.stringify(cyCustomEnv, null, 2)} const hasFailedInitialTests = hasFailedTests(initialResults); const hasFailedRetryTests = hasFailedTests(retryResults); - if (finalResults.length !== files.length) { - throw createFailError('Cypress crashed', { exitCode: -1 }); - } - // If the initialResults had failures and failedSpecFilePaths was not populated properly return errors - if (hasFailedRetryTests || (hasFailedInitialTests && !retryResults.length)) { + if ( + (hasFailedRetryTests && failedSpecFilePaths.length) || + (hasFailedInitialTests && !retryResults.length) + ) { throw createFailError('Not all tests passed'); } }, diff --git a/x-pack/plugins/security_solution/scripts/run_cypress/parallel_serverless.ts b/x-pack/plugins/security_solution/scripts/run_cypress/parallel_serverless.ts index 57a5e9705e7cf..e9d2f3ba52b24 100644 --- a/x-pack/plugins/security_solution/scripts/run_cypress/parallel_serverless.ts +++ b/x-pack/plugins/security_solution/scripts/run_cypress/parallel_serverless.ts @@ -541,7 +541,7 @@ ${JSON.stringify(cypressConfigFile, null, 2)} } else { try { result = await cypress.run({ - browser: 'electron', + browser: 'chrome', spec: filePath, configFile: cypressConfigFilePath, reporter: argv.reporter as string, @@ -554,6 +554,7 @@ ${JSON.stringify(cypressConfigFile, null, 2)} numTestsKeptInMemory: 0, env: cyCustomEnv, }, + runnerUi: !process.env.CI, }); if ((result as CypressCommandLine.CypressRunResult)?.totalFailed) { failedSpecFilePaths.push(filePath); diff --git a/x-pack/plugins/security_solution/server/endpoint/lib/artifacts/task.ts b/x-pack/plugins/security_solution/server/endpoint/lib/artifacts/task.ts index 8066e6094b568..d0c4d825d57d6 100644 --- a/x-pack/plugins/security_solution/server/endpoint/lib/artifacts/task.ts +++ b/x-pack/plugins/security_solution/server/endpoint/lib/artifacts/task.ts @@ -170,7 +170,6 @@ export class ManifestTask { this.logger.error( `unable to recover from error while attempting to retrieve last computed manifest` ); - return; } } diff --git a/x-pack/plugins/security_solution/server/endpoint/schemas/artifacts/saved_objects.ts b/x-pack/plugins/security_solution/server/endpoint/schemas/artifacts/saved_objects.ts index f0bc3a80d3406..4ca6d67031662 100644 --- a/x-pack/plugins/security_solution/server/endpoint/schemas/artifacts/saved_objects.ts +++ b/x-pack/plugins/security_solution/server/endpoint/schemas/artifacts/saved_objects.ts @@ -109,6 +109,7 @@ export const internalUnifiedManifestSchema = t.intersection([ t.type({ id: identifier, created: t.union([t.string, t.undefined]), + version: t.union([t.string, t.undefined]), }) ), ]); diff --git a/x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.mock.ts b/x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.mock.ts index a0cbc058ba6a8..31ac67b2368d6 100644 --- a/x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.mock.ts +++ b/x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.mock.ts @@ -72,6 +72,7 @@ export interface ManifestManagerMockOptions { packagePolicyService: jest.Mocked; savedObjectsClient: ReturnType; productFeaturesService: ProductFeaturesService; + experimentalFeatures?: string[]; } export const buildManifestManagerMockOptions = ( @@ -98,7 +99,8 @@ export const buildManifestManagerContextMock = ( ...fullOpts, artifactClient: createEndpointArtifactClientMock(), logger: loggingSystemMock.create().get() as jest.Mocked, - experimentalFeatures: parseExperimentalConfigValue([]).features, + experimentalFeatures: parseExperimentalConfigValue([...(opts.experimentalFeatures ?? [])]) + .features, packagerTaskPackagePolicyUpdateBatchSize: 10, esClient: elasticsearchServiceMock.createElasticsearchClient(), }; diff --git a/x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.test.ts b/x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.test.ts index 7b996c7737c89..d6e82322ffa9c 100644 --- a/x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.test.ts +++ b/x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.test.ts @@ -14,6 +14,7 @@ import type { InternalArtifactCompleteSchema, InternalArtifactSchema, InternalManifestSchema, + InternalUnifiedManifestSchema, } from '../../../schemas/artifacts'; import { createPackagePolicyWithConfigMock, @@ -32,6 +33,7 @@ import { mockFindExceptionListItemResponses, } from './manifest_manager.mock'; +import type { ManifestManagerContext } from './manifest_manager'; import { ManifestManager } from './manifest_manager'; import type { EndpointArtifactClientInterface } from '../artifact_client'; import { InvalidInternalManifestError } from '../errors'; @@ -107,6 +109,168 @@ describe('ManifestManager', () => { ARTIFACT_TRUSTED_APPS_WINDOWS = ARTIFACTS[4]; }); + describe('getLastComputedManifest from Unified Manifest SO', () => { + const mockGetAllUnifiedManifestsSOFromCache = jest.fn().mockImplementation(() => [ + { + policyId: '.global', + semanticVersion: '1.0.0', + artifactIds: [ + ARTIFACT_ID_EXCEPTIONS_MACOS, + ARTIFACT_ID_EXCEPTIONS_WINDOWS, + ARTIFACT_ID_EXCEPTIONS_LINUX, + ], + created: '20-01-2020 10:00:00.000Z', + id: '3', + }, + { + policyId: TEST_POLICY_ID_1, + semanticVersion: '1.0.0', + artifactIds: [ + ARTIFACT_ID_EXCEPTIONS_WINDOWS, + ARTIFACT_ID_TRUSTED_APPS_MACOS, + ARTIFACT_ID_TRUSTED_APPS_WINDOWS, + ], + created: '20-01-2020 10:00:00.000Z', + id: '1', + }, + { + policyId: TEST_POLICY_ID_2, + semanticVersion: '1.0.0', + artifactIds: [ARTIFACT_ID_TRUSTED_APPS_WINDOWS], + created: '20-01-2020 10:00:00.000Z', + id: '2', + }, + ]); + + test('Retrieves empty unified manifest successfully', async () => { + const savedObjectsClient = savedObjectsClientMock.create(); + const manifestManager = new ManifestManager( + buildManifestManagerContextMock({ + savedObjectsClient, + experimentalFeatures: ['unifiedManifestEnabled'], + }) + ); + + manifestManager.getAllUnifiedManifestsSO = jest.fn().mockImplementation(() => []); + + const manifest = await manifestManager.getLastComputedManifest(); + + expect(manifest?.getSchemaVersion()).toStrictEqual('v1'); + expect(manifest?.getSemanticVersion()).toStrictEqual('1.0.0'); + expect(manifest?.getSavedObjectVersion()).toStrictEqual('WzQ3NzAsMV0='); + expect(manifest?.getAllArtifacts()).toStrictEqual([]); + }); + + test('Retrieves empty unified manifest successfully but uses semanticVersion from existing legacy SO manifest', async () => { + const semanticVersion = '1.14.0'; + const savedObjectsClient = savedObjectsClientMock.create(); + const manifestManager = new ManifestManager( + buildManifestManagerContextMock({ + savedObjectsClient, + experimentalFeatures: ['unifiedManifestEnabled'], + }) + ); + + savedObjectsClient.get = jest.fn().mockImplementation(async (objectType: string) => { + if (objectType === ManifestConstants.SAVED_OBJECT_TYPE) { + return { + attributes: { + artifacts: [ + { artifactId: ARTIFACT_ID_EXCEPTIONS_MACOS, policyId: undefined }, + { artifactId: ARTIFACT_ID_EXCEPTIONS_WINDOWS, policyId: undefined }, + ], + semanticVersion, + }, + }; + } else { + return null; + } + }); + + manifestManager.getAllUnifiedManifestsSO = jest.fn().mockImplementation(() => []); + + const manifest = await manifestManager.getLastComputedManifest(); + + expect(manifest?.getSchemaVersion()).toStrictEqual('v1'); + expect(manifest?.getSemanticVersion()).toStrictEqual(semanticVersion); + expect(manifest?.getSavedObjectVersion()).toStrictEqual('WzQ3NzAsMV0='); + expect(manifest?.getAllArtifacts()).toStrictEqual([]); + }); + + test('Retrieves non empty manifest succesfully from Unified Saved Object', async () => { + const savedObjectsClient = savedObjectsClientMock.create(); + const manifestManagerContext = buildManifestManagerContextMock({ + savedObjectsClient, + experimentalFeatures: ['unifiedManifestEnabled'], + }); + const manifestManager = new ManifestManager(manifestManagerContext); + + ( + manifestManagerContext.artifactClient as jest.Mocked + ).fetchAll.mockReturnValue(createFetchAllArtifactsIterableMock([ARTIFACTS as Artifact[]])); + + manifestManager.getAllUnifiedManifestsSO = mockGetAllUnifiedManifestsSOFromCache; + + const manifest = await manifestManager.getLastComputedManifest(); + + expect(manifest?.getSchemaVersion()).toStrictEqual('v1'); + expect(manifest?.getSemanticVersion()).toStrictEqual('1.0.0'); + expect(manifest?.getSavedObjectVersion()).toStrictEqual('WzQ3NzAsMV0='); + expect(manifest?.getAllArtifacts()).toStrictEqual(ARTIFACTS.slice(0, 5)); + expect(manifest?.isDefaultArtifact(ARTIFACT_EXCEPTIONS_MACOS)).toBe(true); + expect(manifest?.getArtifactTargetPolicies(ARTIFACT_EXCEPTIONS_MACOS)).toStrictEqual( + new Set() + ); + expect(manifest?.isDefaultArtifact(ARTIFACT_EXCEPTIONS_WINDOWS)).toBe(true); + expect(manifest?.getArtifactTargetPolicies(ARTIFACT_EXCEPTIONS_WINDOWS)).toStrictEqual( + new Set([TEST_POLICY_ID_1]) + ); + expect(manifest?.isDefaultArtifact(ARTIFACT_TRUSTED_APPS_MACOS)).toBe(false); + expect(manifest?.getArtifactTargetPolicies(ARTIFACT_TRUSTED_APPS_MACOS)).toStrictEqual( + new Set([TEST_POLICY_ID_1]) + ); + expect(manifest?.isDefaultArtifact(ARTIFACT_TRUSTED_APPS_WINDOWS)).toBe(false); + expect(manifest?.getArtifactTargetPolicies(ARTIFACT_TRUSTED_APPS_WINDOWS)).toStrictEqual( + new Set([TEST_POLICY_ID_1, TEST_POLICY_ID_2]) + ); + }); + + test("Retrieve non empty unified manifest and skips over artifacts that can't be found", async () => { + const savedObjectsClient = savedObjectsClientMock.create(); + const manifestManagerContext = buildManifestManagerContextMock({ + savedObjectsClient, + experimentalFeatures: ['unifiedManifestEnabled'], + }); + const manifestManager = new ManifestManager(manifestManagerContext); + + manifestManager.getAllUnifiedManifestsSO = mockGetAllUnifiedManifestsSOFromCache; + + ( + manifestManagerContext.artifactClient as jest.Mocked + ).fetchAll.mockReturnValue( + createFetchAllArtifactsIterableMock([ + // report the MACOS Exceptions artifact as not found + [ + ARTIFACT_TRUSTED_APPS_MACOS, + ARTIFACT_EXCEPTIONS_WINDOWS, + ARTIFACT_TRUSTED_APPS_WINDOWS, + ARTIFACTS_BY_ID[ARTIFACT_ID_EXCEPTIONS_LINUX], + ] as Artifact[], + ]) + ); + + const manifest = await manifestManager.getLastComputedManifest(); + + expect(manifest?.getAllArtifacts()).toStrictEqual(ARTIFACTS.slice(1, 5)); + + expect(manifestManagerContext.logger.warn).toHaveBeenCalledWith( + "Missing artifacts detected! Internal artifact manifest (SavedObject version [WzQ3NzAsMV0=]) references [1] artifact IDs that don't exist.\n" + + "First 10 below (run with logging set to 'debug' to see all):\n" + + 'endpoint-exceptionlist-macos-v1-96b76a1a911662053a1562ac14c4ff1e87c2ff550d6fe52e1e0b3790526597d3' + ); + }); + }); + describe('getLastComputedManifest', () => { test('Returns null when saved object not found', async () => { const savedObjectsClient = savedObjectsClientMock.create(); @@ -282,7 +446,197 @@ describe('ManifestManager', () => { }); }); - describe('buildNewManifest', () => { + describe('commit unified manifest', () => { + test('Correctly updates, creates and deletes unified manifest so', async () => { + const context = buildManifestManagerContextMock({ + experimentalFeatures: ['unifiedManifestEnabled'], + }); + const manifestManager = new ManifestManager(context); + const manifest = ManifestManager.createDefaultManifest(); + + manifest.addEntry(ARTIFACT_EXCEPTIONS_MACOS); + manifest.addEntry(ARTIFACT_EXCEPTIONS_MACOS, TEST_POLICY_ID_1); + manifest.addEntry(ARTIFACT_TRUSTED_APPS_WINDOWS, TEST_POLICY_ID_1); + manifest.addEntry(ARTIFACT_EXCEPTIONS_WINDOWS, TEST_POLICY_ID_2); + manifest.addEntry(ARTIFACT_TRUSTED_APPS_MACOS, TEST_POLICY_ID_1); + manifest.addEntry(ARTIFACT_TRUSTED_APPS_MACOS, TEST_POLICY_ID_2); + + manifestManager.getAllUnifiedManifestsSO = jest.fn().mockImplementation(() => [ + { + policyId: '.global', + semanticVersion: '1.0.0', + artifactIds: [ARTIFACT_ID_EXCEPTIONS_MACOS], + created: '20-01-2020 10:00:00.000Z', + id: '2', + }, + { + policyId: TEST_POLICY_ID_1, + semanticVersion: '1.0.0', + artifactIds: [ARTIFACT_ID_EXCEPTIONS_MACOS, ARTIFACT_ID_TRUSTED_APPS_MACOS], + created: '20-01-2020 10:00:00.000Z', + id: '3', + }, + { + policyId: 'non-existent-policy', + semanticVersion: '1.0.0', + artifactIds: [ARTIFACT_ID_EXCEPTIONS_WINDOWS], + created: '20-01-2020 10:00:00.000Z', + id: '4', + }, + ]); + + context.savedObjectsClient.bulkCreate = jest.fn(); + context.savedObjectsClient.bulkUpdate = jest.fn(); + context.savedObjectsClient.bulkDelete = jest.fn(); + manifestManager.bumpGlobalUnifiedManifestVersion = jest.fn(); + + await expect(manifestManager.commit(manifest)).resolves.toBeUndefined(); + expect(context.savedObjectsClient.bulkCreate).toHaveBeenCalledTimes(1); + // TEST_POLICY_ID_1 and .global exists, shouldn't be created + expect(context.savedObjectsClient.bulkCreate).toHaveBeenCalledWith( + [ + { + attributes: { + artifactIds: [ARTIFACT_ID_EXCEPTIONS_WINDOWS, ARTIFACT_ID_TRUSTED_APPS_MACOS], + id: undefined, + policyId: TEST_POLICY_ID_2, + semanticVersion: '1.0.0', + }, + type: ManifestConstants.UNIFIED_SAVED_OBJECT_TYPE, + }, + ], + { initialNamespaces: ['*'] } + ); + + expect(context.savedObjectsClient.bulkUpdate).toHaveBeenCalledTimes(1); + // TEST_POLICY_ID_1 is updated, global is not due to no changes + expect(context.savedObjectsClient.bulkUpdate).toHaveBeenCalledWith([ + { + attributes: { + artifactIds: [ + ARTIFACT_ID_EXCEPTIONS_MACOS, + ARTIFACT_ID_TRUSTED_APPS_WINDOWS, + ARTIFACT_ID_TRUSTED_APPS_MACOS, + ], + policyId: TEST_POLICY_ID_1, + semanticVersion: '1.0.1', + }, + id: '3', + type: ManifestConstants.UNIFIED_SAVED_OBJECT_TYPE, + }, + ]); + + // non-existent-policy should be deleted for not being in the manifest + expect(context.savedObjectsClient.bulkDelete).toHaveBeenCalledTimes(1); + expect(context.savedObjectsClient.bulkDelete).toHaveBeenCalledWith([ + { id: '4', type: ManifestConstants.UNIFIED_SAVED_OBJECT_TYPE }, + ]); + // Global manifest wasn't updated, manual bump is required + expect(manifestManager.bumpGlobalUnifiedManifestVersion).toHaveBeenCalledTimes(1); + }); + }); + + describe('commit', () => { + test('Creates new saved object if no saved object version', async () => { + const context = buildManifestManagerContextMock({}); + const manifestManager = new ManifestManager(context); + const manifest = ManifestManager.createDefaultManifest(); + + manifest.addEntry(ARTIFACT_EXCEPTIONS_MACOS); + manifest.addEntry(ARTIFACT_EXCEPTIONS_MACOS, TEST_POLICY_ID_1); + manifest.addEntry(ARTIFACT_EXCEPTIONS_WINDOWS, TEST_POLICY_ID_2); + manifest.addEntry(ARTIFACT_TRUSTED_APPS_MACOS, TEST_POLICY_ID_1); + manifest.addEntry(ARTIFACT_TRUSTED_APPS_MACOS, TEST_POLICY_ID_2); + + context.savedObjectsClient.create = jest + .fn() + .mockImplementation((_type: string, object: InternalManifestSchema) => object); + + await expect(manifestManager.commit(manifest)).resolves.toBeUndefined(); + + expect(context.savedObjectsClient.create).toHaveBeenCalledTimes(1); + expect(context.savedObjectsClient.create).toHaveBeenNthCalledWith( + 1, + ManifestConstants.SAVED_OBJECT_TYPE, + { + artifacts: [ + { artifactId: ARTIFACT_ID_EXCEPTIONS_MACOS, policyId: undefined }, + { artifactId: ARTIFACT_ID_EXCEPTIONS_MACOS, policyId: TEST_POLICY_ID_1 }, + { artifactId: ARTIFACT_ID_TRUSTED_APPS_MACOS, policyId: TEST_POLICY_ID_1 }, + { artifactId: ARTIFACT_ID_EXCEPTIONS_WINDOWS, policyId: TEST_POLICY_ID_2 }, + { artifactId: ARTIFACT_ID_TRUSTED_APPS_MACOS, policyId: TEST_POLICY_ID_2 }, + ], + schemaVersion: 'v1', + semanticVersion: '1.0.0', + created: expect.anything(), + }, + { id: 'endpoint-manifest-v1' } + ); + }); + + test('Updates existing saved object if has saved object version', async () => { + const context = buildManifestManagerContextMock({}); + const manifestManager = new ManifestManager(context); + const manifest = new Manifest({ soVersion: '1.0.0' }); + + manifest.addEntry(ARTIFACT_EXCEPTIONS_MACOS); + manifest.addEntry(ARTIFACT_EXCEPTIONS_MACOS, TEST_POLICY_ID_1); + manifest.addEntry(ARTIFACT_EXCEPTIONS_WINDOWS, TEST_POLICY_ID_2); + manifest.addEntry(ARTIFACT_TRUSTED_APPS_MACOS, TEST_POLICY_ID_1); + manifest.addEntry(ARTIFACT_TRUSTED_APPS_MACOS, TEST_POLICY_ID_2); + + context.savedObjectsClient.update = jest + .fn() + .mockImplementation((_type: string, _id: string, object: InternalManifestSchema) => object); + + await expect(manifestManager.commit(manifest)).resolves.toBeUndefined(); + + expect(context.savedObjectsClient.update).toHaveBeenCalledTimes(1); + expect(context.savedObjectsClient.update).toHaveBeenNthCalledWith( + 1, + ManifestConstants.SAVED_OBJECT_TYPE, + 'endpoint-manifest-v1', + { + artifacts: [ + { artifactId: ARTIFACT_ID_EXCEPTIONS_MACOS, policyId: undefined }, + { artifactId: ARTIFACT_ID_EXCEPTIONS_MACOS, policyId: TEST_POLICY_ID_1 }, + { artifactId: ARTIFACT_ID_TRUSTED_APPS_MACOS, policyId: TEST_POLICY_ID_1 }, + { artifactId: ARTIFACT_ID_EXCEPTIONS_WINDOWS, policyId: TEST_POLICY_ID_2 }, + { artifactId: ARTIFACT_ID_TRUSTED_APPS_MACOS, policyId: TEST_POLICY_ID_2 }, + ], + schemaVersion: 'v1', + semanticVersion: '1.0.0', + }, + { version: '1.0.0' } + ); + }); + + test('Throws error when saved objects client fails', async () => { + const context = buildManifestManagerContextMock({}); + const manifestManager = new ManifestManager(context); + const manifest = new Manifest({ soVersion: '1.0.0' }); + const error = new Error(); + + context.savedObjectsClient.update = jest.fn().mockRejectedValue(error); + + await expect(manifestManager.commit(manifest)).rejects.toBe(error); + + expect(context.savedObjectsClient.update).toHaveBeenCalledTimes(1); + expect(context.savedObjectsClient.update).toHaveBeenNthCalledWith( + 1, + ManifestConstants.SAVED_OBJECT_TYPE, + 'endpoint-manifest-v1', + { + artifacts: [], + schemaVersion: 'v1', + semanticVersion: '1.0.0', + }, + { version: '1.0.0' } + ); + }); + }); + + describe.each([true, false])('buildNewManifest', (unifiedManifestSO) => { const SUPPORTED_ARTIFACT_NAMES = [ ARTIFACT_NAME_EXCEPTIONS_MACOS, ARTIFACT_NAME_EXCEPTIONS_WINDOWS, @@ -305,8 +659,10 @@ describe('ManifestManager', () => { ...new Set(artifacts.map((artifact) => artifact.identifier)).values(), ]; - test('Fails when exception list client fails', async () => { - const context = buildManifestManagerContextMock({}); + test(`Fails when exception list client fails when unifiedManifestEnabled feature flag is set to: ${unifiedManifestSO}`, async () => { + const context = buildManifestManagerContextMock({ + ...(unifiedManifestSO ? { experimentalFeatures: ['unifiedManifestEnabled'] } : {}), + }); const manifestManager = new ManifestManager(context); context.exceptionListClient.findExceptionListItem = jest.fn().mockRejectedValue(new Error()); @@ -314,8 +670,10 @@ describe('ManifestManager', () => { await expect(manifestManager.buildNewManifest()).rejects.toThrow(); }); - test('Builds fully new manifest if no baseline parameter passed and no exception list items', async () => { - const context = buildManifestManagerContextMock({}); + test(`Builds fully new manifest if no baseline parameter passed and no exception list items when unifiedManifestEnabled feature flag is set to: ${unifiedManifestSO}`, async () => { + const context = buildManifestManagerContextMock({ + ...(unifiedManifestSO ? { experimentalFeatures: ['unifiedManifestEnabled'] } : {}), + }); const manifestManager = new ManifestManager(context); context.exceptionListClient.findExceptionListItem = mockFindExceptionListItemResponses({}); @@ -323,11 +681,6 @@ describe('ManifestManager', () => { TEST_POLICY_ID_1, ]); - context.savedObjectsClient.create = jest - .fn() - .mockImplementation((_type: string, object: InternalManifestSchema) => ({ - attributes: object, - })); const manifest = await manifestManager.buildNewManifest(); expect(manifest?.getSchemaVersion()).toStrictEqual('v1'); @@ -348,7 +701,7 @@ describe('ManifestManager', () => { } }); - test('Builds fully new manifest if no baseline parameter passed and present exception list items', async () => { + test(`Builds fully new manifest if no baseline parameter passed and present exception list items when unifiedManifestEnabled feature flag is set to: ${unifiedManifestSO}`, async () => { const exceptionListItem = getExceptionListItemSchemaMock({ os_types: ['macos'] }); const trustedAppListItem = getExceptionListItemSchemaMock({ os_types: ['linux'], @@ -366,7 +719,9 @@ describe('ManifestManager', () => { os_types: ['macos'], tags: ['policy:all'], }); - const context = buildManifestManagerContextMock({}); + const context = buildManifestManagerContextMock({ + ...(unifiedManifestSO ? { experimentalFeatures: ['unifiedManifestEnabled'] } : {}), + }); const manifestManager = new ManifestManager(context); context.exceptionListClient.findExceptionListItem = mockFindExceptionListItemResponses({ @@ -378,11 +733,7 @@ describe('ManifestManager', () => { }, [ENDPOINT_ARTIFACT_LISTS.blocklists.id]: { linux: [blocklistsListItem] }, }); - context.savedObjectsClient.create = jest - .fn() - .mockImplementation((_type: string, object: InternalManifestSchema) => ({ - attributes: object, - })); + context.packagePolicyService.fetchAllItemIds = getMockPolicyFetchAllItemIds([ TEST_POLICY_ID_1, ]); @@ -432,7 +783,7 @@ describe('ManifestManager', () => { } }); - test('Reuses artifacts when baseline parameter passed and present exception list items', async () => { + test(`Reuses artifacts when baseline parameter passed and present exception list items when unifiedManifestEnabled feature flag is set to: ${unifiedManifestSO}`, async () => { const exceptionListItem = getExceptionListItemSchemaMock({ os_types: ['macos'] }); const trustedAppListItem = getExceptionListItemSchemaMock({ os_types: ['linux'], @@ -450,7 +801,9 @@ describe('ManifestManager', () => { os_types: ['macos'], tags: ['policy:all'], }); - const context = buildManifestManagerContextMock({}); + const context = buildManifestManagerContextMock({ + ...(unifiedManifestSO ? { experimentalFeatures: ['unifiedManifestEnabled'] } : {}), + }); const manifestManager = new ManifestManager(context); context.exceptionListClient.findExceptionListItem = mockFindExceptionListItemResponses({ @@ -459,11 +812,7 @@ describe('ManifestManager', () => { context.packagePolicyService.fetchAllItemIds = getMockPolicyFetchAllItemIds([ TEST_POLICY_ID_1, ]); - context.savedObjectsClient.create = jest - .fn() - .mockImplementation((_type: string, object: InternalManifestSchema) => ({ - attributes: object, - })); + const oldManifest = await manifestManager.buildNewManifest(); context.exceptionListClient.findExceptionListItem = mockFindExceptionListItemResponses({ @@ -519,7 +868,7 @@ describe('ManifestManager', () => { } }); - test('Builds fully new manifest with single entries when they are duplicated', async () => { + test(`Builds fully new manifest with single entries when they are duplicated when unifiedManifestEnabled feature flag is set to: ${unifiedManifestSO}`, async () => { const exceptionListItem = getExceptionListItemSchemaMock({ os_types: ['macos'] }); const trustedAppListItem = getExceptionListItemSchemaMock({ os_types: ['linux'], @@ -537,7 +886,9 @@ describe('ManifestManager', () => { os_types: ['macos'], tags: ['policy:all'], }); - const context = buildManifestManagerContextMock({}); + const context = buildManifestManagerContextMock({ + ...(unifiedManifestSO ? { experimentalFeatures: ['unifiedManifestEnabled'] } : {}), + }); const manifestManager = new ManifestManager(context); const duplicatedEventFilterInDifferentPolicy = { @@ -569,11 +920,7 @@ describe('ManifestManager', () => { macos: [blocklistsListItem, blocklistsListItem], }, }); - context.savedObjectsClient.create = jest - .fn() - .mockImplementation((_type: string, object: InternalManifestSchema) => ({ - attributes: object, - })); + context.packagePolicyService.fetchAllItemIds = getMockPolicyFetchAllItemIds([ TEST_POLICY_ID_1, TEST_POLICY_ID_2, @@ -655,7 +1002,7 @@ describe('ManifestManager', () => { } }); - test('Builds manifest with policy specific exception list items for trusted apps', async () => { + test(`Builds manifest with policy specific exception list items for trusted apps when unifiedManifestEnabled feature flag is set to: ${unifiedManifestSO}`, async () => { const exceptionListItem = getExceptionListItemSchemaMock({ os_types: ['macos'] }); const trustedAppListItem = getExceptionListItemSchemaMock({ os_types: ['linux'], @@ -668,7 +1015,9 @@ describe('ManifestManager', () => { ], tags: [`policy:${TEST_POLICY_ID_2}`], }); - const context = buildManifestManagerContextMock({}); + const context = buildManifestManagerContextMock({ + ...(unifiedManifestSO ? { experimentalFeatures: ['unifiedManifestEnabled'] } : {}), + }); const manifestManager = new ManifestManager(context); context.exceptionListClient.findExceptionListItem = mockFindExceptionListItemResponses({ @@ -682,12 +1031,6 @@ describe('ManifestManager', () => { TEST_POLICY_ID_2, ]); - context.savedObjectsClient.create = jest - .fn() - .mockImplementation((_type: string, object: InternalManifestSchema) => ({ - attributes: object, - })); - const manifest = await manifestManager.buildNewManifest(); expect(manifest?.getSchemaVersion()).toStrictEqual('v1'); @@ -733,7 +1076,7 @@ describe('ManifestManager', () => { }); }); - describe('buildNewManifest when using app features', () => { + describe.each([true, false])('buildNewManifest when using app features', (unifiedManifestSO) => { const SUPPORTED_ARTIFACT_NAMES = [ ARTIFACT_NAME_EXCEPTIONS_MACOS, ARTIFACT_NAME_EXCEPTIONS_WINDOWS, @@ -756,7 +1099,7 @@ describe('ManifestManager', () => { ...new Set(artifacts.map((artifact) => artifact.identifier)).values(), ]; - test('when it has endpoint artifact management app feature it should not generate host isolation exceptions', async () => { + test(`when it has endpoint artifact management app feature it should not generate host isolation exceptions when unifiedManifestEnabled feature flag is set to: ${unifiedManifestSO}`, async () => { const exceptionListItem = getExceptionListItemSchemaMock({ os_types: ['macos'] }); const trustedAppListItem = getExceptionListItemSchemaMock({ os_types: ['linux'], @@ -774,9 +1117,10 @@ describe('ManifestManager', () => { os_types: ['macos'], tags: ['policy:all'], }); - const context = buildManifestManagerContextMock({}, [ - ProductFeatureSecurityKey.endpointArtifactManagement, - ]); + const context = buildManifestManagerContextMock( + { ...(unifiedManifestSO ? { experimentalFeatures: ['unifiedManifestEnabled'] } : {}) }, + [ProductFeatureSecurityKey.endpointArtifactManagement] + ); const manifestManager = new ManifestManager(context); context.exceptionListClient.findExceptionListItem = mockFindExceptionListItemResponses({ @@ -788,11 +1132,7 @@ describe('ManifestManager', () => { }, [ENDPOINT_ARTIFACT_LISTS.blocklists.id]: { linux: [blocklistsListItem] }, }); - context.savedObjectsClient.create = jest - .fn() - .mockImplementation((_type: string, object: InternalManifestSchema) => ({ - attributes: object, - })); + context.packagePolicyService.fetchAllItemIds = getMockPolicyFetchAllItemIds([ TEST_POLICY_ID_1, ]); @@ -840,7 +1180,7 @@ describe('ManifestManager', () => { } }); - test('when it has endpoint artifact management and response actions app features it should generate all exceptions', async () => { + test(`when it has endpoint artifact management and response actions app features it should generate all exceptions when unifiedManifestEnabled feature flag is set to: ${unifiedManifestSO}`, async () => { const exceptionListItem = getExceptionListItemSchemaMock({ os_types: ['macos'] }); const trustedAppListItem = getExceptionListItemSchemaMock({ os_types: ['linux'], @@ -858,10 +1198,13 @@ describe('ManifestManager', () => { os_types: ['macos'], tags: ['policy:all'], }); - const context = buildManifestManagerContextMock({}, [ - ProductFeatureSecurityKey.endpointArtifactManagement, - ProductFeatureSecurityKey.endpointResponseActions, - ]); + const context = buildManifestManagerContextMock( + { ...(unifiedManifestSO ? { experimentalFeatures: ['unifiedManifestEnabled'] } : {}) }, + [ + ProductFeatureSecurityKey.endpointArtifactManagement, + ProductFeatureSecurityKey.endpointResponseActions, + ] + ); const manifestManager = new ManifestManager(context); context.exceptionListClient.findExceptionListItem = mockFindExceptionListItemResponses({ @@ -873,11 +1216,7 @@ describe('ManifestManager', () => { }, [ENDPOINT_ARTIFACT_LISTS.blocklists.id]: { linux: [blocklistsListItem] }, }); - context.savedObjectsClient.create = jest - .fn() - .mockImplementation((_type: string, object: InternalManifestSchema) => ({ - attributes: object, - })); + context.packagePolicyService.fetchAllItemIds = getMockPolicyFetchAllItemIds([ TEST_POLICY_ID_1, ]); @@ -927,7 +1266,7 @@ describe('ManifestManager', () => { } }); - test('when does not have right app features, should not generate any exception', async () => { + test(`when does not have right app features, should not generate any exception when unifiedManifestEnabled feature flag is set to: ${unifiedManifestSO}`, async () => { const exceptionListItem = getExceptionListItemSchemaMock({ os_types: ['macos'] }); const trustedAppListItem = getExceptionListItemSchemaMock({ os_types: ['linux'], @@ -945,7 +1284,10 @@ describe('ManifestManager', () => { os_types: ['macos'], tags: ['policy:all'], }); - const context = buildManifestManagerContextMock({}, []); + const context = buildManifestManagerContextMock( + { ...(unifiedManifestSO ? { experimentalFeatures: ['unifiedManifestEnabled'] } : {}) }, + [] + ); const manifestManager = new ManifestManager(context); context.exceptionListClient.findExceptionListItem = mockFindExceptionListItemResponses({ @@ -957,123 +1299,7 @@ describe('ManifestManager', () => { }, [ENDPOINT_ARTIFACT_LISTS.blocklists.id]: { linux: [blocklistsListItem] }, }); - context.savedObjectsClient.create = jest - .fn() - .mockImplementation((_type: string, object: InternalManifestSchema) => ({ - attributes: object, - })); - context.packagePolicyService.fetchAllItemIds = getMockPolicyFetchAllItemIds([ - TEST_POLICY_ID_1, - ]); - - const manifest = await manifestManager.buildNewManifest(); - - expect(manifest?.getSchemaVersion()).toStrictEqual('v1'); - expect(manifest?.getSemanticVersion()).toStrictEqual('1.0.0'); - expect(manifest?.getSavedObjectVersion()).toBeUndefined(); - - const artifacts = manifest.getAllArtifacts(); - - expect(artifacts.length).toBe(15); - expect(getArtifactIds(artifacts)).toStrictEqual(SUPPORTED_ARTIFACT_NAMES); - - expect(getArtifactObject(artifacts[0])).toStrictEqual({ entries: [] }); - expect(getArtifactObject(artifacts[1])).toStrictEqual({ entries: [] }); - expect(getArtifactObject(artifacts[2])).toStrictEqual({ entries: [] }); - expect(getArtifactObject(artifacts[3])).toStrictEqual({ entries: [] }); - expect(getArtifactObject(artifacts[4])).toStrictEqual({ entries: [] }); - expect(getArtifactObject(artifacts[5])).toStrictEqual({ entries: [] }); - expect(getArtifactObject(artifacts[6])).toStrictEqual({ entries: [] }); - expect(getArtifactObject(artifacts[7])).toStrictEqual({ entries: [] }); - expect(getArtifactObject(artifacts[8])).toStrictEqual({ entries: [] }); - expect(getArtifactObject(artifacts[9])).toStrictEqual({ entries: [] }); - expect(getArtifactObject(artifacts[10])).toStrictEqual({ entries: [] }); - expect(getArtifactObject(artifacts[11])).toStrictEqual({ entries: [] }); - expect(getArtifactObject(artifacts[12])).toStrictEqual({ entries: [] }); - expect(getArtifactObject(artifacts[13])).toStrictEqual({ entries: [] }); - expect(getArtifactObject(artifacts[14])).toStrictEqual({ entries: [] }); - - for (const artifact of artifacts) { - expect(manifest.isDefaultArtifact(artifact)).toBe(true); - expect(manifest.getArtifactTargetPolicies(artifact)).toStrictEqual( - new Set([TEST_POLICY_ID_1]) - ); - } - }); - }); - - describe('buildNewManifest when Endpoint Exceptions contain `matches`', () => { - test('when contains only `wildcard`, `event.module=endpoint` is added', async () => { - const exceptionListItem = getExceptionListItemSchemaMock({ - os_types: ['macos'], - entries: [ - { type: 'wildcard', operator: 'included', field: 'path', value: '*match_me*' }, - { type: 'wildcard', operator: 'excluded', field: 'not_path', value: '*dont_match_me*' }, - ], - }); - const expectedExceptionListItem = getExceptionListItemSchemaMock({ - os_types: ['macos'], - entries: [ - ...exceptionListItem.entries, - { type: 'match', operator: 'included', field: 'event.module', value: 'endpoint' }, - ], - }); - - const context = buildManifestManagerContextMock({}); - const manifestManager = new ManifestManager(context); - - context.exceptionListClient.findExceptionListItem = mockFindExceptionListItemResponses({ - [ENDPOINT_LIST_ID]: { macos: [exceptionListItem] }, - }); - context.savedObjectsClient.create = jest - .fn() - .mockImplementation((_type: string, object: InternalManifestSchema) => ({ - attributes: object, - })); - context.packagePolicyService.fetchAllItemIds = getMockPolicyFetchAllItemIds([ - TEST_POLICY_ID_1, - ]); - - const manifest = await manifestManager.buildNewManifest(); - - expect(manifest?.getSchemaVersion()).toStrictEqual('v1'); - expect(manifest?.getSemanticVersion()).toStrictEqual('1.0.0'); - expect(manifest?.getSavedObjectVersion()).toBeUndefined(); - - const artifacts = manifest.getAllArtifacts(); - - expect(artifacts.length).toBe(15); - - expect(getArtifactObject(artifacts[0])).toStrictEqual({ - entries: translateToEndpointExceptions([expectedExceptionListItem], 'v1'), - }); - }); - - test('when contains anything next to `wildcard`, nothing is added', async () => { - const exceptionListItem = getExceptionListItemSchemaMock({ - os_types: ['macos'], - entries: [ - { type: 'wildcard', operator: 'included', field: 'path', value: '*match_me*' }, - { type: 'wildcard', operator: 'excluded', field: 'path', value: '*dont_match_me*' }, - { type: 'match', operator: 'included', field: 'path', value: 'something' }, - ], - }); - const expectedExceptionListItem = getExceptionListItemSchemaMock({ - os_types: ['macos'], - entries: [...exceptionListItem.entries], - }); - const context = buildManifestManagerContextMock({}); - const manifestManager = new ManifestManager(context); - - context.exceptionListClient.findExceptionListItem = mockFindExceptionListItemResponses({ - [ENDPOINT_LIST_ID]: { macos: [exceptionListItem] }, - }); - context.savedObjectsClient.create = jest - .fn() - .mockImplementation((_type: string, object: InternalManifestSchema) => ({ - attributes: object, - })); context.packagePolicyService.fetchAllItemIds = getMockPolicyFetchAllItemIds([ TEST_POLICY_ID_1, ]); @@ -1087,16 +1313,129 @@ describe('ManifestManager', () => { const artifacts = manifest.getAllArtifacts(); expect(artifacts.length).toBe(15); + expect(getArtifactIds(artifacts)).toStrictEqual(SUPPORTED_ARTIFACT_NAMES); - expect(getArtifactObject(artifacts[0])).toStrictEqual({ - entries: translateToEndpointExceptions([expectedExceptionListItem], 'v1'), - }); + expect(getArtifactObject(artifacts[0])).toStrictEqual({ entries: [] }); + expect(getArtifactObject(artifacts[1])).toStrictEqual({ entries: [] }); + expect(getArtifactObject(artifacts[2])).toStrictEqual({ entries: [] }); + expect(getArtifactObject(artifacts[3])).toStrictEqual({ entries: [] }); + expect(getArtifactObject(artifacts[4])).toStrictEqual({ entries: [] }); + expect(getArtifactObject(artifacts[5])).toStrictEqual({ entries: [] }); + expect(getArtifactObject(artifacts[6])).toStrictEqual({ entries: [] }); + expect(getArtifactObject(artifacts[7])).toStrictEqual({ entries: [] }); + expect(getArtifactObject(artifacts[8])).toStrictEqual({ entries: [] }); + expect(getArtifactObject(artifacts[9])).toStrictEqual({ entries: [] }); + expect(getArtifactObject(artifacts[10])).toStrictEqual({ entries: [] }); + expect(getArtifactObject(artifacts[11])).toStrictEqual({ entries: [] }); + expect(getArtifactObject(artifacts[12])).toStrictEqual({ entries: [] }); + expect(getArtifactObject(artifacts[13])).toStrictEqual({ entries: [] }); + expect(getArtifactObject(artifacts[14])).toStrictEqual({ entries: [] }); + + for (const artifact of artifacts) { + expect(manifest.isDefaultArtifact(artifact)).toBe(true); + expect(manifest.getArtifactTargetPolicies(artifact)).toStrictEqual( + new Set([TEST_POLICY_ID_1]) + ); + } }); }); - describe('deleteArtifacts', () => { - test('Successfully invokes saved objects client', async () => { - const context = buildManifestManagerContextMock({}); + describe.each([true, false])( + 'buildNewManifest when Endpoint Exceptions contain `matches`', + (unifiedManifestSO) => { + test(`when contains only \`wildcard\`, \`event.module=endpoint\` is added when unifiedManifestEnabled feature flag is set to: ${unifiedManifestSO}`, async () => { + const exceptionListItem = getExceptionListItemSchemaMock({ + os_types: ['macos'], + entries: [ + { type: 'wildcard', operator: 'included', field: 'path', value: '*match_me*' }, + { type: 'wildcard', operator: 'excluded', field: 'not_path', value: '*dont_match_me*' }, + ], + }); + const expectedExceptionListItem = getExceptionListItemSchemaMock({ + os_types: ['macos'], + entries: [ + ...exceptionListItem.entries, + { type: 'match', operator: 'included', field: 'event.module', value: 'endpoint' }, + ], + }); + + const context = buildManifestManagerContextMock({ + ...(unifiedManifestSO ? { experimentalFeatures: ['unifiedManifestEnabled'] } : {}), + }); + const manifestManager = new ManifestManager(context); + + context.exceptionListClient.findExceptionListItem = mockFindExceptionListItemResponses({ + [ENDPOINT_LIST_ID]: { macos: [exceptionListItem] }, + }); + + context.packagePolicyService.fetchAllItemIds = getMockPolicyFetchAllItemIds([ + TEST_POLICY_ID_1, + ]); + + const manifest = await manifestManager.buildNewManifest(); + + expect(manifest?.getSchemaVersion()).toStrictEqual('v1'); + expect(manifest?.getSemanticVersion()).toStrictEqual('1.0.0'); + expect(manifest?.getSavedObjectVersion()).toBeUndefined(); + + const artifacts = manifest.getAllArtifacts(); + + expect(artifacts.length).toBe(15); + + expect(getArtifactObject(artifacts[0])).toStrictEqual({ + entries: translateToEndpointExceptions([expectedExceptionListItem], 'v1'), + }); + }); + + test(`when contains anything next to \`wildcard\`, nothing is added when unifiedManifestEnabled feature flag is set to: ${unifiedManifestSO}`, async () => { + const exceptionListItem = getExceptionListItemSchemaMock({ + os_types: ['macos'], + entries: [ + { type: 'wildcard', operator: 'included', field: 'path', value: '*match_me*' }, + { type: 'wildcard', operator: 'excluded', field: 'path', value: '*dont_match_me*' }, + { type: 'match', operator: 'included', field: 'path', value: 'something' }, + ], + }); + const expectedExceptionListItem = getExceptionListItemSchemaMock({ + os_types: ['macos'], + entries: [...exceptionListItem.entries], + }); + + const context = buildManifestManagerContextMock({ + ...(unifiedManifestSO ? { experimentalFeatures: ['unifiedManifestEnabled'] } : {}), + }); + const manifestManager = new ManifestManager(context); + + context.exceptionListClient.findExceptionListItem = mockFindExceptionListItemResponses({ + [ENDPOINT_LIST_ID]: { macos: [exceptionListItem] }, + }); + + context.packagePolicyService.fetchAllItemIds = getMockPolicyFetchAllItemIds([ + TEST_POLICY_ID_1, + ]); + + const manifest = await manifestManager.buildNewManifest(); + + expect(manifest?.getSchemaVersion()).toStrictEqual('v1'); + expect(manifest?.getSemanticVersion()).toStrictEqual('1.0.0'); + expect(manifest?.getSavedObjectVersion()).toBeUndefined(); + + const artifacts = manifest.getAllArtifacts(); + + expect(artifacts.length).toBe(15); + + expect(getArtifactObject(artifacts[0])).toStrictEqual({ + entries: translateToEndpointExceptions([expectedExceptionListItem], 'v1'), + }); + }); + } + ); + + describe.each([true, false])('deleteArtifacts', (unifiedManifestSO) => { + test(`Successfully invokes saved objects client when unifiedManifestEnabled feature flag is set to: ${unifiedManifestSO}`, async () => { + const context = buildManifestManagerContextMock({ + ...(unifiedManifestSO ? { experimentalFeatures: ['unifiedManifestEnabled'] } : {}), + }); const manifestManager = new ManifestManager(context); await expect( @@ -1112,8 +1451,10 @@ describe('ManifestManager', () => { ]); }); - test('Returns errors for partial failures', async () => { - const context = buildManifestManagerContextMock({}); + test(`Returns errors for partial failures when unifiedManifestEnabled feature flag is set to: ${unifiedManifestSO}`, async () => { + const context = buildManifestManagerContextMock({ + ...(unifiedManifestSO ? { experimentalFeatures: ['unifiedManifestEnabled'] } : {}), + }); const artifactClient = context.artifactClient as jest.Mocked; const manifestManager = new ManifestManager(context); const error = new Error(); @@ -1140,9 +1481,11 @@ describe('ManifestManager', () => { }); }); - describe('pushArtifacts', () => { - test('Successfully invokes artifactClient', async () => { - const context = buildManifestManagerContextMock({}); + describe.each([true, false])('pushArtifacts', (unifiedManifestSO) => { + test(`Successfully invokes artifactClient when unifiedManifestEnabled feature flag is set to: ${unifiedManifestSO}`, async () => { + const context = buildManifestManagerContextMock({ + ...(unifiedManifestSO ? { experimentalFeatures: ['unifiedManifestEnabled'] } : {}), + }); const artifactClient = context.artifactClient as jest.Mocked; const manifestManager = new ManifestManager(context); const newManifest = ManifestManager.createDefaultManifest(); @@ -1164,8 +1507,10 @@ describe('ManifestManager', () => { ]); }); - test('Returns errors for partial failures', async () => { - const context = buildManifestManagerContextMock({}); + test(`Returns errors for partial failures when unifiedManifestEnabled feature flag is set to: ${unifiedManifestSO}`, async () => { + const context = buildManifestManagerContextMock({ + ...(unifiedManifestSO ? { experimentalFeatures: ['unifiedManifestEnabled'] } : {}), + }); const artifactClient = context.artifactClient as jest.Mocked; const manifestManager = new ManifestManager(context); const newManifest = ManifestManager.createDefaultManifest(); @@ -1206,114 +1551,16 @@ describe('ManifestManager', () => { }); }); - describe('commit', () => { - test('Creates new saved object if no saved object version', async () => { - const context = buildManifestManagerContextMock({}); - const manifestManager = new ManifestManager(context); - const manifest = ManifestManager.createDefaultManifest(); - - manifest.addEntry(ARTIFACT_EXCEPTIONS_MACOS); - manifest.addEntry(ARTIFACT_EXCEPTIONS_MACOS, TEST_POLICY_ID_1); - manifest.addEntry(ARTIFACT_EXCEPTIONS_WINDOWS, TEST_POLICY_ID_2); - manifest.addEntry(ARTIFACT_TRUSTED_APPS_MACOS, TEST_POLICY_ID_1); - manifest.addEntry(ARTIFACT_TRUSTED_APPS_MACOS, TEST_POLICY_ID_2); - - context.savedObjectsClient.create = jest - .fn() - .mockImplementation((_type: string, object: InternalManifestSchema) => object); - - await expect(manifestManager.commit(manifest)).resolves.toBeUndefined(); - - expect(context.savedObjectsClient.create).toHaveBeenCalledTimes(1); - expect(context.savedObjectsClient.create).toHaveBeenNthCalledWith( - 1, - ManifestConstants.SAVED_OBJECT_TYPE, - { - artifacts: [ - { artifactId: ARTIFACT_ID_EXCEPTIONS_MACOS, policyId: undefined }, - { artifactId: ARTIFACT_ID_EXCEPTIONS_MACOS, policyId: TEST_POLICY_ID_1 }, - { artifactId: ARTIFACT_ID_TRUSTED_APPS_MACOS, policyId: TEST_POLICY_ID_1 }, - { artifactId: ARTIFACT_ID_EXCEPTIONS_WINDOWS, policyId: TEST_POLICY_ID_2 }, - { artifactId: ARTIFACT_ID_TRUSTED_APPS_MACOS, policyId: TEST_POLICY_ID_2 }, - ], - schemaVersion: 'v1', - semanticVersion: '1.0.0', - created: expect.anything(), - }, - { id: 'endpoint-manifest-v1' } - ); - }); - - test('Updates existing saved object if has saved object version', async () => { - const context = buildManifestManagerContextMock({}); - const manifestManager = new ManifestManager(context); - const manifest = new Manifest({ soVersion: '1.0.0' }); - - manifest.addEntry(ARTIFACT_EXCEPTIONS_MACOS); - manifest.addEntry(ARTIFACT_EXCEPTIONS_MACOS, TEST_POLICY_ID_1); - manifest.addEntry(ARTIFACT_EXCEPTIONS_WINDOWS, TEST_POLICY_ID_2); - manifest.addEntry(ARTIFACT_TRUSTED_APPS_MACOS, TEST_POLICY_ID_1); - manifest.addEntry(ARTIFACT_TRUSTED_APPS_MACOS, TEST_POLICY_ID_2); - - context.savedObjectsClient.update = jest - .fn() - .mockImplementation((_type: string, _id: string, object: InternalManifestSchema) => object); - - await expect(manifestManager.commit(manifest)).resolves.toBeUndefined(); - - expect(context.savedObjectsClient.update).toHaveBeenCalledTimes(1); - expect(context.savedObjectsClient.update).toHaveBeenNthCalledWith( - 1, - ManifestConstants.SAVED_OBJECT_TYPE, - 'endpoint-manifest-v1', - { - artifacts: [ - { artifactId: ARTIFACT_ID_EXCEPTIONS_MACOS, policyId: undefined }, - { artifactId: ARTIFACT_ID_EXCEPTIONS_MACOS, policyId: TEST_POLICY_ID_1 }, - { artifactId: ARTIFACT_ID_TRUSTED_APPS_MACOS, policyId: TEST_POLICY_ID_1 }, - { artifactId: ARTIFACT_ID_EXCEPTIONS_WINDOWS, policyId: TEST_POLICY_ID_2 }, - { artifactId: ARTIFACT_ID_TRUSTED_APPS_MACOS, policyId: TEST_POLICY_ID_2 }, - ], - schemaVersion: 'v1', - semanticVersion: '1.0.0', - }, - { version: '1.0.0' } - ); - }); - - test('Throws error when saved objects client fails', async () => { - const context = buildManifestManagerContextMock({}); - const manifestManager = new ManifestManager(context); - const manifest = new Manifest({ soVersion: '1.0.0' }); - const error = new Error(); - - context.savedObjectsClient.update = jest.fn().mockRejectedValue(error); - - await expect(manifestManager.commit(manifest)).rejects.toBe(error); - - expect(context.savedObjectsClient.update).toHaveBeenCalledTimes(1); - expect(context.savedObjectsClient.update).toHaveBeenNthCalledWith( - 1, - ManifestConstants.SAVED_OBJECT_TYPE, - 'endpoint-manifest-v1', - { - artifacts: [], - schemaVersion: 'v1', - semanticVersion: '1.0.0', - }, - { version: '1.0.0' } - ); - }); - }); - - describe('tryDispatch', () => { + describe.each([true, false])('tryDispatch', (unifiedSavedObject) => { const getMockPolicyFetchAllItems = (items: PackagePolicy[]) => jest.fn(async function* () { yield items; }); - test('Should not dispatch if no policies', async () => { - const context = buildManifestManagerContextMock({}); + test(`Should not dispatch if no policies when unifiedManifestEnabled feature flag is set to: ${unifiedSavedObject}`, async () => { + const context = buildManifestManagerContextMock({ + ...(unifiedSavedObject ? { experimentalFeatures: ['unifiedManifestEnabled'] } : {}), + }); const manifestManager = new ManifestManager(context); const manifest = new Manifest({ soVersion: '1.0.0' }); @@ -1325,8 +1572,10 @@ describe('ManifestManager', () => { expect(context.packagePolicyService.bulkUpdate).toHaveBeenCalledTimes(0); }); - test('Should return errors if invalid config for package policy', async () => { - const context = buildManifestManagerContextMock({}); + test(`Should return errors if invalid config for package policy when unifiedManifestEnabled feature flag is set to: ${unifiedSavedObject}`, async () => { + const context = buildManifestManagerContextMock({ + ...(unifiedSavedObject ? { experimentalFeatures: ['unifiedManifestEnabled'] } : {}), + }); const manifestManager = new ManifestManager(context); const manifest = new Manifest({ soVersion: '1.0.0' }); @@ -1343,8 +1592,10 @@ describe('ManifestManager', () => { expect(context.packagePolicyService.bulkUpdate).toHaveBeenCalledTimes(0); }); - test('Should not dispatch if semantic version has not changed', async () => { - const context = buildManifestManagerContextMock({}); + test(`Should not dispatch if semantic version has not changed when unifiedManifestEnabled feature flag is set to: ${unifiedSavedObject}`, async () => { + const context = buildManifestManagerContextMock({ + ...(unifiedSavedObject ? { experimentalFeatures: ['unifiedManifestEnabled'] } : {}), + }); const manifestManager = new ManifestManager(context); const manifest = new Manifest({ soVersion: '1.0.0' }); @@ -1372,8 +1623,10 @@ describe('ManifestManager', () => { expect(context.packagePolicyService.bulkUpdate).toHaveBeenCalledTimes(0); }); - test('Should dispatch to only policies where list of artifacts changed', async () => { - const context = buildManifestManagerContextMock({}); + test(`Should dispatch to only policies where list of artifacts changed when unifiedManifestEnabled feature flag is set to: ${unifiedSavedObject}`, async () => { + const context = buildManifestManagerContextMock({ + ...(unifiedSavedObject ? { experimentalFeatures: ['unifiedManifestEnabled'] } : {}), + }); const manifestManager = new ManifestManager(context); const manifest = new Manifest({ soVersion: '1.0.0', semanticVersion: '1.0.1' }); @@ -1441,8 +1694,10 @@ describe('ManifestManager', () => { ); }); - test('Should dispatch to only policies where artifact content changed', async () => { - const context = buildManifestManagerContextMock({}); + test(`Should dispatch to only policies where artifact content changed when unifiedManifestEnabled feature flag is set to: ${unifiedSavedObject}`, async () => { + const context = buildManifestManagerContextMock({ + ...(unifiedSavedObject ? { experimentalFeatures: ['unifiedManifestEnabled'] } : {}), + }); const manifestManager = new ManifestManager(context); const manifest = new Manifest({ soVersion: '1.0.0', semanticVersion: '1.0.1' }); @@ -1512,8 +1767,10 @@ describe('ManifestManager', () => { ); }); - test('Should return partial errors', async () => { - const context = buildManifestManagerContextMock({}); + test(`Should return partial errors when unifiedManifestEnabled feature flag is set to: ${unifiedSavedObject}`, async () => { + const context = buildManifestManagerContextMock({ + ...(unifiedSavedObject ? { experimentalFeatures: ['unifiedManifestEnabled'] } : {}), + }); const manifestManager = new ManifestManager(context); const error = new Error(); @@ -1556,9 +1813,11 @@ describe('ManifestManager', () => { }); }); - describe('cleanup artifacts', () => { - test('Successfully removes orphan artifacts', async () => { - const context = buildManifestManagerContextMock({}); + describe.each([true, false])('cleanup artifacts', (unifiedSavedObject) => { + test(`Successfully removes orphan artifacts when unifiedManifestEnabled feature flag is set to: ${unifiedSavedObject}`, async () => { + const context = buildManifestManagerContextMock({ + ...(unifiedSavedObject ? { experimentalFeatures: ['unifiedManifestEnabled'] } : {}), + }); const manifestManager = new ManifestManager(context); (context.artifactClient.fetchAll as jest.Mock).mockReturnValue( @@ -1586,8 +1845,10 @@ describe('ManifestManager', () => { ]); }); - test('When there is no artifact to be removed', async () => { - const context = buildManifestManagerContextMock({}); + test(`When there is no artifact to be removed when unifiedManifestEnabled feature flag is set to: ${unifiedSavedObject}`, async () => { + const context = buildManifestManagerContextMock({ + ...(unifiedSavedObject ? { experimentalFeatures: ['unifiedManifestEnabled'] } : {}), + }); const manifestManager = new ManifestManager(context); context.exceptionListClient.findExceptionListItem = mockFindExceptionListItemResponses({}); @@ -1625,4 +1886,336 @@ describe('ManifestManager', () => { expect(context.artifactClient.bulkDeleteArtifacts).toHaveBeenCalledTimes(0); }); }); + + describe('Unified Manifest Methods', () => { + let manifestManager: ManifestManager; + let context: ManifestManagerContext; + + beforeEach(() => { + context = buildManifestManagerContextMock({}); + manifestManager = new ManifestManager(context); + }); + + afterEach(() => { + jest.clearAllMocks(); + }); + + describe('transforms', () => { + const createLegacyManifestSO = ( + opts: { + semanticVersion?: string; + } = {} + ) => ({ + attributes: { + schemaVersion: 'v1' as const, + semanticVersion: opts.semanticVersion ?? '1.0.0', + artifacts: [ + { artifactId: ARTIFACT_ID_EXCEPTIONS_MACOS, policyId: undefined }, + { artifactId: ARTIFACT_ID_EXCEPTIONS_WINDOWS, policyId: undefined }, + { artifactId: ARTIFACT_ID_EXCEPTIONS_LINUX, policyId: undefined }, + { artifactId: ARTIFACT_ID_EXCEPTIONS_WINDOWS, policyId: TEST_POLICY_ID_1 }, + { artifactId: ARTIFACT_ID_TRUSTED_APPS_MACOS, policyId: TEST_POLICY_ID_1 }, + { artifactId: ARTIFACT_ID_TRUSTED_APPS_WINDOWS, policyId: TEST_POLICY_ID_1 }, + { artifactId: ARTIFACT_ID_TRUSTED_APPS_WINDOWS, policyId: TEST_POLICY_ID_2 }, + ], + }, + version: 'WzQ3NzAsMV0=', + }); + + const createUnifiedManifestSO = (globalSemanticVersion?: string) => [ + { + policyId: '.global', + semanticVersion: globalSemanticVersion ?? '1.0.0', + artifactIds: [ + ARTIFACT_ID_EXCEPTIONS_MACOS, + ARTIFACT_ID_EXCEPTIONS_WINDOWS, + ARTIFACT_ID_EXCEPTIONS_LINUX, + ], + ...(globalSemanticVersion ? { created: '20-01-2020 10:00:00.000Z' } : {}), + id: '3', + }, + { + policyId: TEST_POLICY_ID_1, + semanticVersion: '1.0.0', + artifactIds: [ + ARTIFACT_ID_EXCEPTIONS_WINDOWS, + ARTIFACT_ID_TRUSTED_APPS_MACOS, + ARTIFACT_ID_TRUSTED_APPS_WINDOWS, + ], + ...(globalSemanticVersion ? { created: '20-01-2020 10:00:00.000Z' } : {}), + id: '1', + }, + { + policyId: TEST_POLICY_ID_2, + semanticVersion: '1.0.0', + artifactIds: [ARTIFACT_ID_TRUSTED_APPS_WINDOWS], + ...(globalSemanticVersion ? { created: '20-01-2020 10:00:00.000Z' } : {}), + id: '2', + }, + ]; + + describe('transformUnifiedManifestSOtoLegacyManifestSO', () => { + const unifiedManifestSO = createUnifiedManifestSO('1.0.5'); + test('should transform unified manifest saved object to legacy manifest saved object', async () => { + const expectedLegacyManifestSO = createLegacyManifestSO({ semanticVersion: '1.0.5' }); + + expect( + manifestManager.transformUnifiedManifestSOtoLegacyManifestSO( + unifiedManifestSO as InternalUnifiedManifestSchema[] + ) + ).toEqual(expectedLegacyManifestSO); + }); + + test('should return empty artifacts array when unified manifest saved object is empty', async () => { + const emptyUnifiedManifestSO: InternalUnifiedManifestSchema[] = []; + const expectedEmptyLegacyManifestSO = createLegacyManifestSO(); + expect( + manifestManager.transformUnifiedManifestSOtoLegacyManifestSO(emptyUnifiedManifestSO) + ).toEqual({ + ...expectedEmptyLegacyManifestSO, + attributes: { ...expectedEmptyLegacyManifestSO.attributes, artifacts: [] }, + }); + }); + + test('should return empty artifacts array when unified manifest saved object is empty but semanticVersion was provided', async () => { + const semanticVersion = '1.14.0'; + const emptyUnifiedManifestSO: InternalUnifiedManifestSchema[] = []; + const expectedEmptyLegacyManifestSO = createLegacyManifestSO(); + expect( + manifestManager.transformUnifiedManifestSOtoLegacyManifestSO( + emptyUnifiedManifestSO, + semanticVersion + ) + ).toEqual({ + ...expectedEmptyLegacyManifestSO, + attributes: { + ...expectedEmptyLegacyManifestSO.attributes, + artifacts: [], + semanticVersion, + }, + }); + }); + }); + describe('transformLegacyManifestSOtoUnifiedManifestSO', () => { + const unifiedManifestSO = createUnifiedManifestSO(); + const expectedLegacyManifestSO = createLegacyManifestSO().attributes; + test('should properly transform legacy manifest to unified manifest saved object with empty exising unified manifest so', async () => { + expect( + manifestManager.transformLegacyManifestSOtoUnifiedManifestSO( + expectedLegacyManifestSO, + [] + ) + ).toEqual(unifiedManifestSO.map((item) => ({ ...item, id: undefined }))); + }); + + test('should properly transform legacy manifest to unified manifest saved object with empty exising unified manifest so and propagate semanticVersion from the manifest', async () => { + const semanticVersion = '1.14.0'; + const expectedLegacyManifestSOWithSemanticVersion = createLegacyManifestSO({ + semanticVersion, + }).attributes; + const unifiedManifestSOWithSemanticVersion = createUnifiedManifestSO(semanticVersion); + + expect( + manifestManager.transformLegacyManifestSOtoUnifiedManifestSO( + expectedLegacyManifestSOWithSemanticVersion, + [] + ) + ).toEqual( + unifiedManifestSOWithSemanticVersion.map((item) => ({ + ...item, + id: undefined, + created: undefined, + })) + ); + }); + + test('should properly transform legacy manifest to unified manifest saved object with existing unified manifest so', async () => { + const createUnifiedManifests = (empty = false) => [ + { + policyId: '.global', + semanticVersion: '1.0.2', + artifactIds: !empty + ? [ + ARTIFACT_ID_EXCEPTIONS_MACOS, + ARTIFACT_ID_EXCEPTIONS_WINDOWS, + ARTIFACT_ID_EXCEPTIONS_LINUX, + ] + : [], + id: '3', + ...(empty ? { created: '2000' } : {}), + }, + { + policyId: TEST_POLICY_ID_1, + semanticVersion: '1.0.5', + artifactIds: !empty + ? [ + ARTIFACT_ID_EXCEPTIONS_WINDOWS, + ARTIFACT_ID_TRUSTED_APPS_MACOS, + ARTIFACT_ID_TRUSTED_APPS_WINDOWS, + ] + : [], + id: '1', + ...(empty ? { created: '2000' } : {}), + }, + { + policyId: TEST_POLICY_ID_2, + semanticVersion: '1.0.1', + artifactIds: !empty ? [ARTIFACT_ID_TRUSTED_APPS_WINDOWS] : [], + id: '2', + ...(empty ? { created: '2000' } : {}), + }, + ]; + + const existingUnifiedManifest = createUnifiedManifests(true); + const output = createUnifiedManifests(); + + const legacyManifest = createLegacyManifestSO().attributes; + + expect( + manifestManager.transformLegacyManifestSOtoUnifiedManifestSO( + legacyManifest, + existingUnifiedManifest as InternalUnifiedManifestSchema[] + ) + ).toEqual(output); + }); + }); + }); + + describe('prepareUnifiedManifestsSOUpdates', () => { + const existingUnifiedManifests = ['.global', TEST_POLICY_ID_1, TEST_POLICY_ID_2].map( + (policyId, idx) => ({ + policyId, + semanticVersion: '1.0.0', + artifactIds: [ARTIFACT_ID_EXCEPTIONS_WINDOWS], + id: `${idx}`, + created: '1', + version: 'abc', + }) + ); + + const bumpSemanticVersion = ( + manifests: Array>, + semanticVersion = '1.0.1' + ) => + manifests.map((manifest) => ({ + ...manifest, + semanticVersion, + })); + + test('correctly selects manifests to create', () => { + const unifiedManifest = existingUnifiedManifests.map( + ({ id, created, ...manifest }) => manifest + ); + + const { unifiedManifestsToUpdate, unifiedManifestsToCreate, unifiedManifestsToDelete } = + manifestManager.prepareUnifiedManifestsSOUpdates(unifiedManifest, []); + + expect(unifiedManifestsToUpdate).toEqual([]); + expect(unifiedManifestsToCreate).toEqual(unifiedManifest); + expect(unifiedManifestsToDelete).toEqual([]); + }); + test('correctly selects manifests to delete', () => { + const newUnifiedManifests = existingUnifiedManifests.slice(0, 2); + + const { unifiedManifestsToUpdate, unifiedManifestsToCreate, unifiedManifestsToDelete } = + manifestManager.prepareUnifiedManifestsSOUpdates( + newUnifiedManifests, + existingUnifiedManifests + ); + + expect(unifiedManifestsToUpdate).toEqual([]); + expect(unifiedManifestsToCreate).toEqual([]); + expect(unifiedManifestsToDelete).toEqual([existingUnifiedManifests[2].id]); + }); + test('correctly selects manifests to update when artifactIds changed', () => { + const newUnifiedManifests = existingUnifiedManifests.map((manifest) => ({ + ...manifest, + artifactIds: [ARTIFACT_ID_EXCEPTIONS_WINDOWS, ARTIFACT_ID_EXCEPTIONS_WINDOWS], + })); + + const expectedUnifiedManifestsToUpdate = bumpSemanticVersion(newUnifiedManifests); + + const { unifiedManifestsToUpdate, unifiedManifestsToCreate, unifiedManifestsToDelete } = + manifestManager.prepareUnifiedManifestsSOUpdates( + newUnifiedManifests, + existingUnifiedManifests + ); + + expect(unifiedManifestsToUpdate).toEqual(expectedUnifiedManifestsToUpdate); + expect(unifiedManifestsToCreate).toEqual([]); + expect(unifiedManifestsToDelete).toEqual([]); + }); + + test('correctly combines all cases', () => { + const newUnifiedManifests = existingUnifiedManifests.slice(0, 2).map((manifest) => ({ + ...manifest, + artifactIds: [ARTIFACT_ID_EXCEPTIONS_WINDOWS, ARTIFACT_ID_EXCEPTIONS_WINDOWS], + })); + + const newUnifiedManifestsAddition = { + policyId: 'test', + semanticVersion: '1.0.0', + artifactIds: [], + }; + + const expectedUnifiedManifestsToUpdate = bumpSemanticVersion(newUnifiedManifests); + + const expectedUnifiedManifestsToCreate = [newUnifiedManifestsAddition]; + + const expectedUnifiedManifestsToDelete = [existingUnifiedManifests[2].id]; + + const { unifiedManifestsToUpdate, unifiedManifestsToCreate, unifiedManifestsToDelete } = + manifestManager.prepareUnifiedManifestsSOUpdates( + [...newUnifiedManifests, newUnifiedManifestsAddition], + existingUnifiedManifests + ); + + expect(unifiedManifestsToUpdate).toEqual(expectedUnifiedManifestsToUpdate); + expect(unifiedManifestsToCreate).toEqual(expectedUnifiedManifestsToCreate); + expect(unifiedManifestsToDelete).toEqual(expectedUnifiedManifestsToDelete); + }); + }); + describe('bumpGlobalUnifiedManifestVersion', () => { + const createSoFindMock = (savedObjects: Array>) => + jest.fn().mockImplementation(async (objectType: { type: string }) => { + if (objectType.type === ManifestConstants.UNIFIED_SAVED_OBJECT_TYPE) { + return { + saved_objects: savedObjects, + }; + } else { + return null; + } + }); + + test('should bump the semantic version of the global manifest', async () => { + context.savedObjectsClient.find = createSoFindMock([ + { + id: '1', + attributes: { + policyId: '.global', + semanticVersion: '1.0.1', + }, + }, + ]); + context.savedObjectsClient.bulkUpdate = jest.fn(); + await manifestManager.bumpGlobalUnifiedManifestVersion(); + expect(context.savedObjectsClient.bulkUpdate).toHaveBeenCalledWith([ + { + id: '1', + type: ManifestConstants.UNIFIED_SAVED_OBJECT_TYPE, + attributes: { + policyId: '.global', + semanticVersion: '1.0.2', + }, + }, + ]); + }); + test('should make a clean return when no global manifest is found', async () => { + context.savedObjectsClient.find = createSoFindMock([]); + context.savedObjectsClient.bulkUpdate = jest.fn(); + await manifestManager.bumpGlobalUnifiedManifestVersion(); + expect(context.savedObjectsClient.bulkUpdate).toHaveBeenCalledTimes(0); + }); + }); + }); }); diff --git a/x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.ts b/x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.ts index 663318c7459a3..3a6cfc5be280c 100644 --- a/x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.ts +++ b/x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.ts @@ -6,15 +6,17 @@ */ import semver from 'semver'; -import { isEmpty, isEqual, keyBy } from 'lodash'; +import { chunk, isEmpty, isEqual, keyBy } from 'lodash'; import type { ElasticsearchClient } from '@kbn/core/server'; import { type Logger, type SavedObjectsClientContract } from '@kbn/core/server'; -import { ENDPOINT_LIST_ID, ENDPOINT_ARTIFACT_LISTS } from '@kbn/securitysolution-list-constants'; +import { ENDPOINT_ARTIFACT_LISTS, ENDPOINT_LIST_ID } from '@kbn/securitysolution-list-constants'; import type { PackagePolicy } from '@kbn/fleet-plugin/common'; import type { Artifact, PackagePolicyClient } from '@kbn/fleet-plugin/server'; import type { ExceptionListClient } from '@kbn/lists-plugin/server'; import type { ExceptionListItemSchema } from '@kbn/securitysolution-io-ts-list-types'; import { ProductFeatureKey } from '@kbn/security-solution-features/keys'; +import { asyncForEach } from '@kbn/std'; +import { UnifiedManifestClient } from '../unified_manifest_client'; import { stringify } from '../../../utils/stringify'; import { QueueProcessor } from '../../../utils/queue_processor'; import type { ProductFeaturesService } from '../../../../lib/product_features_service/product_features_service'; @@ -35,9 +37,15 @@ import { Manifest, } from '../../../lib/artifacts'; +import type { + InternalUnifiedManifestBaseSchema, + InternalUnifiedManifestSchema, + InternalUnifiedManifestUpdateSchema, +} from '../../../schemas/artifacts'; import { internalArtifactCompleteSchema, type InternalArtifactCompleteSchema, + type InternalManifestSchema, type WrappedTranslatedExceptionList, } from '../../../schemas/artifacts'; import type { EndpointArtifactClientInterface } from '../artifact_client'; @@ -513,7 +521,25 @@ export class ManifestManager { */ public async getLastComputedManifest(): Promise { try { - const manifestSo = await this.getManifestClient().getManifest(); + let manifestSo; + if (this.experimentalFeatures.unifiedManifestEnabled) { + const unifiedManifestsSo = await this.getAllUnifiedManifestsSO(); + // On first run, there will be no existing Unified Manifests SO, so we need to copy the semanticVersion from the legacy manifest + // This is to ensure that the first Unified Manifest created has the same semanticVersion as the legacy manifest and is not too far + // behind for package policy to pick it up. + if (unifiedManifestsSo.length === 0) { + const legacyManifestSo = await this.getManifestClient().getManifest(); + const legacySemanticVersion = legacyManifestSo?.attributes?.semanticVersion; + manifestSo = this.transformUnifiedManifestSOtoLegacyManifestSO( + unifiedManifestsSo, + legacySemanticVersion + ); + } else { + manifestSo = this.transformUnifiedManifestSOtoLegacyManifestSO(unifiedManifestsSo); + } + } else { + manifestSo = await this.getManifestClient().getManifest(); + } if (manifestSo.version === undefined) { throw new InvalidInternalManifestError( @@ -721,21 +747,25 @@ export class ManifestManager { * @returns {Promise} An error, if encountered, or null. */ public async commit(manifest: Manifest) { - const manifestClient = this.getManifestClient(); - - // Commit the new manifest const manifestSo = manifest.toSavedObject(); - const version = manifest.getSavedObjectVersion(); - if (version == null) { - await manifestClient.createManifest(manifestSo); + if (this.experimentalFeatures.unifiedManifestEnabled) { + await this.commitUnified(manifestSo); } else { - await manifestClient.updateManifest(manifestSo, { - version, - }); - } + const manifestClient = this.getManifestClient(); - this.logger.debug(`Committed manifest ${manifest.getSemanticVersion()}`); + const version = manifest.getSavedObjectVersion(); + + if (version == null) { + await manifestClient.createManifest(manifestSo); + } else { + await manifestClient.updateManifest(manifestSo, { + version, + }); + } + + this.logger.debug(`Committed manifest ${manifest.getSemanticVersion()}`); + } } private fetchAllPolicies(): AsyncIterable { @@ -835,4 +865,229 @@ export class ManifestManager { ); } } + + /** + * Unified Manifest methods + */ + + private setNewSemanticVersion(semanticVersion: string): string | null { + const newSemanticVersion = semver.inc(semanticVersion, 'patch'); + if (!semver.valid(newSemanticVersion)) { + throw new Error(`Invalid semver: ${newSemanticVersion}`); + } + return newSemanticVersion; + } + + protected getUnifiedManifestClient(): UnifiedManifestClient { + return new UnifiedManifestClient(this.savedObjectsClient); + } + + public async getAllUnifiedManifestsSO(): Promise { + return this.getUnifiedManifestClient().getAllUnifiedManifests(); + } + + public transformUnifiedManifestSOtoLegacyManifestSO( + unifiedManifestsSo: InternalUnifiedManifestSchema[], + semanticVersion?: string + ): { + version: string; + attributes: { + artifacts: Array< + { artifactId: string; policyId: undefined } | { artifactId: string; policyId: string } + >; + semanticVersion: string; + schemaVersion: ManifestSchemaVersion; + }; + } { + const globalUnifiedManifest = unifiedManifestsSo.find((a) => a.policyId === '.global'); + return { + version: 'WzQ3NzAsMV0=', // version is hardcoded since it was used only to determine whether to create a new manifest or update an existing one + attributes: { + artifacts: [ + ...(globalUnifiedManifest?.artifactIds.map((artifactId) => ({ + artifactId, + policyId: undefined, + })) ?? []), + ...unifiedManifestsSo.reduce( + (acc: Array<{ artifactId: string; policyId: string }>, unifiedManifest) => { + if (unifiedManifest.policyId === '.global') { + return acc; + } + acc.push( + ...unifiedManifest.artifactIds.map((artifactId) => ({ + policyId: unifiedManifest.policyId, + artifactId, + })) + ); + + return acc; + }, + [] + ), + ], + semanticVersion: (semanticVersion || globalUnifiedManifest?.semanticVersion) ?? '1.0.0', + schemaVersion: this.schemaVersion, + }, + }; + } + + public transformLegacyManifestSOtoUnifiedManifestSO( + manifestSo: InternalManifestSchema, + unifiedManifestsSo: InternalUnifiedManifestSchema[] + ): Array { + const manifestObject = manifestSo.artifacts.reduce( + ( + acc: Record, + { artifactId, policyId = '.global' } + ) => { + const existingPolicy = acc[policyId]; + if (existingPolicy) { + existingPolicy.artifactIds.push(artifactId); + } else { + const existingUnifiedManifestSo = unifiedManifestsSo.find( + (item) => item.policyId === policyId + ); + + // On first run, there will be no existing Unified Manifests SO, so we need to copy the semanticVersion from the legacy manifest + // This is to ensure that the first Unified Manifest created has the same semanticVersion as the legacy manifest and is not too far + // behind for package policy to pick it up. + const semanticVersion = + (policyId === '.global' && !unifiedManifestsSo.length + ? manifestSo?.semanticVersion + : existingUnifiedManifestSo?.semanticVersion) ?? '1.0.0'; + + acc[policyId] = { + policyId, + artifactIds: [artifactId], + semanticVersion, + id: existingUnifiedManifestSo?.id, + }; + } + return acc; + }, + {} + ); + return Object.values(manifestObject); + } + + public prepareUnifiedManifestsSOUpdates( + unifiedManifestsSo: Array & { id?: string }>, + existingUnifiedManifestsSo: InternalUnifiedManifestSchema[] + ) { + const existingManifestsObj: Record = {}; + existingUnifiedManifestsSo.forEach((manifest) => { + existingManifestsObj[manifest.id] = manifest; + }); + + const { unifiedManifestsToUpdate, unifiedManifestsToCreate } = unifiedManifestsSo.reduce( + ( + acc: { + unifiedManifestsToUpdate: InternalUnifiedManifestUpdateSchema[]; + unifiedManifestsToCreate: InternalUnifiedManifestBaseSchema[]; + }, + unifiedManifest + ) => { + if (unifiedManifest.id !== undefined) { + // Manifest with id exists in SO, check if it needs to be updated + const existingUnifiedManifest = existingManifestsObj[unifiedManifest.id]; + // Update SO if the artifactIds changed. + if (!isEqual(existingUnifiedManifest.artifactIds, unifiedManifest.artifactIds)) { + acc.unifiedManifestsToUpdate.push({ + ...unifiedManifest, + semanticVersion: this.setNewSemanticVersion(unifiedManifest.semanticVersion), + version: existingUnifiedManifest.version, + } as InternalUnifiedManifestUpdateSchema); + } + } else { + // Manifest with id does not exist in SO, create new SO + acc.unifiedManifestsToCreate.push(unifiedManifest); + } + + return acc; + }, + { unifiedManifestsToUpdate: [], unifiedManifestsToCreate: [] } + ); + + const unifiedManifestsToDelete = existingUnifiedManifestsSo.reduce( + (acc: string[], { policyId, id }) => { + const existingPolicy = unifiedManifestsSo.find((item) => item.policyId === policyId); + if (!existingPolicy) { + acc.push(id); + } + return acc; + }, + [] + ); + + return { unifiedManifestsToUpdate, unifiedManifestsToCreate, unifiedManifestsToDelete }; + } + + public async bumpGlobalUnifiedManifestVersion(): Promise { + const globalUnifiedManifestSO = + await this.getUnifiedManifestClient().getUnifiedManifestByPolicyId('.global'); + if (!globalUnifiedManifestSO?.saved_objects?.length) { + this.logger.warn('No Global Unified Manifest found to bump version'); + return; + } + const globalUnifiedManifest = globalUnifiedManifestSO.saved_objects[0]; + + const newSemanticVersion = + this.setNewSemanticVersion(globalUnifiedManifest.attributes.semanticVersion) || '1.0.0'; + await this.getUnifiedManifestClient().updateUnifiedManifest({ + ...globalUnifiedManifest.attributes, + id: globalUnifiedManifest.id, + semanticVersion: newSemanticVersion, + }); + } + + public async commitUnified(manifestSo: InternalManifestSchema): Promise { + const existingUnifiedManifestsSo = await this.getAllUnifiedManifestsSO(); + + const unifiedManifestSO = this.transformLegacyManifestSOtoUnifiedManifestSO( + manifestSo, + existingUnifiedManifestsSo + ); + + const { unifiedManifestsToUpdate, unifiedManifestsToCreate, unifiedManifestsToDelete } = + this.prepareUnifiedManifestsSOUpdates(unifiedManifestSO, existingUnifiedManifestsSo); + + if (unifiedManifestsToCreate.length) { + await asyncForEach(chunk(unifiedManifestsToCreate, 100), async (unifiedManifestsBatch) => { + await this.getUnifiedManifestClient().createUnifiedManifests(unifiedManifestsBatch); + }); + this.logger.debug(`Created ${unifiedManifestsToCreate.length} unified manifests`); + } + + if (unifiedManifestsToUpdate.length) { + await asyncForEach(chunk(unifiedManifestsToUpdate, 100), async (unifiedManifestsBatch) => { + await this.getUnifiedManifestClient().updateUnifiedManifests(unifiedManifestsBatch); + }); + + this.logger.debug(`Updated ${unifiedManifestsToUpdate.length} unified manifests`); + } + + if (unifiedManifestsToDelete.length) { + await asyncForEach(chunk(unifiedManifestsToDelete, 100), async (unifiedManifestsBatch) => { + await this.getUnifiedManifestClient().deleteUnifiedManifestByIds(unifiedManifestsBatch); + }); + + this.logger.debug(`Deleted ${unifiedManifestsToDelete.length} unified manifests`); + } + + if ( + unifiedManifestsToCreate.length || + unifiedManifestsToUpdate.length || + unifiedManifestsToDelete.length + ) { + // If global manifest is not in the list of manifests to create or update, we need to bump its version + // We use it to set schemaVersion of the legacy manifest we are going to create so that its being picked up when populating agent policy + const hasGlobalManifest = [...unifiedManifestsToCreate, ...unifiedManifestsToUpdate].some( + (manifest) => manifest.policyId === '.global' + ); + + if (!hasGlobalManifest || unifiedManifestsToDelete.length) { + await this.bumpGlobalUnifiedManifestVersion(); + } + } + } } diff --git a/x-pack/plugins/security_solution/server/endpoint/services/artifacts/unified_manifes_client.test.ts b/x-pack/plugins/security_solution/server/endpoint/services/artifacts/unified_manifes_client.test.ts index 83a37e617caf7..4fde69946ccff 100644 --- a/x-pack/plugins/security_solution/server/endpoint/services/artifacts/unified_manifes_client.test.ts +++ b/x-pack/plugins/security_solution/server/endpoint/services/artifacts/unified_manifes_client.test.ts @@ -73,8 +73,7 @@ describe('unified_manifest_client', () => { test('can get unified manifest by id', async () => { await unifiedManifestClient.getUnifiedManifestById('123'); expect(savedObjectsClient.bulkGet).toHaveBeenCalledWith( - expect.arrayContaining([mockSoClientCallParams({ id: '123' }, false)]), - { namespace: UNIFIED_MANIFEST_ALL_NAMESPACES } + expect.arrayContaining([mockSoClientCallParams({ id: '123' }, false)]) ); }); @@ -84,8 +83,7 @@ describe('unified_manifest_client', () => { expect.arrayContaining([ mockSoClientCallParams({ id: '123' }, false), mockSoClientCallParams({ id: '456' }, false), - ]), - { namespace: UNIFIED_MANIFEST_ALL_NAMESPACES } + ]) ); }); @@ -114,17 +112,14 @@ describe('unified_manifest_client', () => { ...mockUnifiedManifestAttributes({ policyId: `policy-${i}` }), id: `id-${i}`, created: '1', + version: '1', }; }) ); - const cbFunc = jest.fn(); - await unifiedManifestClient.getAllUnifiedManifests(cbFunc); + const result = await unifiedManifestClient.getAllUnifiedManifests(); - expect(cbFunc).toHaveBeenCalledTimes(3); - expect(cbFunc).toHaveBeenLastCalledWith([ - expect.objectContaining({ policyId: 'policy-2000', id: 'id-2000' }), - ]); + expect(result.length).toBe(2001); }); }); @@ -140,8 +135,7 @@ describe('unified_manifest_client', () => { expect(savedObjectsClient.bulkUpdate).toHaveBeenCalledWith( expect.arrayContaining([ mockSoClientCallParams({ id: '1234', version: 'abcd' }, true, false), - ]), - { namespace: UNIFIED_MANIFEST_ALL_NAMESPACES } + ]) ); }); test('can update unified manifests', async () => { @@ -153,8 +147,7 @@ describe('unified_manifest_client', () => { expect.arrayContaining([ mockSoClientCallParams({ id: '1234', version: 'abcd' }, true, false), mockSoClientCallParams({ id: '1234', version: 'abcd' }, true, false), - ]), - { namespace: UNIFIED_MANIFEST_ALL_NAMESPACES } + ]) ); }); }); @@ -162,8 +155,7 @@ describe('unified_manifest_client', () => { test('can delete unified manifest', async () => { await unifiedManifestClient.deleteUnifiedManifestById('123'); expect(savedObjectsClient.bulkDelete).toHaveBeenCalledWith( - expect.arrayContaining([{ id: '123', type: ManifestConstants.UNIFIED_SAVED_OBJECT_TYPE }]), - { namespace: UNIFIED_MANIFEST_ALL_NAMESPACES } + expect.arrayContaining([{ id: '123', type: ManifestConstants.UNIFIED_SAVED_OBJECT_TYPE }]) ); }); test('can delete unified manifests', async () => { @@ -172,8 +164,7 @@ describe('unified_manifest_client', () => { expect.arrayContaining([ mockSoClientCallParams({ id: '123' }, false), mockSoClientCallParams({ id: '456' }, false), - ]), - { namespace: UNIFIED_MANIFEST_ALL_NAMESPACES } + ]) ); }); }); diff --git a/x-pack/plugins/security_solution/server/endpoint/services/artifacts/unified_manifest_client.ts b/x-pack/plugins/security_solution/server/endpoint/services/artifacts/unified_manifest_client.ts index db47c43b68607..d84742ed65f10 100644 --- a/x-pack/plugins/security_solution/server/endpoint/services/artifacts/unified_manifest_client.ts +++ b/x-pack/plugins/security_solution/server/endpoint/services/artifacts/unified_manifest_client.ts @@ -86,20 +86,19 @@ export class UnifiedManifestClient { manifestIds: string[] ): Promise> { return this.savedObjectsClient.bulkGet( - manifestIds.map((id) => ({ id, type: ManifestConstants.UNIFIED_SAVED_OBJECT_TYPE })), - { namespace: UNIFIED_MANIFEST_ALL_NAMESPACES } + manifestIds.map((id) => ({ id, type: ManifestConstants.UNIFIED_SAVED_OBJECT_TYPE })) ); } public async getAllUnifiedManifests( - cb: (unifiedManifests: InternalUnifiedManifestSchema[]) => void | Promise, options?: FetchAllUnifiedManifestsOptions - ): Promise { + ): Promise { const unifiedManifestsFetcher = this.fetchAllUnifiedManifests(this.savedObjectsClient, options); - + const allUnifiedManifests: InternalUnifiedManifestSchema[] = []; for await (const unifiedManifests of unifiedManifestsFetcher) { - await cb(unifiedManifests); + allUnifiedManifests.push(...unifiedManifests); } + return allUnifiedManifests; } /** @@ -127,8 +126,7 @@ export class UnifiedManifestClient { attributes, ...(version ? { version } : {}), }; - }), - { namespace: UNIFIED_MANIFEST_ALL_NAMESPACES } + }) ); } @@ -144,8 +142,7 @@ export class UnifiedManifestClient { manifestIds: string[] ): Promise { return this.savedObjectsClient.bulkDelete( - manifestIds.map((id) => ({ id, type: ManifestConstants.UNIFIED_SAVED_OBJECT_TYPE })), - { namespace: UNIFIED_MANIFEST_ALL_NAMESPACES } + manifestIds.map((id) => ({ id, type: ManifestConstants.UNIFIED_SAVED_OBJECT_TYPE })) ); } @@ -160,7 +157,7 @@ export class UnifiedManifestClient { fields = [], kuery, sortOrder = 'asc', - sortField = 'created', + sortField = 'created_at', }: FetchAllUnifiedManifestsOptions = {} ): AsyncIterable { return createSoFindIterable({ diff --git a/x-pack/plugins/security_solution/server/endpoint/services/artifacts/utils.ts b/x-pack/plugins/security_solution/server/endpoint/services/artifacts/utils.ts index f52eafbdc4529..de1484bf155a1 100644 --- a/x-pack/plugins/security_solution/server/endpoint/services/artifacts/utils.ts +++ b/x-pack/plugins/security_solution/server/endpoint/services/artifacts/utils.ts @@ -16,6 +16,7 @@ export const mapUnifiedManifestSavedObjectToUnifiedManifest = ({ attributes: { artifactIds, policyId, semanticVersion }, // eslint-disable-next-line @typescript-eslint/naming-convention created_at, + version, }: SavedObject): InternalUnifiedManifestSchema => { return { id, @@ -23,5 +24,6 @@ export const mapUnifiedManifestSavedObjectToUnifiedManifest = ({ semanticVersion, created: created_at, artifactIds, + version, }; }; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/logic/diff/normalization/convert_rule_to_diffable.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/logic/diff/normalization/convert_rule_to_diffable.ts index 95a8687324d1c..c08edbc0c5cc5 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/logic/diff/normalization/convert_rule_to_diffable.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/logic/diff/normalization/convert_rule_to_diffable.ts @@ -53,6 +53,7 @@ import { extractRuleNameOverrideObject } from './extract_rule_name_override_obje import { extractRuleSchedule } from './extract_rule_schedule'; import { extractTimelineTemplateReference } from './extract_timeline_template_reference'; import { extractTimestampOverrideObject } from './extract_timestamp_override_object'; +import { addEcsToRequiredFields } from '../../../../rule_management/utils/utils'; /** * Normalizes a given rule to the form which is suitable for passing to the diff algorithm. @@ -133,7 +134,7 @@ const extractDiffableCommonFields = ( note: rule.note ?? '', setup: rule.setup ?? '', related_integrations: rule.related_integrations ?? [], - required_fields: rule.required_fields ?? [], + required_fields: addEcsToRequiredFields(rule.required_fields), author: rule.author ?? [], license: rule.license ?? '', diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/model/rule_assets/prebuilt_rule_asset.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/model/rule_assets/prebuilt_rule_asset.ts index 40a3d048fb518..38ead608a3b75 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/model/rule_assets/prebuilt_rule_asset.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/prebuilt_rules/model/rule_assets/prebuilt_rule_asset.ts @@ -7,7 +7,6 @@ import * as z from 'zod'; import { - RequiredFieldArray, RuleSignatureId, RuleVersion, BaseCreateProps, @@ -33,6 +32,5 @@ export const PrebuiltRuleAsset = BaseCreateProps.and(TypeSpecificCreateProps).an z.object({ rule_id: RuleSignatureId, version: RuleVersion, - required_fields: RequiredFieldArray.optional(), }) ); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/crud/update_rules.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/crud/update_rules.ts index d36f0ab4ad66e..ec790f9f6f71b 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/crud/update_rules.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/crud/update_rules.ts @@ -14,6 +14,7 @@ import { transformRuleToAlertAction } from '../../../../../../common/detection_e import type { InternalRuleUpdate, RuleParams, RuleAlertType } from '../../../rule_schema'; import { transformToActionFrequency } from '../../normalization/rule_actions'; import { typeSpecificSnakeToCamel } from '../../normalization/rule_converters'; +import { addEcsToRequiredFields } from '../../utils/utils'; export interface UpdateRulesOptions { rulesClient: RulesClient; @@ -38,6 +39,7 @@ export const updateRules = async ({ const typeSpecificParams = typeSpecificSnakeToCamel(ruleUpdate); const enabled = ruleUpdate.enabled ?? true; + const newInternalRule: InternalRuleUpdate = { name: ruleUpdate.name, tags: ruleUpdate.tags ?? [], @@ -58,7 +60,7 @@ export const updateRules = async ({ meta: ruleUpdate.meta, maxSignals: ruleUpdate.max_signals ?? DEFAULT_MAX_SIGNALS, relatedIntegrations: ruleUpdate.related_integrations ?? [], - requiredFields: existingRule.params.requiredFields, + requiredFields: addEcsToRequiredFields(ruleUpdate.required_fields), riskScore: ruleUpdate.risk_score, riskScoreMapping: ruleUpdate.risk_score_mapping ?? [], ruleNameOverride: ruleUpdate.rule_name_override, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/normalization/rule_converters.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/normalization/rule_converters.ts index 50a1cecce88c8..355fa626f7848 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/normalization/rule_converters.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/normalization/rule_converters.ts @@ -22,7 +22,6 @@ import { import type { PatchRuleRequestBody } from '../../../../../common/api/detection_engine/rule_management'; import type { RelatedIntegrationArray, - RequiredFieldArray, RuleCreateProps, TypeSpecificCreateProps, TypeSpecificResponse, @@ -78,6 +77,7 @@ import type { } from '../../rule_schema'; import { transformFromAlertThrottle, transformToActionFrequency } from './rule_actions'; import { + addEcsToRequiredFields, convertAlertSuppressionToCamel, convertAlertSuppressionToSnake, migrateLegacyInvestigationFields, @@ -431,7 +431,6 @@ export const patchTypeSpecificSnakeToCamel = ( export const convertPatchAPIToInternalSchema = ( nextParams: PatchRuleRequestBody & { related_integrations?: RelatedIntegrationArray; - required_fields?: RequiredFieldArray; }, existingRule: SanitizedRule ): InternalRuleUpdate => { @@ -462,7 +461,7 @@ export const convertPatchAPIToInternalSchema = ( meta: nextParams.meta ?? existingParams.meta, maxSignals: nextParams.max_signals ?? existingParams.maxSignals, relatedIntegrations: nextParams.related_integrations ?? existingParams.relatedIntegrations, - requiredFields: nextParams.required_fields ?? existingParams.requiredFields, + requiredFields: addEcsToRequiredFields(nextParams.required_fields), riskScore: nextParams.risk_score ?? existingParams.riskScore, riskScoreMapping: nextParams.risk_score_mapping ?? existingParams.riskScoreMapping, ruleNameOverride: nextParams.rule_name_override ?? existingParams.ruleNameOverride, @@ -487,11 +486,9 @@ export const convertPatchAPIToInternalSchema = ( }; }; -// eslint-disable-next-line complexity export const convertCreateAPIToInternalSchema = ( input: RuleCreateProps & { related_integrations?: RelatedIntegrationArray; - required_fields?: RequiredFieldArray; }, immutable = false, defaultEnabled = true @@ -537,7 +534,7 @@ export const convertCreateAPIToInternalSchema = ( version: input.version ?? 1, exceptionsList: input.exceptions_list ?? [], relatedIntegrations: input.related_integrations ?? [], - requiredFields: input.required_fields ?? [], + requiredFields: addEcsToRequiredFields(input.required_fields), setup: input.setup ?? '', ...typeSpecificParams, }, @@ -776,6 +773,7 @@ export const convertPrebuiltRuleAssetToRuleResponse = ( return RuleResponse.parse({ ...prebuiltRuleAssetDefaults, ...prebuiltRuleAsset, + required_fields: addEcsToRequiredFields(prebuiltRuleAsset.required_fields), ...ruleResponseSpecificFields, }); }; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/utils/utils.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/utils/utils.ts index bda8cd7a688ca..66fa635e768ad 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/utils/utils.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/utils/utils.ts @@ -9,6 +9,8 @@ import { partition } from 'lodash/fp'; import pMap from 'p-map'; import { v4 as uuidv4 } from 'uuid'; +import { ecsFieldMap } from '@kbn/alerts-as-data-utils'; + import type { ActionsClient, FindActionResult } from '@kbn/actions-plugin/server'; import type { FindResult, PartialRule } from '@kbn/alerting-plugin/server'; import type { SavedObjectsClientContract } from '@kbn/core/server'; @@ -18,6 +20,8 @@ import type { AlertSuppression, AlertSuppressionCamel, InvestigationFields, + RequiredField, + RequiredFieldInput, RuleResponse, } from '../../../../../common/api/detection_engine/model/rule_schema'; import type { @@ -388,3 +392,19 @@ export const migrateLegacyInvestigationFields = ( return investigationFields; }; + +/* + Computes the boolean "ecs" property value for each required field based on the ECS field map. + "ecs" property indicates whether the required field is an ECS field or not. +*/ +export const addEcsToRequiredFields = (requiredFields?: RequiredFieldInput[]): RequiredField[] => + (requiredFields ?? []).map((requiredFieldWithoutEcs) => { + const isEcsField = Boolean( + ecsFieldMap[requiredFieldWithoutEcs.name]?.type === requiredFieldWithoutEcs.type + ); + + return { + ...requiredFieldWithoutEcs, + ecs: isEcsField, + }; + }); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/utils/strip_non_ecs_fields.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/utils/strip_non_ecs_fields.ts index 86a3dc4ff6c1f..08e5fa5fd879d 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/utils/strip_non_ecs_fields.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/utils/strip_non_ecs_fields.ts @@ -67,9 +67,9 @@ const getIsEcsFieldObject = (path: string) => { /** * checks if path is in Ecs mapping */ -const getIsEcsField = (path: string) => { +export const getIsEcsField = (path: string): boolean => { const ecsField = ecsFieldMap[path as keyof typeof ecsFieldMap]; - const isEcsField = !!ecsField || ecsObjectFields[path]; + const isEcsField = Boolean(!!ecsField || ecsObjectFields[path]); return isEcsField; }; diff --git a/x-pack/plugins/security_solution/server/saved_objects.ts b/x-pack/plugins/security_solution/server/saved_objects.ts index 0b1fec5677488..3659b15a04714 100644 --- a/x-pack/plugins/security_solution/server/saved_objects.ts +++ b/x-pack/plugins/security_solution/server/saved_objects.ts @@ -13,7 +13,7 @@ import { noteType, pinnedEventType, timelineType } from './lib/timeline/saved_ob import { legacyType as legacyRuleActionsType } from './lib/detection_engine/rule_actions_legacy'; import { prebuiltRuleAssetType } from './lib/detection_engine/prebuilt_rules'; import { type as signalsMigrationType } from './lib/detection_engine/migrations/saved_objects'; -import { manifestType } from './endpoint/lib/artifacts/saved_object_mappings'; +import { manifestType, unifiedManifestType } from './endpoint/lib/artifacts/saved_object_mappings'; import { riskEngineConfigurationType } from './lib/entity_analytics/risk_engine/saved_object'; const types = [ @@ -23,6 +23,7 @@ const types = [ prebuiltRuleAssetType, timelineType, manifestType, + unifiedManifestType, signalsMigrationType, riskEngineConfigurationType, protectionUpdatesNoteType, diff --git a/x-pack/plugins/security_solution/tsconfig.json b/x-pack/plugins/security_solution/tsconfig.json index b5778dbf20e39..bb26581356fa1 100644 --- a/x-pack/plugins/security_solution/tsconfig.json +++ b/x-pack/plugins/security_solution/tsconfig.json @@ -200,6 +200,7 @@ "@kbn/security-plugin-types-server", "@kbn/deeplinks-security", "@kbn/react-kibana-context-render", - "@kbn/search-types" + "@kbn/search-types", + "@kbn/field-utils" ] } diff --git a/x-pack/plugins/serverless_search/public/application/components/index_management/api_empty_prompt.tsx b/x-pack/plugins/serverless_search/public/application/components/index_management/api_empty_prompt.tsx index 4881c8d73f40f..22643b9030747 100644 --- a/x-pack/plugins/serverless_search/public/application/components/index_management/api_empty_prompt.tsx +++ b/x-pack/plugins/serverless_search/public/application/components/index_management/api_empty_prompt.tsx @@ -26,6 +26,7 @@ import { CodeBox, getConsoleRequest, getLanguageDefinitionCodeSnippet, + IngestPipelinePanel, LanguageDefinition, LanguageDefinitionSnippetArguments, } from '@kbn/search-api-panels'; @@ -37,6 +38,10 @@ import { useKibanaServices } from '../../hooks/use_kibana'; import { javaDefinition } from '../languages/java'; import { languageDefinitions } from '../languages/languages'; import { LanguageGrid } from '../languages/language_grid'; + +import { useIngestPipelines } from '../../hooks/api/use_ingest_pipelines'; +import { DEFAULT_INGESTION_PIPELINE } from '../../constants'; + import { API_KEY_PLACEHOLDER, CLOUD_ID_PLACEHOLDER, @@ -55,6 +60,8 @@ export const APIIndexEmptyPrompt = ({ indexName, onBackClick }: APIIndexEmptyPro const assetBasePath = useAssetBasePath(); const [selectedLanguage, setSelectedLanguage] = React.useState(javaDefinition); + + const [selectedPipeline, setSelectedPipeline] = React.useState(''); const [clientApiKey, setClientApiKey] = useState(API_KEY_PLACEHOLDER); const { elasticsearchURL, cloudId } = useMemo(() => { return { @@ -67,8 +74,11 @@ export const APIIndexEmptyPrompt = ({ indexName, onBackClick }: APIIndexEmptyPro apiKey: clientApiKey, cloudId, indexName, + ingestPipeline: selectedPipeline, }; + const { data: pipelineData } = useIngestPipelines(); + const apiIngestSteps: EuiContainedStepProps[] = [ { title: i18n.translate( @@ -85,6 +95,14 @@ export const APIIndexEmptyPrompt = ({ indexName, onBackClick }: APIIndexEmptyPro selectedLanguage={selectedLanguage.id} /> + + + `curl -X POST "\$\{ES_URL\}/_bulk?pretty"${ + ingestPipeline ? `&pipeline=${ingestPipeline}` : '' + }" \\ -H "Authorization: ApiKey "\$\{API_KEY\}"" \\ -H "Content-Type: application/json" \\ -d' @@ -49,7 +51,13 @@ export API_KEY="${apiKey}"`, { "index" : { "_index" : "books" } } {"name": "The Handmaid'"'"'s Tale", "author": "Margaret Atwood", "release_date": "1985-06-01", "page_count": 311} '`, - ingestDataIndex: ({ apiKey, url, indexName }) => `curl -X POST ${url}/_bulk?pretty \\ + ingestDataIndex: ({ + apiKey, + indexName, + ingestPipeline, + }) => `curl -X POST "\$\{url\}/_bulk?pretty${ + ingestPipeline ? `&pipeline=${ingestPipeline}` : '' + }" \\ -H "Authorization: ApiKey ${apiKey}" \\ -H "Content-Type: application/json" \\ -d' diff --git a/x-pack/plugins/serverless_search/public/application/components/languages/dotnet.ts b/x-pack/plugins/serverless_search/public/application/components/languages/dotnet.ts index 1ac3641f67fe9..0d191f2b1e5b6 100644 --- a/x-pack/plugins/serverless_search/public/application/components/languages/dotnet.ts +++ b/x-pack/plugins/serverless_search/public/application/components/languages/dotnet.ts @@ -27,7 +27,7 @@ using Elastic.Clients.Elasticsearch.Serverless.QueryDsl; var client = new ElasticsearchClient("${cloudId}", new ApiKey("${apiKey}"));`, testConnection: `var info = await client.InfoAsync();`, - ingestData: `var doc = new Book + ingestData: ({ ingestPipeline }) => `var doc = new Book { Id = "9780553351927", Name = "Snow Crash", @@ -36,8 +36,10 @@ var client = new ElasticsearchClient("${cloudId}", new ApiKey("${apiKey}"));`, PageCount = 470 }; -var response = await client.IndexAsync(doc, "books");`, - ingestDataIndex: ({ apiKey, cloudId, indexName }) => `using System; +var response = await client.IndexAsync(doc, index: "books"${ + ingestPipeline ? `, x => x.Pipeline("${ingestPipeline}")` : '' + }));`, + ingestDataIndex: ({ apiKey, cloudId, indexName, ingestPipeline }) => `using System; using Elastic.Clients.Elasticsearch.Serverless; using Elastic.Clients.Elasticsearch.Serverless.QueryDsl; @@ -52,7 +54,9 @@ var doc = new Book PageCount = 470 }; -var response = await client.IndexAsync(doc, "${indexName}");`, +var response = await client.IndexAsync(doc, index: "${indexName}"${ + ingestPipeline ? `, x => x.Pipeline("${ingestPipeline}")` : '' + }));`, buildSearchQuery: `var response = await client.SearchAsync(s => s .Index("books") .From(0) diff --git a/x-pack/plugins/serverless_search/public/application/components/languages/go.ts b/x-pack/plugins/serverless_search/public/application/components/languages/go.ts index d92195ad6d82e..ea328f0c9ff6c 100644 --- a/x-pack/plugins/serverless_search/public/application/components/languages/go.ts +++ b/x-pack/plugins/serverless_search/public/application/components/languages/go.ts @@ -46,8 +46,8 @@ func main() { }, iconType: 'go.svg', id: Languages.GO, - ingestData: `ingestResult, err := es.Bulk(). - Index("books"). + ingestData: ({ ingestPipeline }) => `ingestResult, err := es.Bulk(). + Index("books").${ingestPipeline ? `\n Pipeline("${ingestPipeline}").` : ''} Raw(strings.NewReader(\` {"index":{"_id":"9780553351927"}} {"name":"Snow Crash","author":"Neal Stephenson","release_date":"1992-06-01","page_count": 470} @@ -64,7 +64,7 @@ func main() { Do(context.Background()) fmt.Println(ingestResult, err)`, - ingestDataIndex: ({ apiKey, url, indexName }) => `import ( + ingestDataIndex: ({ apiKey, url, indexName, ingestPipeline }) => `import ( "context" "fmt" "log" @@ -83,7 +83,7 @@ func main() { log.Fatalf("Error creating the client: %s", err) } res, err := es.Bulk(). - Index("${indexName}"). + Index("${indexName}").${ingestPipeline ? `\n Pipeline("${ingestPipeline}").` : ''} Raw(strings.NewReader(\` { "index": { "_id": "1"}} {"name": "foo", "title": "bar"}\n\`)). diff --git a/x-pack/plugins/serverless_search/public/application/components/languages/java.ts b/x-pack/plugins/serverless_search/public/application/components/languages/java.ts index c247eb978c15b..4d83be5bd4fca 100644 --- a/x-pack/plugins/serverless_search/public/application/components/languages/java.ts +++ b/x-pack/plugins/serverless_search/public/application/components/languages/java.ts @@ -44,7 +44,7 @@ ElasticsearchClient esClient = new ElasticsearchClient(transport);`, testConnection: `InfoResponse info = esClient.info(); logger.info(info.toString());`, - ingestData: `List books = new ArrayList<>(); + ingestData: ({ ingestPipeline }) => `List books = new ArrayList<>(); books.add(new Book("9780553351927", "Snow Crash", "Neal Stephenson", "1992-06-01", 470)); books.add(new Book("9780441017225", "Revelation Space", "Alastair Reynolds", "2000-03-15", 585)); books.add(new Book("9780451524935", "1984", "George Orwell", "1985-06-01", 328)); @@ -57,7 +57,7 @@ BulkRequest.Builder br = new BulkRequest.Builder(); for (Book book : books) { br.operations(op -> op .index(idx -> idx - .index("books") + .index("books")${ingestPipeline ? `\n .pipeline("${ingestPipeline}")` : ''} .id(product.getId()) .document(book) ) @@ -75,7 +75,7 @@ if (result.errors()) { } } }`, - ingestDataIndex: ({ apiKey, indexName, url }) => `// URL and API key + ingestDataIndex: ({ apiKey, indexName, url, ingestPipeline }) => `// URL and API key String serverUrl = "${url}"; String apiKey = "${apiKey}"; @@ -107,7 +107,9 @@ BulkRequest.Builder br = new BulkRequest.Builder(); for (Book book : books) { br.operations(op -> op .index(idx -> idx - .index("${indexName}") + .index("${indexName}")${ + ingestPipeline ? `\n .pipeline("${ingestPipeline}")` : '' + } .id(product.getId()) .document(book) ) diff --git a/x-pack/plugins/serverless_search/public/application/components/languages/javascript.ts b/x-pack/plugins/serverless_search/public/application/components/languages/javascript.ts index 72d865f1030bc..aefd1c71f467d 100644 --- a/x-pack/plugins/serverless_search/public/application/components/languages/javascript.ts +++ b/x-pack/plugins/serverless_search/public/application/components/languages/javascript.ts @@ -39,7 +39,7 @@ const client = new Client({ }, iconType: 'javascript.svg', id: Languages.JAVASCRIPT, - ingestData: `// Sample books data + ingestData: ({ ingestPipeline }) => `// Sample books data const dataset = [ {"name": "Snow Crash", "author": "Neal Stephenson", "release_date": "1992-06-01", "page_count": 470}, {"name": "Revelation Space", "author": "Alastair Reynolds", "release_date": "2000-03-15", "page_count": 585}, @@ -51,7 +51,7 @@ const dataset = [ // Index with the bulk helper const result = await client.helpers.bulk({ - datasource: dataset, + datasource: dataset,${ingestPipeline ? `\n pipeline: "${ingestPipeline}",` : ''} onDocument (doc) { return { index: { _index: 'my-index-name' }}; } @@ -74,6 +74,7 @@ console.log(result); apiKey, url, indexName, + ingestPipeline, }) => `const { Client } = require('@elastic/elasticsearch-serverless'); const client = new Client({ node: '${url}', @@ -87,7 +88,7 @@ const dataset = [ // Index with the bulk helper const result = await client.helpers.bulk({ - datasource: dataset, + datasource: dataset,${ingestPipeline ? `\n pipeline: "${ingestPipeline}",` : ''} onDocument (doc) { return { index: { _index: '${indexName ?? 'index_name'}' }}; } diff --git a/x-pack/plugins/serverless_search/public/application/components/languages/php.ts b/x-pack/plugins/serverless_search/public/application/components/languages/php.ts index 0a7dbe5758dd9..c156165683a6a 100644 --- a/x-pack/plugins/serverless_search/public/application/components/languages/php.ts +++ b/x-pack/plugins/serverless_search/public/application/components/languages/php.ts @@ -29,7 +29,10 @@ export const phpDefinition: LanguageDefinition = { }, iconType: 'php.svg', id: Languages.PHP, - ingestData: `$body = [ + ingestData: ({ ingestPipeline }) => `$params =[${ + ingestPipeline ? `\n 'pipeline' => '${ingestPipeline}',` : '' + } + 'body' => [ [ "index" => [ "_index" => "books" ]], [ "name" => "Snow Crash", "author" => "Neal Stephenson", "release_date" => "1992-06-01", "page_count" => 470], [ "index" => [ "_index" => "books" ]], @@ -42,22 +45,27 @@ export const phpDefinition: LanguageDefinition = { [ "name" => "Brave New World", "author" => "Aldous Huxley", "release_date" => "1932-06-01", "page_count" => 268], [ "index" => [ "_index" => "books" ]], [ "name" => "The Handmaid's Tale", "author" => "Margaret Atwood", "release_date" => "1985-06-01", "page_count" => 311] -]; +]]; -$response = $client->bulk(body: $body); +$response = $client->bulk($params); echo $response->getStatusCode(); echo (string) $response->getBody();`, - ingestDataIndex: ({ apiKey, url, indexName }) => `$client = ClientBuilder::create() + ingestDataIndex: ({ + apiKey, + url, + indexName, + ingestPipeline, + }) => `$client = ClientBuilder::create() ->setEndpoint('${url}') ->setApiKey('${apiKey}') ->build(); +$params =[${ingestPipeline ? `\n 'pipeline' => '${ingestPipeline}',` : ''} + 'body' => [ + [ 'index' => [ '_index' => '${indexName ?? INDEX_NAME_PLACEHOLDER}', '_id' => '1' ]], + [ 'name' => 'foo', 'title' => 'bar' ] +]]; -$body = [ - [ 'index' => [ '_index' => '${indexName ?? INDEX_NAME_PLACEHOLDER}', '_id' => '1' ]], - [ 'name' => 'foo', 'title' => 'bar' ] -]; - -$response = $client->bulk(body: $body); +$response = $client->bulk($params); echo $response->getStatusCode(); echo (string) $response->getBody(); `, diff --git a/x-pack/plugins/serverless_search/public/application/components/languages/python.ts b/x-pack/plugins/serverless_search/public/application/components/languages/python.ts index dbed5f124e617..266a28b12c181 100644 --- a/x-pack/plugins/serverless_search/public/application/components/languages/python.ts +++ b/x-pack/plugins/serverless_search/public/application/components/languages/python.ts @@ -29,7 +29,7 @@ client = Elasticsearch( }, iconType: 'python.svg', id: Languages.PYTHON, - ingestData: `documents = [ + ingestData: ({ ingestPipeline }) => `documents = [ { "index": { "_index": "books", "_id": "9780553351927"}}, {"name": "Snow Crash", "author": "Neal Stephenson", "release_date": "1992-06-01", "page_count": 470}, { "index": { "_index": "books", "_id": "9780441017225"}}, @@ -44,11 +44,12 @@ client = Elasticsearch( {"name": "The Handmaid's Tale", "author": "Margaret Atwood", "release_date": "1985-06-01", "page_count": 311}, ] -client.bulk(operations=documents)`, +client.bulk(operations=documents${ingestPipeline ? `, pipeline="${ingestPipeline}"` : ''})`, ingestDataIndex: ({ apiKey, url, indexName, + ingestPipeline, }) => `from elasticsearch_serverless import Elasticsearch client = Elasticsearch( @@ -61,7 +62,7 @@ documents = [ {"name": "foo", "title": "bar"}, ] -client.bulk(operations=documents) +client.bulk(operations=documents${ingestPipeline ? `, pipeline="${ingestPipeline}"` : ''}) `, installClient: `python -m pip install elasticsearch-serverless diff --git a/x-pack/plugins/serverless_search/public/application/components/languages/ruby.ts b/x-pack/plugins/serverless_search/public/application/components/languages/ruby.ts index f0553b5d7ec76..19b926878024d 100644 --- a/x-pack/plugins/serverless_search/public/application/components/languages/ruby.ts +++ b/x-pack/plugins/serverless_search/public/application/components/languages/ruby.ts @@ -28,7 +28,7 @@ export const rubyDefinition: LanguageDefinition = { }, iconType: 'ruby.svg', id: Languages.RUBY, - ingestData: `documents = [ + ingestData: ({ ingestPipeline }) => `documents = [ { index: { _index: 'books', data: {name: "Snow Crash", "author": "Neal Stephenson", "release_date": "1992-06-01", "page_count": 470} } }, { index: { _index: 'books', data: {name: "Revelation Space", "author": "Alastair Reynolds", "release_date": "2000-03-15", "page_count": 585} } }, { index: { _index: 'books', data: {name: "1984", "author": "George Orwell", "release_date": "1985-06-01", "page_count": 328} } }, @@ -36,8 +36,13 @@ export const rubyDefinition: LanguageDefinition = { { index: { _index: 'books', data: {name: "Brave New World", "author": "Aldous Huxley", "release_date": "1932-06-01", "page_count": 268} } }, { index: { _index: 'books', data: {name: "The Handmaid's Tale", "author": "Margaret Atwood", "release_date": "1985-06-01", "page_count": 311} } } ] -client.bulk(body: documents)`, - ingestDataIndex: ({ apiKey, url, indexName }) => `client = ElasticsearchServerless::Client.new( +client.bulk(body: documents${ingestPipeline ? `, pipeline: "${ingestPipeline}"` : ''})`, + ingestDataIndex: ({ + apiKey, + url, + indexName, + ingestPipeline, + }) => `client = ElasticsearchServerless::Client.new( api_key: '${apiKey}', url: '${url}' ) @@ -47,7 +52,7 @@ documents = [ indexName ?? INDEX_NAME_PLACEHOLDER }', data: {name: "foo", "title": "bar"} } }, ] -client.bulk(body: documents) +client.bulk(body: documents${ingestPipeline ? `, pipeline: "${ingestPipeline}"` : ''}) `, installClient: `# Requires Ruby version 3.0 or higher diff --git a/x-pack/plugins/serverless_search/public/application/components/overview.tsx b/x-pack/plugins/serverless_search/public/application/components/overview.tsx index 318bcc0b13125..2a5beea0ef2e3 100644 --- a/x-pack/plugins/serverless_search/public/application/components/overview.tsx +++ b/x-pack/plugins/serverless_search/public/application/components/overview.tsx @@ -44,6 +44,7 @@ import { API_KEY_PLACEHOLDER, CLOUD_ID_PLACEHOLDER, ELASTICSEARCH_URL_PLACEHOLDER, + DEFAULT_INGESTION_PIPELINE, } from '../constants'; import { javaDefinition } from './languages/java'; import { languageDefinitions } from './languages/languages'; @@ -55,6 +56,7 @@ import { PipelineOverviewButton } from './pipeline_overview_button'; import { SelectClientCallouts } from './select_client_callouts'; import { PipelineManageButton } from './pipeline_manage_button'; import { OPTIONAL_LABEL } from '../../../common/i18n_string'; +import { useIngestPipelines } from '../hooks/api/use_ingest_pipelines'; export const ElasticsearchOverview = () => { const [selectedLanguage, setSelectedLanguage] = useState(javaDefinition); @@ -82,13 +84,17 @@ export const ElasticsearchOverview = () => { () => (consolePlugin?.EmbeddableConsole ? : null), [consolePlugin] ); + const [selectedPipeline, setSelectedPipeline] = React.useState(''); const codeSnippetArguments: LanguageDefinitionSnippetArguments = { url: elasticsearchURL, apiKey: clientApiKey, cloudId, + ingestPipeline: selectedPipeline, }; + const { data: pipelineData } = useIngestPipelines(); + return ( @@ -302,7 +308,8 @@ export const ElasticsearchOverview = () => { 'ingestData', codeSnippetArguments )} - consoleRequest={getConsoleRequest('ingestData')} + ingestPipelineData={pipelineData?.pipelines} + consoleRequest={getConsoleRequest('ingestData', codeSnippetArguments)} languages={languageDefinitions} selectedLanguage={selectedLanguage} setSelectedLanguage={setSelectedLanguage} @@ -312,6 +319,9 @@ export const ElasticsearchOverview = () => { consolePlugin={consolePlugin} sharePlugin={share} additionalIngestionPanel={} + selectedPipeline={selectedPipeline} + setSelectedPipeline={setSelectedPipeline} + defaultIngestPipeline={DEFAULT_INGESTION_PIPELINE} /> { + const { http } = useKibanaServices(); + return useQuery({ + queryKey: ['fetchIngestPipelines'], + queryFn: async () => + http.fetch>( + `/internal/serverless_search/ingest_pipelines/` + ), + }); +}; diff --git a/x-pack/plugins/serverless_search/server/plugin.ts b/x-pack/plugins/serverless_search/server/plugin.ts index 0601b099d8a0d..8963a3c78f917 100644 --- a/x-pack/plugins/serverless_search/server/plugin.ts +++ b/x-pack/plugins/serverless_search/server/plugin.ts @@ -29,6 +29,7 @@ import type { import { registerConnectorsRoutes } from './routes/connectors_routes'; import { registerTelemetryUsageCollector } from './collectors/connectors/telemetry'; import { registerMappingRoutes } from './routes/mapping_routes'; +import { registerIngestPipelineRoutes } from './routes/ingest_pipeline_routes'; export interface RouteDependencies { http: CoreSetup['http']; @@ -95,6 +96,7 @@ export class ServerlessSearchPlugin registerConnectorsRoutes(dependencies); registerIndicesRoutes(dependencies); registerMappingRoutes(dependencies); + registerIngestPipelineRoutes(dependencies); if (usageCollection) { registerTelemetryUsageCollector(usageCollection, this.logger); diff --git a/x-pack/plugins/serverless_search/server/routes/ingest_pipeline_routes.ts b/x-pack/plugins/serverless_search/server/routes/ingest_pipeline_routes.ts new file mode 100644 index 0000000000000..4a2720c8712d9 --- /dev/null +++ b/x-pack/plugins/serverless_search/server/routes/ingest_pipeline_routes.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 { RouteDependencies } from '../plugin'; + +export const registerIngestPipelineRoutes = ({ router }: RouteDependencies) => { + router.get( + { + path: '/internal/serverless_search/ingest_pipelines/', + validate: {}, + }, + async (context, request, response) => { + const { client } = (await context.core).elasticsearch; + const pipelines = await client.asCurrentUser.ingest.getPipeline(); + + return response.ok({ + body: { + pipelines, + }, + headers: { 'content-type': 'application/json' }, + }); + } + ); +}; diff --git a/x-pack/plugins/stack_connectors/server/connector_types/cases_webhook/service.test.ts b/x-pack/plugins/stack_connectors/server/connector_types/cases_webhook/service.test.ts index 4598e8471a838..1e7b492ada959 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/cases_webhook/service.test.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/cases_webhook/service.test.ts @@ -13,6 +13,7 @@ import { CasesWebhookMethods, CasesWebhookPublicConfigurationType, ExternalServi import { Logger } from '@kbn/core/server'; import { loggingSystemMock } from '@kbn/core/server/mocks'; import { actionsConfigMock } from '@kbn/actions-plugin/server/actions_config.mock'; +import { getBasicAuthHeader } from '@kbn/actions-plugin/server/lib'; const logger = loggingSystemMock.create().get() as jest.Mocked; jest.mock('@kbn/actions-plugin/server/lib/axios_utils', () => { @@ -124,6 +125,43 @@ describe('Cases webhook service', () => { ) ).not.toThrow(); }); + + test('uses the basic auth header for authentication', () => { + createExternalService( + actionId, + { + config, + secrets: { user: 'username', password: 'password' }, + }, + logger, + configurationUtilities + ); + + expect(axios.create).toHaveBeenCalledWith({ + headers: { + ...getBasicAuthHeader({ username: 'username', password: 'password' }), + 'content-type': 'application/json', + }, + }); + }); + + test('does not add the basic auth header for authentication if hasAuth=false', () => { + createExternalService( + actionId, + { + config: { ...config, hasAuth: false }, + secrets: { user: 'username', password: 'password' }, + }, + logger, + configurationUtilities + ); + + expect(axios.create).toHaveBeenCalledWith({ + headers: { + 'content-type': 'application/json', + }, + }); + }); }); describe('getIncident', () => { diff --git a/x-pack/plugins/stack_connectors/server/connector_types/cases_webhook/service.ts b/x-pack/plugins/stack_connectors/server/connector_types/cases_webhook/service.ts index dd0b28d321a60..46407c18bd081 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/cases_webhook/service.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/cases_webhook/service.ts @@ -8,10 +8,10 @@ import axios, { AxiosResponse } from 'axios'; import { Logger } from '@kbn/core/server'; -import { isString } from 'lodash'; import { renderMustacheStringNoEscape } from '@kbn/actions-plugin/server/lib/mustache_renderer'; import { request } from '@kbn/actions-plugin/server/lib/axios_utils'; import { ActionsConfigurationUtilities } from '@kbn/actions-plugin/server/actions_config'; +import { combineHeadersWithBasicAuthHeader } from '@kbn/actions-plugin/server/lib'; import { validateAndNormalizeUrl, validateJson } from './validators'; import { createServiceError, @@ -69,14 +69,18 @@ export const createExternalService = ( } const createIncidentUrl = removeSlash(createIncidentUrlConfig); + const headersWithBasicAuth = hasAuth + ? combineHeadersWithBasicAuthHeader({ + username: user ?? undefined, + password: password ?? undefined, + headers, + }) + : {}; const axiosInstance = axios.create({ - ...(hasAuth && isString(secrets.user) && isString(secrets.password) - ? { auth: { username: secrets.user, password: secrets.password } } - : {}), headers: { ['content-type']: 'application/json', - ...(headers != null ? headers : {}), + ...headersWithBasicAuth, }, }); diff --git a/x-pack/plugins/stack_connectors/server/connector_types/jira/service.test.ts b/x-pack/plugins/stack_connectors/server/connector_types/jira/service.test.ts index f6b4dcf909abe..34e0f1f799ce5 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/jira/service.test.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/jira/service.test.ts @@ -13,6 +13,7 @@ import { ExternalService } from './types'; import { Logger } from '@kbn/core/server'; import { loggingSystemMock } from '@kbn/core/server/mocks'; import { actionsConfigMock } from '@kbn/actions-plugin/server/actions_config.mock'; +import { getBasicAuthHeader } from '@kbn/actions-plugin/server'; const logger = loggingSystemMock.create().get() as jest.Mocked; interface ResponseError extends Error { @@ -204,6 +205,21 @@ describe('Jira service', () => { ) ).toThrow(); }); + + test('uses the basic auth header for authentication', () => { + createExternalService( + { + config: { apiUrl: 'https://coolsite.net/', projectKey: 'CK' }, + secrets: { apiToken: 'token', email: 'elastic@elastic.com' }, + }, + logger, + configurationUtilities + ); + + expect(axios.create).toHaveBeenCalledWith({ + headers: getBasicAuthHeader({ username: 'elastic@elastic.com', password: 'token' }), + }); + }); }); describe('getIncident', () => { diff --git a/x-pack/plugins/stack_connectors/server/connector_types/jira/service.ts b/x-pack/plugins/stack_connectors/server/connector_types/jira/service.ts index f0ad0e3062ccc..3cd5115234da1 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/jira/service.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/jira/service.ts @@ -15,6 +15,7 @@ import { throwIfResponseIsNotValid, } from '@kbn/actions-plugin/server/lib/axios_utils'; import { ActionsConfigurationUtilities } from '@kbn/actions-plugin/server/actions_config'; +import { getBasicAuthHeader } from '@kbn/actions-plugin/server'; import { CreateCommentParams, CreateIncidentParams, @@ -66,7 +67,7 @@ export const createExternalService = ( const searchUrl = `${urlWithoutTrailingSlash}/${BASE_URL}/search`; const axiosInstance = axios.create({ - auth: { username: email, password: apiToken }, + headers: getBasicAuthHeader({ username: email, password: apiToken }), }); const getIncidentViewURL = (key: string) => { diff --git a/x-pack/plugins/stack_connectors/server/connector_types/lib/servicenow/utils.test.ts b/x-pack/plugins/stack_connectors/server/connector_types/lib/servicenow/utils.test.ts index f151affe8a597..8bc9fa0565d8f 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/lib/servicenow/utils.test.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/lib/servicenow/utils.test.ts @@ -20,6 +20,7 @@ import type { ResponseError } from './types'; import { connectorTokenClientMock } from '@kbn/actions-plugin/server/lib/connector_token_client.mock'; import { actionsConfigMock } from '@kbn/actions-plugin/server/actions_config.mock'; import { getOAuthJwtAccessToken } from '@kbn/actions-plugin/server/lib/get_oauth_jwt_access_token'; +import { getBasicAuthHeader } from '@kbn/actions-plugin/server'; jest.mock('@kbn/actions-plugin/server/lib/get_oauth_jwt_access_token', () => ({ getOAuthJwtAccessToken: jest.fn(), @@ -189,7 +190,7 @@ describe('utils', () => { expect(createAxiosInstanceMock).toHaveBeenCalledTimes(1); expect(createAxiosInstanceMock).toHaveBeenCalledWith({ - auth: { password: 'password', username: 'username' }, + headers: getBasicAuthHeader({ username: 'username', password: 'password' }), }); }); diff --git a/x-pack/plugins/stack_connectors/server/connector_types/lib/servicenow/utils.ts b/x-pack/plugins/stack_connectors/server/connector_types/lib/servicenow/utils.ts index 44171d1a11947..8998fa9f94c63 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/lib/servicenow/utils.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/lib/servicenow/utils.ts @@ -11,6 +11,7 @@ import { addTimeZoneToDate, getErrorMessage } from '@kbn/actions-plugin/server/l import { ActionsConfigurationUtilities } from '@kbn/actions-plugin/server/actions_config'; import { ConnectorTokenClientContract } from '@kbn/actions-plugin/server/types'; import { getOAuthJwtAccessToken } from '@kbn/actions-plugin/server/lib/get_oauth_jwt_access_token'; +import { getBasicAuthHeader } from '@kbn/actions-plugin/server'; import { ExternalServiceCredentials, Incident, @@ -115,7 +116,7 @@ export const getAxiosInstance = ({ if (!isOAuth && username && password) { axiosInstance = axios.create({ - auth: { username, password }, + headers: getBasicAuthHeader({ username, password }), }); } else { axiosInstance = axios.create(); diff --git a/x-pack/plugins/stack_connectors/server/connector_types/resilient/resilient.ts b/x-pack/plugins/stack_connectors/server/connector_types/resilient/resilient.ts index 4c8175e52ab8f..1351488dbf892 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/resilient/resilient.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/resilient/resilient.ts @@ -7,7 +7,7 @@ import { AxiosError } from 'axios'; import { omitBy, isNil } from 'lodash/fp'; -import { CaseConnector, ServiceParams } from '@kbn/actions-plugin/server'; +import { CaseConnector, getBasicAuthHeader, ServiceParams } from '@kbn/actions-plugin/server'; import { schema, Type } from '@kbn/config-schema'; import { getErrorMessage } from '@kbn/actions-plugin/server/lib/axios_utils'; import { @@ -96,12 +96,10 @@ export class ResilientConnector extends CaseConnector< } private getAuthHeaders() { - const token = Buffer.from( - this.secrets.apiKeyId + ':' + this.secrets.apiKeySecret, - 'utf8' - ).toString('base64'); - - return { Authorization: `Basic ${token}` }; + return getBasicAuthHeader({ + username: this.secrets.apiKeyId, + password: this.secrets.apiKeySecret, + }); } private getOrgUrl() { diff --git a/x-pack/plugins/stack_connectors/server/connector_types/webhook/index.test.ts b/x-pack/plugins/stack_connectors/server/connector_types/webhook/index.test.ts index bd24314fa79b7..9e82b2d2c31e7 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/webhook/index.test.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/webhook/index.test.ts @@ -348,13 +348,10 @@ describe('execute()', () => { delete requestMock.mock.calls[0][0].configurationUtilities; expect(requestMock.mock.calls[0][0]).toMatchInlineSnapshot(` Object { - "auth": Object { - "password": "123", - "username": "abc", - }, "axios": undefined, "data": "some data", "headers": Object { + "Authorization": "Basic YWJjOjEyMw==", "aheader": "a value", }, "logger": Object { diff --git a/x-pack/plugins/stack_connectors/server/connector_types/webhook/index.ts b/x-pack/plugins/stack_connectors/server/connector_types/webhook/index.ts index b71c478177178..a3383ee844016 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/webhook/index.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/webhook/index.ts @@ -25,6 +25,7 @@ import { SecurityConnectorFeatureId, } from '@kbn/actions-plugin/common/types'; import { renderMustacheString } from '@kbn/actions-plugin/server/lib/mustache_renderer'; +import { combineHeadersWithBasicAuthHeader } from '@kbn/actions-plugin/server/lib'; import { SSLCertType, WebhookAuthType } from '../../../common/webhook/constants'; import { getRetryAfterIntervalFromHeaders } from '../lib/http_response_retry_header'; import { nullableType } from '../lib/nullable'; @@ -210,6 +211,7 @@ export async function executor( isString(secrets.password) ? { auth: { username: secrets.user, password: secrets.password } } : {}; + const sslCertificate = authType === WebhookAuthType.SSL && ((isString(secrets.crt) && isString(secrets.key)) || isString(secrets.pfx)) @@ -233,14 +235,19 @@ export async function executor( ...(ca ? { ca: Buffer.from(ca, 'base64') } : {}), }; + const headersWithBasicAuth = combineHeadersWithBasicAuthHeader({ + username: basicAuth.auth?.username, + password: basicAuth.auth?.password, + headers, + }); + const result: Result> = await promiseResult( request({ axios: axiosInstance, method, url, logger, - ...basicAuth, - headers: headers ? headers : {}, + headers: headersWithBasicAuth, data, configurationUtilities, sslOverrides, diff --git a/x-pack/plugins/stack_connectors/server/connector_types/xmatters/index.test.ts b/x-pack/plugins/stack_connectors/server/connector_types/xmatters/index.test.ts index f39f510282984..23f7a01887126 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/xmatters/index.test.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/xmatters/index.test.ts @@ -5,11 +5,7 @@ * 2.0. */ -jest.mock('./post_xmatters', () => ({ - postXmatters: jest.fn(), -})); -import { postXmatters } from './post_xmatters'; - +import axios from 'axios'; import { Logger } from '@kbn/core/server'; import { ConnectorTypeConfigType, @@ -28,8 +24,22 @@ import { import { actionsConfigMock } from '@kbn/actions-plugin/server/actions_config.mock'; import { ActionsConfigurationUtilities } from '@kbn/actions-plugin/server/actions_config'; import { loggerMock } from '@kbn/logging-mocks'; +import * as utils from '@kbn/actions-plugin/server/lib/axios_utils'; + +jest.mock('axios'); +jest.mock('@kbn/actions-plugin/server/lib/axios_utils', () => { + const originalUtils = jest.requireActual('@kbn/actions-plugin/server/lib/axios_utils'); + return { + ...originalUtils, + request: jest.fn(), + patch: jest.fn(), + }; +}); + +axios.create = jest.fn(() => axios); +const requestMock = utils.request as jest.Mock; +axios.create = jest.fn(() => axios); -const postxMattersMock = postXmatters as jest.Mock; const services: Services = actionsMock.createServices(); const mockedLogger: jest.Mocked = loggerMock.create(); @@ -383,8 +393,8 @@ describe('connector validation', () => { describe('execute()', () => { beforeEach(() => { - postxMattersMock.mockReset(); - postxMattersMock.mockResolvedValue({ + requestMock.mockReset(); + requestMock.mockResolvedValue({ status: 200, statusText: '', data: '', @@ -415,14 +425,10 @@ describe('execute()', () => { logger: mockedLogger, }); - expect(postxMattersMock.mock.calls[0][0]).toMatchInlineSnapshot(` + const { method, url, headers, data } = requestMock.mock.calls[0][0]; + + expect({ method, url, headers, data }).toMatchInlineSnapshot(` Object { - "basicAuth": Object { - "auth": Object { - "password": "123", - "username": "abc", - }, - }, "data": Object { "alertActionGroupName": "Small t-shirt", "date": "2022-01-18T19:01:08.818Z", @@ -432,6 +438,10 @@ describe('execute()', () => { "spaceId": "default", "tags": "test1, test2", }, + "headers": Object { + "Authorization": "Basic YWJjOjEyMw==", + }, + "method": "post", "url": "https://abc.def/my-xmatters", } `); @@ -442,7 +452,7 @@ describe('execute()', () => { configUrl: 'https://abc.def/my-xmatters', usesBasic: true, }; - postxMattersMock.mockRejectedValueOnce({ + requestMock.mockRejectedValueOnce({ tag: 'err', message: 'maxContentLength size of 1000000 exceeded', }); @@ -496,9 +506,10 @@ describe('execute()', () => { logger: mockedLogger, }); - expect(postxMattersMock.mock.calls[0][0]).toMatchInlineSnapshot(` + const { method, url, headers, data } = requestMock.mock.calls[0][0]; + + expect({ method, url, headers, data }).toMatchInlineSnapshot(` Object { - "basicAuth": undefined, "data": Object { "alertActionGroupName": "Small t-shirt", "date": "2022-01-18T19:01:08.818Z", @@ -508,6 +519,8 @@ describe('execute()', () => { "spaceId": "default", "tags": "test1, test2", }, + "headers": undefined, + "method": "post", "url": "https://abc.def/my-xmatters?apiKey=someKey", } `); diff --git a/x-pack/plugins/stack_connectors/server/connector_types/xmatters/post_xmatters.ts b/x-pack/plugins/stack_connectors/server/connector_types/xmatters/post_xmatters.ts index 1fcec5a4238f7..2c2a08901cec3 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/xmatters/post_xmatters.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/xmatters/post_xmatters.ts @@ -9,6 +9,7 @@ import axios, { AxiosResponse } from 'axios'; import { Logger } from '@kbn/core/server'; import { ActionsConfigurationUtilities } from '@kbn/actions-plugin/server/actions_config'; import { request } from '@kbn/actions-plugin/server/lib/axios_utils'; +import { combineHeadersWithBasicAuthHeader } from '@kbn/actions-plugin/server/lib'; interface PostXmattersOptions { url: string; @@ -42,7 +43,10 @@ export async function postXmatters( method: 'post', url, logger, - ...basicAuth, + headers: combineHeadersWithBasicAuthHeader({ + username: basicAuth?.auth.username, + password: basicAuth?.auth.password, + }), data, configurationUtilities, validateStatus: () => true, diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json index 2cc9d3cb58a3f..48ab3c8c34bc2 100644 --- a/x-pack/plugins/translations/translations/fr-FR.json +++ b/x-pack/plugins/translations/translations/fr-FR.json @@ -13933,7 +13933,6 @@ "xpack.enterpriseSearch.crawler.deleteDomainModal.description": "Supprimer le domaine {domainUrl} de votre robot d'indexation. Cela supprimera également tous les points d'entrée et toutes les règles d'indexation que vous avez configurés. Tous les documents associés à ce domaine seront supprimés lors de la prochaine indexation. {thisCannotBeUndoneMessage}", "xpack.enterpriseSearch.crawler.entryPointsTable.emptyMessageDescription": "{link} pour spécifier un point d'entrée pour le robot d'indexation", "xpack.enterpriseSearch.deleteConnectorModal.li.myconnectornameRelatedIndexLabel": "{connectorName} (Index associé : {deleteModalIndexName})", - "xpack.enterpriseSearch.endpointsHeader.apiKey.activeKeys": "{number} clés d'API actives", "xpack.enterpriseSearch.errorConnectingState.cloudErrorMessage": "Les nœuds Enterprise Search fonctionnent-ils dans votre déploiement cloud ? {deploymentSettingsLink}", "xpack.enterpriseSearch.errorConnectingState.description1": "Impossible d'établir une connexion à Enterprise Search avec l'URL hôte {enterpriseSearchUrl} en raison de l'erreur suivante :", "xpack.enterpriseSearch.errorConnectingState.description2": "Vérifiez que l'URL hôte est correctement configurée dans {configFile}.", @@ -16150,12 +16149,7 @@ "xpack.enterpriseSearch.overview.gettingStarted.testConnection.description": "Envoyez une requête de test pour confirmer que votre client de langage et votre instance Elasticsearch sont opérationnels.", "xpack.enterpriseSearch.overview.gettingStarted.testConnection.title": "Tester votre connexion", "xpack.enterpriseSearch.overview.navTitle": "Aperçu", - "xpack.enterpriseSearch.overview.pageTemplate.apiKey.copyApiEndpoint": "Copier le point de terminaison Elasticsearch dans le presse-papiers", "xpack.enterpriseSearch.overview.setupCta.description": "Ajoutez des fonctions de recherche à votre application ou à votre organisation interne avec Elastic App Search et Workplace Search. Regardez la vidéo pour savoir ce qu'il est possible de faire lorsque la recherche est facilitée.", - "xpack.enterpriseSearch.pageTemplate.apiKey.copied": "Copié", - "xpack.enterpriseSearch.pageTemplate.apiKey.elasticsearchEndpoint": "Point de terminaison Elasticsearch :", - "xpack.enterpriseSearch.pageTemplate.apiKey.manageLabel": "Gérer", - "xpack.enterpriseSearch.pageTemplate.apiKey.newButtonLabel": "Nouvelle clé d'API", "xpack.enterpriseSearch.pageTemplate.endpointsButtonLabel": "Points de terminaison et clés d'API", "xpack.enterpriseSearch.passwordLabel": "Mot de passe", "xpack.enterpriseSearch.pipeline.title": "Transformer et enrichir vos données", @@ -21088,10 +21082,8 @@ "xpack.infra.assetDetails.tabs.metadata.seeLess": "Afficher moins", "xpack.infra.assetDetails.tabs.metadata.seeMore": "+{count} de plus", "xpack.infra.assetDetails.tabs.metadata": "Métadonnées", - "xpack.infra.assetDetails.tabs.osquery": "Osquery", "xpack.infra.assetDetails.tabs.overview": "Aperçu", "xpack.infra.assetDetails.tabs.processes": "Processus", - "xpack.infra.assetDetails.tabs.profiling": "Universal Profiling", "xpack.infra.homePage.toolbar.showingLastOneMinuteDataText": "Dernières {duration} de données pour l'heure sélectionnée", "xpack.infra.hostsViewPage.errorOnCreateOrLoadDataview": "Une erreur s'est produite lors de la création d'une vue de données : {metricAlias}. Essayez de recharger la page.", "xpack.infra.hostsViewPage.kpi.subtitle.average.limit": "Moyenne (de {limit} hôtes)", @@ -24100,7 +24092,6 @@ "xpack.logsExplorer.dataTable.header.popover.resource": "Ressource", "xpack.logsExplorer.dataTable.header.resource.tooltip.paragraph": "Les champs fournissant des informations sur la source du document, comme :", "xpack.logsExplorer.flyoutDetail.title": "Détails du log", - "xpack.logsExplorer.grid.closePopover": "Fermer la fenêtre contextuelle", "xpack.logsExplorer.popoverAction.closePopover": "Fermer la fenêtre contextuelle", "xpack.logsExplorer.popoverAction.copyValue": "Copier la valeur", "xpack.logsExplorer.popoverAction.filterFor": "Filtrer sur", @@ -44919,7 +44910,6 @@ "xpack.features.savedQueryManagementFeatureName": "Gestion des requêtes enregistrées", "xpack.features.savedQueryManagementTooltip": "Si \"All\" (Tout) est défini, les requêtes enregistrées peuvent être gérées grâce à Kibana dans toutes les applications compatibles. Si \"None\" est défini, les privilèges relatifs aux requêtes enregistrées sont fixés indépendamment pour chaque application.", "xpack.features.visualizeFeatureName": "Bibliothèque Visualize", - "xpack.metricsData.assetDetails.formulas.cpuUsage": "Utilisation CPU", "xpack.metricsData.assetDetails.formulas.cpuUsage.iowaitLabel": "iowait", "xpack.metricsData.assetDetails.formulas.cpuUsage.irqLabel": "irq", "xpack.metricsData.assetDetails.formulas.cpuUsage.niceLabel": "nice", @@ -44927,45 +44917,25 @@ "xpack.metricsData.assetDetails.formulas.cpuUsage.stealLabel": "steal", "xpack.metricsData.assetDetails.formulas.cpuUsage.systemLabel": "system", "xpack.metricsData.assetDetails.formulas.cpuUsage.userLabel": "utilisateur", - "xpack.metricsData.assetDetails.formulas.diskIORead": "Entrées et sorties par seconde en lecture sur le disque", - "xpack.metricsData.assetDetails.formulas.diskIOWrite": "Entrées et sorties par seconde en écriture sur le disque", - "xpack.metricsData.assetDetails.formulas.diskReadThroughput": "Rendement de lecture du disque", - "xpack.metricsData.assetDetails.formulas.diskSpaceAvailability": "Disponibilité de l'espace disque", - "xpack.metricsData.assetDetails.formulas.diskSpaceAvailable": "Espace disque disponible", - "xpack.metricsData.assetDetails.formulas.diskUsage": "Utilisation du disque", - "xpack.metricsData.assetDetails.formulas.diskWriteThroughput": "Rendement d’écriture du disque", "xpack.metricsData.assetDetails.formulas.hostCount.hostsLabel": "Hôtes", "xpack.metricsData.assetDetails.formulas.kubernetes.capacity": "Capacité", "xpack.metricsData.assetDetails.formulas.kubernetes.used": "Utilisé", - "xpack.metricsData.assetDetails.formulas.load15m": "Charge (15 min)", - "xpack.metricsData.assetDetails.formulas.load1m": "Charge (1 min)", - "xpack.metricsData.assetDetails.formulas.load5m": "Charge (5 min)", "xpack.metricsData.assetDetails.formulas.logRate": "Taux de log", - "xpack.metricsData.assetDetails.formulas.memoryFree": "Sans mémoire", - "xpack.metricsData.assetDetails.formulas.memoryUsage": "Utilisation mémoire", "xpack.metricsData.assetDetails.formulas.metric.label.cache": "cache", "xpack.metricsData.assetDetails.formulas.metric.label.free": "gratuit", "xpack.metricsData.assetDetails.formulas.metric.label.used": "utilisé", - "xpack.metricsData.assetDetails.formulas.normalizedLoad1m": "Charge normalisée", "xpack.metricsData.assetDetails.formulas.rx": "Réseau entrant (RX)", "xpack.metricsData.assetDetails.formulas.tx": "Réseau sortant (TX)", - "xpack.metricsData.assetDetails.metricsCharts.cpuUsage": "Utilisation CPU", - "xpack.metricsData.assetDetails.metricsCharts.diskIOPS": "Entrées et sorties par seconde (IOPS) sur le disque", - "xpack.metricsData.assetDetails.metricsCharts.diskThroughput": "Rendement du disque", "xpack.metricsData.assetDetails.metricsCharts.diskUsage.label.used": "Utilisé", - "xpack.metricsData.assetDetails.metricsCharts.diskUsageByMountingPoint": "Utilisation du disque par point de montage", "xpack.metricsData.assetDetails.metricsCharts.kubernetes.nodeCpuCapacity": "Capacité CPU du nœud", "xpack.metricsData.assetDetails.metricsCharts.kubernetes.nodeDiskCapacity": "Capacité du disque du nœud", "xpack.metricsData.assetDetails.metricsCharts.kubernetes.nodeMemoryCapacity": "Capacité de mémoire du nœud", "xpack.metricsData.assetDetails.metricsCharts.kubernetes.nodePodCapacity": "Capacité de pod du nœud", - "xpack.metricsData.assetDetails.metricsCharts.load": "Charge", - "xpack.metricsData.assetDetails.metricsCharts.memoryUsage": "Utilisation mémoire", "xpack.metricsData.assetDetails.metricsCharts.metric.label.cache": "Cache", "xpack.metricsData.assetDetails.metricsCharts.metric.label.free": "Gratuit", "xpack.metricsData.assetDetails.metricsCharts.metric.label.read": "Lire", "xpack.metricsData.assetDetails.metricsCharts.metric.label.used": "Utilisé", "xpack.metricsData.assetDetails.metricsCharts.metric.label.write": "Écrire", - "xpack.metricsData.assetDetails.metricsCharts.network": "Réseau", "xpack.metricsData.assetDetails.metricsCharts.network.label.rx": "Entrant (RX)", "xpack.metricsData.assetDetails.metricsCharts.network.label.tx": "Sortant (TX)", "xpack.metricsData.hostsPage.goToMetricsSettings": "Vérifier les paramètres", diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 7cb20be1fd0e7..dac5c30126d51 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -13912,7 +13912,6 @@ "xpack.enterpriseSearch.crawler.deleteDomainModal.description": "ドメイン{domainUrl}をクローラーから削除します。これにより、設定したすべてのエントリポイントとクロールルールも削除されます。このドメインに関連するすべてのドキュメントは、次回のクロールで削除されます。{thisCannotBeUndoneMessage}", "xpack.enterpriseSearch.crawler.entryPointsTable.emptyMessageDescription": "クローラーのエントリポイントを指定するには、{link}してください", "xpack.enterpriseSearch.deleteConnectorModal.li.myconnectornameRelatedIndexLabel": "{connectorName}(関連付けられたインデックス:{deleteModalIndexName})", - "xpack.enterpriseSearch.endpointsHeader.apiKey.activeKeys": "{number}個のアクティブなAPIキー", "xpack.enterpriseSearch.errorConnectingState.cloudErrorMessage": "クラウドデプロイのエンタープライズ サーチノードが実行中ですか?{deploymentSettingsLink}", "xpack.enterpriseSearch.errorConnectingState.description1": "次のエラーのため、ホストURL {enterpriseSearchUrl}では、エンタープライズ サーチへの接続を確立できません。", "xpack.enterpriseSearch.errorConnectingState.description2": "ホストURLが{configFile}で正しく構成されていることを確認してください。", @@ -16128,12 +16127,7 @@ "xpack.enterpriseSearch.overview.gettingStarted.testConnection.description": "テストリクエストを送信して、言語クライアントとElasticsearchインスタンスが起動し、実行中であることを確認してください。", "xpack.enterpriseSearch.overview.gettingStarted.testConnection.title": "接続をテスト", "xpack.enterpriseSearch.overview.navTitle": "概要", - "xpack.enterpriseSearch.overview.pageTemplate.apiKey.copyApiEndpoint": "Elasticsearchエンドポイントをクリップボードにコピーします。", "xpack.enterpriseSearch.overview.setupCta.description": "Elastic App Search および Workplace Search を使用して、アプリまたは社内組織に検索を追加できます。検索が簡単になるとどのような利点があるのかについては、動画をご覧ください。", - "xpack.enterpriseSearch.pageTemplate.apiKey.copied": "コピー完了", - "xpack.enterpriseSearch.pageTemplate.apiKey.elasticsearchEndpoint": "Elasticsearchエンドポイント:", - "xpack.enterpriseSearch.pageTemplate.apiKey.manageLabel": "管理", - "xpack.enterpriseSearch.pageTemplate.apiKey.newButtonLabel": "新しいAPIキー", "xpack.enterpriseSearch.pageTemplate.endpointsButtonLabel": "エンドポイントとAPIキー", "xpack.enterpriseSearch.passwordLabel": "パスワード", "xpack.enterpriseSearch.pipeline.title": "データの変換とエンリッチ", @@ -21228,10 +21222,8 @@ "xpack.infra.assetDetails.tabs.metadata.seeLess": "簡易表示", "xpack.infra.assetDetails.tabs.metadata.seeMore": "他 {count} 件", "xpack.infra.assetDetails.tabs.metadata": "メタデータ", - "xpack.infra.assetDetails.tabs.osquery": "Osquery", "xpack.infra.assetDetails.tabs.overview": "概要", "xpack.infra.assetDetails.tabs.processes": "プロセス", - "xpack.infra.assetDetails.tabs.profiling": "ユニバーサルプロファイリング", "xpack.infra.assetDetails.tooltip.activeAlertsExplanation": "アクティブアラート", "xpack.infra.bottomDrawer.kubernetesDashboardsLink": "Kubernetesダッシュボード", "xpack.infra.chartSection.missingMetricDataBody": "このチャートはデータが欠けています。", @@ -24075,7 +24067,6 @@ "xpack.logsExplorer.dataTable.header.popover.resource": "リソース", "xpack.logsExplorer.dataTable.header.resource.tooltip.paragraph": "次のようなドキュメントのソースに関する情報を提供するフィールド:", "xpack.logsExplorer.flyoutDetail.title": "ログの詳細", - "xpack.logsExplorer.grid.closePopover": "ポップオーバーを閉じる", "xpack.logsExplorer.popoverAction.closePopover": "ポップオーバーを閉じる", "xpack.logsExplorer.popoverAction.copyValue": "値をコピー", "xpack.logsExplorer.popoverAction.filterFor": "フィルター", @@ -44889,7 +44880,6 @@ "xpack.features.savedQueryManagementFeatureName": "保存されたクエリ管理", "xpack.features.savedQueryManagementTooltip": "[すべて]に設定すると、保存されたクエリは、クエリをサポートするすべてのアプリケーションのKibana全体で管理できます。[なし]に設定すると、保存されたクエリ権限は各アプリケーションで独自に決定されます。", "xpack.features.visualizeFeatureName": "Visualizeライブラリ", - "xpack.metricsData.assetDetails.formulas.cpuUsage": "CPU使用状況", "xpack.metricsData.assetDetails.formulas.cpuUsage.iowaitLabel": "iowait", "xpack.metricsData.assetDetails.formulas.cpuUsage.irqLabel": "irq", "xpack.metricsData.assetDetails.formulas.cpuUsage.niceLabel": "nice", @@ -44897,45 +44887,25 @@ "xpack.metricsData.assetDetails.formulas.cpuUsage.stealLabel": "steal", "xpack.metricsData.assetDetails.formulas.cpuUsage.systemLabel": "システム", "xpack.metricsData.assetDetails.formulas.cpuUsage.userLabel": "ユーザー", - "xpack.metricsData.assetDetails.formulas.diskIORead": "ディスク読み取りIOPS", - "xpack.metricsData.assetDetails.formulas.diskIOWrite": "ディスク書き込みIOPS", - "xpack.metricsData.assetDetails.formulas.diskReadThroughput": "ディスク読み取りスループット", - "xpack.metricsData.assetDetails.formulas.diskSpaceAvailability": "空きディスク容量", - "xpack.metricsData.assetDetails.formulas.diskSpaceAvailable": "空きディスク容量", - "xpack.metricsData.assetDetails.formulas.diskUsage": "ディスク使用量", - "xpack.metricsData.assetDetails.formulas.diskWriteThroughput": "ディスク書き込みスループット", "xpack.metricsData.assetDetails.formulas.hostCount.hostsLabel": "ホスト", "xpack.metricsData.assetDetails.formulas.kubernetes.capacity": "容量", "xpack.metricsData.assetDetails.formulas.kubernetes.used": "使用中", - "xpack.metricsData.assetDetails.formulas.load15m": "読み込み(15m)", - "xpack.metricsData.assetDetails.formulas.load1m": "読み込み(1m)", - "xpack.metricsData.assetDetails.formulas.load5m": "読み込み(5m)", "xpack.metricsData.assetDetails.formulas.logRate": "ログレート", - "xpack.metricsData.assetDetails.formulas.memoryFree": "空きメモリー", - "xpack.metricsData.assetDetails.formulas.memoryUsage": "メモリー使用状況", "xpack.metricsData.assetDetails.formulas.metric.label.cache": "キャッシュ", "xpack.metricsData.assetDetails.formulas.metric.label.free": "空き", "xpack.metricsData.assetDetails.formulas.metric.label.used": "使用中", - "xpack.metricsData.assetDetails.formulas.normalizedLoad1m": "正規化された負荷", "xpack.metricsData.assetDetails.formulas.rx": "ネットワーク受信(RX)", "xpack.metricsData.assetDetails.formulas.tx": "ネットワーク送信(TX)", - "xpack.metricsData.assetDetails.metricsCharts.cpuUsage": "CPU使用状況", - "xpack.metricsData.assetDetails.metricsCharts.diskIOPS": "Disk IOPS", - "xpack.metricsData.assetDetails.metricsCharts.diskThroughput": "Disk Throughput", "xpack.metricsData.assetDetails.metricsCharts.diskUsage.label.used": "使用中", - "xpack.metricsData.assetDetails.metricsCharts.diskUsageByMountingPoint": "マウントポイント別ディスク使用量", "xpack.metricsData.assetDetails.metricsCharts.kubernetes.nodeCpuCapacity": "ノード CPU 処理能力", "xpack.metricsData.assetDetails.metricsCharts.kubernetes.nodeDiskCapacity": "ノードディスク容量", "xpack.metricsData.assetDetails.metricsCharts.kubernetes.nodeMemoryCapacity": "ノードメモリー容量", "xpack.metricsData.assetDetails.metricsCharts.kubernetes.nodePodCapacity": "ノードポッド容量", - "xpack.metricsData.assetDetails.metricsCharts.load": "読み込み", - "xpack.metricsData.assetDetails.metricsCharts.memoryUsage": "メモリー使用状況", "xpack.metricsData.assetDetails.metricsCharts.metric.label.cache": "キャッシュ", "xpack.metricsData.assetDetails.metricsCharts.metric.label.free": "空き", "xpack.metricsData.assetDetails.metricsCharts.metric.label.read": "読み取り", "xpack.metricsData.assetDetails.metricsCharts.metric.label.used": "使用中", "xpack.metricsData.assetDetails.metricsCharts.metric.label.write": "書き込み", - "xpack.metricsData.assetDetails.metricsCharts.network": "ネットワーク", "xpack.metricsData.assetDetails.metricsCharts.network.label.rx": "受信(RX)", "xpack.metricsData.assetDetails.metricsCharts.network.label.tx": "送信(TX)", "xpack.metricsData.hostsPage.goToMetricsSettings": "設定を確認", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 396ca22ee5058..7e2e9e2e28f1e 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -13938,7 +13938,6 @@ "xpack.enterpriseSearch.crawler.deleteDomainModal.description": "从网络爬虫中移除域 {domainUrl}。这还会删除您已设置的所有入口点和爬网规则。将在下次爬网时移除与此域相关的任何文档。{thisCannotBeUndoneMessage}", "xpack.enterpriseSearch.crawler.entryPointsTable.emptyMessageDescription": "{link}以指定网络爬虫的入口点", "xpack.enterpriseSearch.deleteConnectorModal.li.myconnectornameRelatedIndexLabel": "{connectorName}(相关索引:{deleteModalIndexName})", - "xpack.enterpriseSearch.endpointsHeader.apiKey.activeKeys": "{number} 个活动 API 密钥", "xpack.enterpriseSearch.errorConnectingState.cloudErrorMessage": "您的云部署是否正在运行 Enterprise Search 节点?{deploymentSettingsLink}", "xpack.enterpriseSearch.errorConnectingState.description1": "由于以下错误,我们无法与主机 URL {enterpriseSearchUrl} 的 Enterprise Search 建立连接:", "xpack.enterpriseSearch.errorConnectingState.description2": "确保在 {configFile} 中已正确配置主机 URL。", @@ -16155,12 +16154,7 @@ "xpack.enterpriseSearch.overview.gettingStarted.testConnection.description": "发送测试请求,以确认您的语言客户端和 Elasticsearch 实例已启动并正在运行。", "xpack.enterpriseSearch.overview.gettingStarted.testConnection.title": "测试您的连接", "xpack.enterpriseSearch.overview.navTitle": "概览", - "xpack.enterpriseSearch.overview.pageTemplate.apiKey.copyApiEndpoint": "复制 Elasticsearch 终端到剪贴板。", "xpack.enterpriseSearch.overview.setupCta.description": "通过 Elastic App Search 和 Workplace Search,将搜索添加到您的应用或内部组织中。观看视频,了解方便易用的搜索功能可以帮您做些什么。", - "xpack.enterpriseSearch.pageTemplate.apiKey.copied": "已复制", - "xpack.enterpriseSearch.pageTemplate.apiKey.elasticsearchEndpoint": "Elasticsearch 终端:", - "xpack.enterpriseSearch.pageTemplate.apiKey.manageLabel": "管理", - "xpack.enterpriseSearch.pageTemplate.apiKey.newButtonLabel": "新 API 密钥", "xpack.enterpriseSearch.pageTemplate.endpointsButtonLabel": "终端和 API 密钥", "xpack.enterpriseSearch.passwordLabel": "密码", "xpack.enterpriseSearch.pipeline.title": "转换和扩充数据", @@ -21094,10 +21088,8 @@ "xpack.infra.assetDetails.tabs.metadata.seeLess": "显示更少", "xpack.infra.assetDetails.tabs.metadata.seeMore": "另外 {count} 个", "xpack.infra.assetDetails.tabs.metadata": "元数据", - "xpack.infra.assetDetails.tabs.osquery": "Osquery", "xpack.infra.assetDetails.tabs.overview": "概览", "xpack.infra.assetDetails.tabs.processes": "进程", - "xpack.infra.assetDetails.tabs.profiling": "Universal Profiling", "xpack.infra.homePage.toolbar.showingLastOneMinuteDataText": "选定时间过去 {duration}的数据", "xpack.infra.hostsViewPage.errorOnCreateOrLoadDataview": "尝试创建数据视图时出错:{metricAlias}。尝试重新加载该页面。", "xpack.infra.hostsViewPage.kpi.subtitle.average.limit": "平均值(属于 {limit} 台主机)", @@ -24108,7 +24100,6 @@ "xpack.logsExplorer.dataTable.header.popover.resource": "资源", "xpack.logsExplorer.dataTable.header.resource.tooltip.paragraph": "提供有关文档来源信息的字段,例如:", "xpack.logsExplorer.flyoutDetail.title": "日志详情", - "xpack.logsExplorer.grid.closePopover": "关闭弹出框", "xpack.logsExplorer.popoverAction.closePopover": "关闭弹出框", "xpack.logsExplorer.popoverAction.copyValue": "复制值", "xpack.logsExplorer.popoverAction.filterFor": "筛留", @@ -44937,7 +44928,6 @@ "xpack.features.savedQueryManagementFeatureName": "已保存查询管理", "xpack.features.savedQueryManagementTooltip": "如果设置为“全部”,可以在支持已保存查询的所有应用程序中管理整个 Kibana 中的已保存查询。如果设置为“无”,将由每个应用程序单独确定已保存查询权限。", "xpack.features.visualizeFeatureName": "Visualize 库", - "xpack.metricsData.assetDetails.formulas.cpuUsage": "CPU 使用率", "xpack.metricsData.assetDetails.formulas.cpuUsage.iowaitLabel": "iowait", "xpack.metricsData.assetDetails.formulas.cpuUsage.irqLabel": "irq", "xpack.metricsData.assetDetails.formulas.cpuUsage.niceLabel": "nice", @@ -44945,45 +44935,25 @@ "xpack.metricsData.assetDetails.formulas.cpuUsage.stealLabel": "steal", "xpack.metricsData.assetDetails.formulas.cpuUsage.systemLabel": "system", "xpack.metricsData.assetDetails.formulas.cpuUsage.userLabel": "用户", - "xpack.metricsData.assetDetails.formulas.diskIORead": "磁盘读取 IOPS", - "xpack.metricsData.assetDetails.formulas.diskIOWrite": "磁盘写入 IOPS", - "xpack.metricsData.assetDetails.formulas.diskReadThroughput": "磁盘读取吞吐量", - "xpack.metricsData.assetDetails.formulas.diskSpaceAvailability": "磁盘空间可用性", - "xpack.metricsData.assetDetails.formulas.diskSpaceAvailable": "可用磁盘空间", - "xpack.metricsData.assetDetails.formulas.diskUsage": "磁盘使用率", - "xpack.metricsData.assetDetails.formulas.diskWriteThroughput": "磁盘写入吞吐量", "xpack.metricsData.assetDetails.formulas.hostCount.hostsLabel": "主机", "xpack.metricsData.assetDetails.formulas.kubernetes.capacity": "容量", "xpack.metricsData.assetDetails.formulas.kubernetes.used": "已使用", - "xpack.metricsData.assetDetails.formulas.load15m": "负载(15 分钟)", - "xpack.metricsData.assetDetails.formulas.load1m": "负载(1 分钟)", - "xpack.metricsData.assetDetails.formulas.load5m": "负载(5 分钟)", "xpack.metricsData.assetDetails.formulas.logRate": "日志速率", - "xpack.metricsData.assetDetails.formulas.memoryFree": "可用内存", - "xpack.metricsData.assetDetails.formulas.memoryUsage": "内存利用率", "xpack.metricsData.assetDetails.formulas.metric.label.cache": "缓存", "xpack.metricsData.assetDetails.formulas.metric.label.free": "可用", "xpack.metricsData.assetDetails.formulas.metric.label.used": "已使用", - "xpack.metricsData.assetDetails.formulas.normalizedLoad1m": "标准化负载", "xpack.metricsData.assetDetails.formulas.rx": "网络入站数据 (RX)", "xpack.metricsData.assetDetails.formulas.tx": "网络出站数据 (TX)", - "xpack.metricsData.assetDetails.metricsCharts.cpuUsage": "CPU 使用率", - "xpack.metricsData.assetDetails.metricsCharts.diskIOPS": "磁盘 IOPS", - "xpack.metricsData.assetDetails.metricsCharts.diskThroughput": "磁盘吞吐量", "xpack.metricsData.assetDetails.metricsCharts.diskUsage.label.used": "已使用", - "xpack.metricsData.assetDetails.metricsCharts.diskUsageByMountingPoint": "磁盘使用率(按装载点)", "xpack.metricsData.assetDetails.metricsCharts.kubernetes.nodeCpuCapacity": "节点 CPU 容量", "xpack.metricsData.assetDetails.metricsCharts.kubernetes.nodeDiskCapacity": "节点磁盘容量", "xpack.metricsData.assetDetails.metricsCharts.kubernetes.nodeMemoryCapacity": "节点内存容量", "xpack.metricsData.assetDetails.metricsCharts.kubernetes.nodePodCapacity": "节点 Pod 容量", - "xpack.metricsData.assetDetails.metricsCharts.load": "加载", - "xpack.metricsData.assetDetails.metricsCharts.memoryUsage": "内存利用率", "xpack.metricsData.assetDetails.metricsCharts.metric.label.cache": "缓存", "xpack.metricsData.assetDetails.metricsCharts.metric.label.free": "可用", "xpack.metricsData.assetDetails.metricsCharts.metric.label.read": "读取", "xpack.metricsData.assetDetails.metricsCharts.metric.label.used": "已使用", "xpack.metricsData.assetDetails.metricsCharts.metric.label.write": "写入", - "xpack.metricsData.assetDetails.metricsCharts.network": "网络", "xpack.metricsData.assetDetails.metricsCharts.network.label.rx": "入站 (RX)", "xpack.metricsData.assetDetails.metricsCharts.network.label.tx": "出站 (TX)", "xpack.metricsData.hostsPage.goToMetricsSettings": "检查设置", diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/toolbar/components/inspect/hover_visibility_container/index.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/toolbar/components/inspect/hover_visibility_container/index.tsx index 95240e4141e31..e76ac557a50fb 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/toolbar/components/inspect/hover_visibility_container/index.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/toolbar/components/inspect/hover_visibility_container/index.tsx @@ -28,6 +28,10 @@ const StyledDiv = euiStyled.div` pointer-events: none; opacity: 0; transition: opacity ${getOr(250, 'eui.euiAnimSpeedNormal', theme)} ease; + &:focus-visible { + pointer-events: auto; + opacity: 1; + } } ${targetClassNames.map((cn) => `&:hover .${cn}`).join(', ')} { diff --git a/x-pack/test/alerting_api_integration/common/lib/wait_for_execution_count.ts b/x-pack/test/alerting_api_integration/common/lib/wait_for_execution_count.ts index 6ad0dab431d81..3cd95484e1d5c 100644 --- a/x-pack/test/alerting_api_integration/common/lib/wait_for_execution_count.ts +++ b/x-pack/test/alerting_api_integration/common/lib/wait_for_execution_count.ts @@ -13,7 +13,7 @@ async function delay(millis: number): Promise { } export function createWaitForExecutionCount( - st: supertest.SuperTest, + st: supertest.Agent, spaceId?: string, delayMs: number = 3000 ) { diff --git a/x-pack/test/alerting_api_integration/observability/helpers/alerting_api_helper.ts b/x-pack/test/alerting_api_integration/observability/helpers/alerting_api_helper.ts index bd6c7761a5fcd..1a66aa2fcd9ed 100644 --- a/x-pack/test/alerting_api_integration/observability/helpers/alerting_api_helper.ts +++ b/x-pack/test/alerting_api_integration/observability/helpers/alerting_api_helper.ts @@ -6,7 +6,7 @@ */ import type { Client } from '@elastic/elasticsearch'; -import type { SuperTest, Test } from 'supertest'; +import type { Agent as SuperTestAgent } from 'supertest'; import { ToolingLog } from '@kbn/tooling-log'; import { ThresholdParams } from '@kbn/observability-plugin/common/custom_threshold_rule/types'; import { refreshSavedObjectIndices } from './refresh_index'; @@ -17,7 +17,7 @@ export async function createIndexConnector({ indexName, logger, }: { - supertest: SuperTest; + supertest: SuperTestAgent; name: string; indexName: string; logger: ToolingLog; @@ -51,7 +51,7 @@ export async function createRule({ logger, esClient, }: { - supertest: SuperTest; + supertest: SuperTestAgent; ruleTypeId: string; name: string; params: Params; diff --git a/x-pack/test/alerting_api_integration/observability/helpers/alerting_wait_for_helpers.ts b/x-pack/test/alerting_api_integration/observability/helpers/alerting_wait_for_helpers.ts index 63960b222cede..032435a03e007 100644 --- a/x-pack/test/alerting_api_integration/observability/helpers/alerting_wait_for_helpers.ts +++ b/x-pack/test/alerting_api_integration/observability/helpers/alerting_wait_for_helpers.ts @@ -29,7 +29,7 @@ export async function waitForRuleStatus({ }: { id: string; expectedStatus: string; - supertest: SuperTest.SuperTest; + supertest: SuperTest.Agent; retryService: RetryService; logger: ToolingLog; }): Promise> { diff --git a/x-pack/test/alerting_api_integration/observability/helpers/data_view.ts b/x-pack/test/alerting_api_integration/observability/helpers/data_view.ts index 1f84b2556ab70..3fdceed845856 100644 --- a/x-pack/test/alerting_api_integration/observability/helpers/data_view.ts +++ b/x-pack/test/alerting_api_integration/observability/helpers/data_view.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { SuperTest, Test } from 'supertest'; +import { Agent as SuperTestAgent } from 'supertest'; import { ToolingLog } from '@kbn/tooling-log'; export const createDataView = async ({ @@ -15,7 +15,7 @@ export const createDataView = async ({ title, logger, }: { - supertest: SuperTest; + supertest: SuperTestAgent; id: string; name: string; title: string; @@ -50,7 +50,7 @@ export const deleteDataView = async ({ id, logger, }: { - supertest: SuperTest; + supertest: SuperTestAgent; id: string; logger: ToolingLog; }) => { diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/find.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/find.ts index 9816059995142..7abc1b134f01d 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/find.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/find.ts @@ -6,7 +6,7 @@ */ import expect from '@kbn/expect'; -import { SuperTest, Test } from 'supertest'; +import { Agent as SuperTestAgent } from 'supertest'; import { chunk, omit } from 'lodash'; import { v4 as uuidv4 } from 'uuid'; import { SuperuserAtSpace1, UserAtSpaceScenarios } from '../../../scenarios'; @@ -16,7 +16,7 @@ import { FtrProviderContext } from '../../../../common/ftr_provider_context'; const findTestUtils = ( describeType: 'internal' | 'public', objectRemover: ObjectRemover, - supertest: SuperTest, + supertest: SuperTestAgent, supertestWithoutAuth: any ) => { describe.skip(describeType, () => { diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/find_with_post.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/find_with_post.ts index 7b60595c4d66e..82956536c6d1a 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/find_with_post.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/find_with_post.ts @@ -6,7 +6,7 @@ */ import expect from '@kbn/expect'; -import { SuperTest, Test } from 'supertest'; +import { Agent as SuperTestAgent } from 'supertest'; import { chunk, omit } from 'lodash'; import { v4 as uuidv4 } from 'uuid'; import { UserAtSpaceScenarios } from '../../../scenarios'; @@ -16,7 +16,7 @@ import { FtrProviderContext } from '../../../../common/ftr_provider_context'; const findTestUtils = ( describeType: 'internal' | 'public', objectRemover: ObjectRemover, - supertest: SuperTest, + supertest: SuperTestAgent, supertestWithoutAuth: any ) => { // FLAKY: https://github.com/elastic/kibana/issues/182314 diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/get.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/get.ts index 6d245ed28cc00..fa362249229e3 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/get.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/get.ts @@ -6,7 +6,7 @@ */ import expect from '@kbn/expect'; -import { SuperTest, Test } from 'supertest'; +import { Agent as SuperTestAgent } from 'supertest'; import { SuperuserAtSpace1, UserAtSpaceScenarios } from '../../../scenarios'; import { getUrlPrefix, @@ -19,7 +19,7 @@ import { FtrProviderContext } from '../../../../common/ftr_provider_context'; const getTestUtils = ( describeType: 'internal' | 'public', objectRemover: ObjectRemover, - supertest: SuperTest, + supertest: SuperTestAgent, supertestWithoutAuth: any ) => { describe(describeType, () => { diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/crowdstrike.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/crowdstrike.ts index 7b4d064eb6b6e..c9d1ca8814592 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/crowdstrike.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/crowdstrike.ts @@ -131,7 +131,7 @@ export default function createCrowdstrikeTests({ getService }: FtrProviderContex password = 'changeme', errorLogger = logErrorDetails, }: { - supertest: SuperTest.SuperTest; + supertest: SuperTest.Agent; subAction: string; subActionParams: Record; expectedHttpCode?: number; diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/sentinelone.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/sentinelone.ts index 4b184ccb7a595..bf6f88be08fdf 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/sentinelone.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/sentinelone.ts @@ -140,7 +140,7 @@ export default function createSentinelOneTests({ getService }: FtrProviderContex password = 'changeme', errorLogger = logErrorDetails, }: { - supertest: SuperTest.SuperTest; + supertest: SuperTest.Agent; subAction: string; subActionParams: Record; expectedHttpCode?: number; diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/sub_action_framework/index.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/sub_action_framework/index.ts index 0a363e001535b..85e3b8405257f 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/sub_action_framework/index.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/sub_action_framework/index.ts @@ -22,7 +22,7 @@ const createSubActionConnector = async ({ connectorTypeId = 'test.sub-action-connector', expectedHttpCode = 200, }: { - supertest: SuperTest.SuperTest; + supertest: SuperTest.Agent; config?: Record; secrets?: Record; connectorTypeId?: string; @@ -56,7 +56,7 @@ const executeSubAction = async ({ subActionParams, expectedHttpCode = 200, }: { - supertest: SuperTest.SuperTest; + supertest: SuperTest.Agent; connectorId: string; subAction: string; subActionParams: Record; diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/actions/connector_types/stack/webhook.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/actions/connector_types/stack/webhook.ts index f3b3a4e7076ef..ad6a8d12baed3 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/actions/connector_types/stack/webhook.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/actions/connector_types/stack/webhook.ts @@ -8,7 +8,7 @@ import http from 'http'; import https from 'https'; import getPort from 'get-port'; -import { SuperTest, Test } from 'supertest'; +import { Agent as SuperTestAgent } from 'supertest'; import expect from '@kbn/expect'; import { URL, format as formatUrl } from 'url'; import { @@ -177,7 +177,7 @@ export default function webhookTest({ getService }: FtrProviderContext) { } export async function createWebhookAction( - supertest: SuperTest, + supertest: SuperTestAgent, webhookSimulatorURL: string, config: Record> = {} ): Promise { diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/find.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/find.ts index a83ec1e70a0a1..d38bb2f40a275 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/find.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/find.ts @@ -6,7 +6,7 @@ */ import expect from '@kbn/expect'; -import { SuperTest, Test } from 'supertest'; +import { Agent as SuperTestAgent } from 'supertest'; import { fromKueryExpression } from '@kbn/es-query'; import { Spaces } from '../../../scenarios'; import { getUrlPrefix, getTestRuleData, ObjectRemover } from '../../../../common/lib'; @@ -14,7 +14,7 @@ import { FtrProviderContext } from '../../../../common/ftr_provider_context'; async function createAlert( objectRemover: ObjectRemover, - supertest: SuperTest, + supertest: SuperTestAgent, overwrites = {} ) { const { body: createdAlert } = await supertest @@ -28,7 +28,7 @@ async function createAlert( const findTestUtils = ( describeType: 'internal' | 'public', - supertest: SuperTest, + supertest: SuperTestAgent, objectRemover: ObjectRemover ) => { describe(describeType, () => { diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/get.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/get.ts index 51f246e2c5609..c22e8233f2d73 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/get.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/get.ts @@ -6,7 +6,7 @@ */ import expect from '@kbn/expect'; -import { SuperTest, Test } from 'supertest'; +import { Agent as SuperTestAgent } from 'supertest'; import { Spaces } from '../../../scenarios'; import { getUrlPrefix, getTestRuleData, ObjectRemover } from '../../../../common/lib'; import { FtrProviderContext } from '../../../../common/ftr_provider_context'; @@ -14,7 +14,7 @@ import { FtrProviderContext } from '../../../../common/ftr_provider_context'; const getTestUtils = ( describeType: 'internal' | 'public', objectRemover: ObjectRemover, - supertest: SuperTest + supertest: SuperTestAgent ) => { describe(describeType, () => { afterEach(() => objectRemover.removeAll()); diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group3/test_helpers.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group3/test_helpers.ts index a898cc14b9104..b2196d9ea3724 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group3/test_helpers.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group3/test_helpers.ts @@ -8,7 +8,7 @@ import moment from 'moment'; import type { RetryService } from '@kbn/ftr-common-functional-services'; import type { IValidatedEvent } from '@kbn/event-log-plugin/server'; -import type { SuperTest, Test } from 'supertest'; +import type { Agent as SuperTestAgent } from 'supertest'; import expect from '@kbn/expect'; import type { FtrProviderContext } from '../../../../common/ftr_provider_context'; import { getUrlPrefix, getTestRuleData, ObjectRemover, getEventLog } from '../../../../common/lib'; @@ -23,7 +23,7 @@ export const createRule = async ({ }: { actionId: string; pattern: { instance: boolean[] }; - supertest: SuperTest; + supertest: SuperTestAgent; objectRemover: ObjectRemover; overwrites?: any; }) => { @@ -65,7 +65,7 @@ export const createAction = async ({ supertest, objectRemover, }: { - supertest: SuperTest; + supertest: SuperTestAgent; objectRemover: ObjectRemover; }) => { const { body: createdAction } = await supertest @@ -89,7 +89,7 @@ export const createMaintenanceWindow = async ({ objectRemover, }: { overwrites?: any; - supertest: SuperTest; + supertest: SuperTestAgent; objectRemover: ObjectRemover; }) => { const { body: window } = await supertest @@ -112,11 +112,7 @@ export const createMaintenanceWindow = async ({ return window; }; -export const getActiveMaintenanceWindows = async ({ - supertest, -}: { - supertest: SuperTest; -}) => { +export const getActiveMaintenanceWindows = async ({ supertest }: { supertest: SuperTestAgent }) => { const { body: activeMaintenanceWindows } = await supertest .get(`${getUrlPrefix(Spaces.space1.id)}/internal/alerting/rules/maintenance_window/_active`) .set('kbn-xsrf', 'foo') @@ -130,7 +126,7 @@ export const finishMaintenanceWindow = async ({ supertest, }: { id: string; - supertest: SuperTest; + supertest: SuperTestAgent; }) => { return supertest .post( @@ -188,7 +184,7 @@ export const expectNoActionsFired = async ({ retry, }: { id: string; - supertest: SuperTest; + supertest: SuperTestAgent; retry: RetryService; }) => { const events = await retry.try(async () => { @@ -215,7 +211,7 @@ export const runSoon = async ({ retry, }: { id: string; - supertest: SuperTest; + supertest: SuperTestAgent; retry: RetryService; }) => { return retry.try(async () => { 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 index d71f7a1c7f951..ea1b7120238b0 100644 --- a/x-pack/test/api_integration/apis/asset_manager/tests/containers.ts +++ b/x-pack/test/api_integration/apis/asset_manager/tests/containers.ts @@ -23,8 +23,8 @@ export default function ({ getService }: FtrProviderContext) { await synthtrace.clean(); }); - it('should return container assets', async () => { - await synthtrace.index(generateContainersData({ from, to, count: 5 })); + it('should return docker container assets', async () => { + await synthtrace.index(generateDockerContainersData({ from, to, count: 5 })); const response = await supertest .get(routePaths.GET_CONTAINERS) @@ -38,8 +38,8 @@ export default function ({ getService }: FtrProviderContext) { 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 })); + it('should return a specific docker container asset by EAN', async () => { + await synthtrace.index(generateDockerContainersData({ from, to, count: 5 })); const testEan = 'container:container-id-1'; const response = await supertest @@ -56,8 +56,68 @@ export default function ({ getService }: FtrProviderContext) { 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 })); + it('should return a filtered list of docker container assets by ID wildcard pattern', async () => { + await synthtrace.index(generateDockerContainersData({ 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']); + + expect(ids).to.eql([ + 'container-id-1', + 'container-id-10', + 'container-id-11', + 'container-id-12', + 'container-id-13', + 'container-id-14', + ]); + }); + + it('should return k8s container assets', async () => { + await synthtrace.index(generateK8sContainersData({ 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 k8s container asset by EAN', async () => { + await synthtrace.index(generateK8sContainersData({ 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 k8s container assets by ID wildcard pattern', async () => { + await synthtrace.index(generateK8sContainersData({ from, to, count: 15 })); const testIdPattern = '*id-1*'; const response = await supertest @@ -86,7 +146,30 @@ export default function ({ getService }: FtrProviderContext) { }); } -function generateContainersData({ +function generateDockerContainersData({ + from, + to, + count = 1, +}: { + from: string; + to: string; + count: number; +}) { + const range = timerange(from, to); + + const containers = Array(count) + .fill(0) + .map((_, idx) => infra.dockerContainer(`container-id-${idx}`)); + + return range + .interval('1m') + .rate(1) + .generator((timestamp) => + containers.map((container) => container.metrics().timestamp(timestamp)) + ); +} + +function generateK8sContainersData({ from, to, count = 1, @@ -100,7 +183,7 @@ function generateContainersData({ const containers = Array(count) .fill(0) .map((_, idx) => - infra.container(`container-id-${idx}`, `container-uid-${idx + 1000}`, `node-name-${idx}`) + infra.k8sContainer(`container-id-${idx}`, `container-uid-${idx + 1000}`, `node-name-${idx}`) ); return range diff --git a/x-pack/test/api_integration/apis/asset_manager/tests/helpers.ts b/x-pack/test/api_integration/apis/asset_manager/tests/helpers.ts index 3d1086ca8b8e4..94ab2f5b99ffe 100644 --- a/x-pack/test/api_integration/apis/asset_manager/tests/helpers.ts +++ b/x-pack/test/api_integration/apis/asset_manager/tests/helpers.ts @@ -9,11 +9,11 @@ import type { AssetWithoutTimestamp } from '@kbn/assetManager-plugin/common/type import type { WriteSamplesPostBody } from '@kbn/assetManager-plugin/server'; import { apm, infra, timerange } from '@kbn/apm-synthtrace-client'; import expect from '@kbn/expect'; -import { SuperTest, Test } from 'supertest'; +import { Agent as SuperTestAgent } from 'supertest'; const SAMPLE_ASSETS_ENDPOINT = '/api/asset-manager/assets/sample'; -export type KibanaSupertest = SuperTest; +export type KibanaSupertest = SuperTestAgent; // NOTE: In almost every case in tests, you want { refresh: true } // in the options of this function, so it is defaulted to that value. diff --git a/x-pack/test/api_integration/apis/cloud_security_posture/helper.ts b/x-pack/test/api_integration/apis/cloud_security_posture/helper.ts index 03a61807f1b31..5565e7a6e096b 100644 --- a/x-pack/test/api_integration/apis/cloud_security_posture/helper.ts +++ b/x-pack/test/api_integration/apis/cloud_security_posture/helper.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { SuperTest, Test } from 'supertest'; +import type { Agent as SuperTestAgent } from 'supertest'; import { Client } from '@elastic/elasticsearch'; import expect from '@kbn/expect'; import { ELASTIC_HTTP_VERSION_HEADER } from '@kbn/core-http-common'; @@ -43,7 +43,7 @@ export const addIndex = async (es: Client, findingsMock: T[], indexName: stri }; export async function createPackagePolicy( - supertest: SuperTest, + supertest: SuperTestAgent, agentPolicyId: string, policyTemplate: string, input: string, diff --git a/x-pack/test/api_integration/apis/management/index_management/index.ts b/x-pack/test/api_integration/apis/management/index_management/index.ts index 97d25f93a4982..63ab1f3371941 100644 --- a/x-pack/test/api_integration/apis/management/index_management/index.ts +++ b/x-pack/test/api_integration/apis/management/index_management/index.ts @@ -15,6 +15,7 @@ export default function ({ loadTestFile }: FtrProviderContext) { loadTestFile(require.resolve('./stats')); loadTestFile(require.resolve('./data_streams')); loadTestFile(require.resolve('./templates')); + loadTestFile(require.resolve('./inference_endpoints')); loadTestFile(require.resolve('./component_templates')); loadTestFile(require.resolve('./cluster_nodes')); loadTestFile(require.resolve('./index_details')); diff --git a/x-pack/test/api_integration/apis/management/index_management/inference_endpoints.ts b/x-pack/test/api_integration/apis/management/index_management/inference_endpoints.ts new file mode 100644 index 0000000000000..ecfcff804d69a --- /dev/null +++ b/x-pack/test/api_integration/apis/management/index_management/inference_endpoints.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 expect from '@kbn/expect'; +import { FtrProviderContext } from '../../../ftr_provider_context'; + +const API_BASE_PATH = '/api/index_management'; + +export default function ({ getService }: FtrProviderContext) { + const supertest = getService('supertest'); + const log = getService('log'); + const ml = getService('ml'); + const inferenceId = 'my-elser-model'; + const taskType = 'sparse_embedding'; + const service = 'elser'; + + describe('Inference endpoints', function () { + before(async () => { + log.debug(`Creating inference endpoint`); + try { + await ml.api.createInferenceEndpoint(inferenceId, taskType, { + service, + service_settings: { + num_allocations: 1, + num_threads: 1, + }, + }); + } catch (err) { + log.debug('[Setup error] Error creating inference endpoint'); + throw err; + } + }); + + after(async () => { + // Cleanup inference endpoints created for testing purposes + try { + log.debug(`Deleting inference endpoint`); + await ml.api.deleteInferenceEndpoint(inferenceId, taskType); + } catch (err) { + log.debug('[Cleanup error] Error deleting inference endpoint'); + throw err; + } + }); + + describe('get inference endpoints', () => { + it('returns the existing inference endpoints', async () => { + const { body: inferenceEndpoints } = await supertest + .get(`${API_BASE_PATH}/inference/all`) + .set('kbn-xsrf', 'xxx') + .set('x-elastic-internal-origin', 'xxx') + .expect(200); + + expect(inferenceEndpoints).to.be.ok(); + expect(inferenceEndpoints[0].model_id).to.eql(inferenceId); + }); + }); + }); +} diff --git a/x-pack/test/api_integration/apis/management/index_management/lib/templates.api.ts b/x-pack/test/api_integration/apis/management/index_management/lib/templates.api.ts index e929cbff2f188..bae578e6c0490 100644 --- a/x-pack/test/api_integration/apis/management/index_management/lib/templates.api.ts +++ b/x-pack/test/api_integration/apis/management/index_management/lib/templates.api.ts @@ -36,7 +36,9 @@ export function templatesApi(getService: FtrProviderContext['getService']) { .send(payload); // Delete all templates created during tests - const cleanUpTemplates = async (additionalRequestHeaders: object = {}) => { + const cleanUpTemplates = async ( + additionalRequestHeaders: Record = {} + ) => { try { await deleteTemplates(templatesCreated).set(additionalRequestHeaders); templatesCreated = []; diff --git a/x-pack/test/api_integration/apis/metrics_ui/helpers.ts b/x-pack/test/api_integration/apis/metrics_ui/helpers.ts index b5375b8d70cab..427909e10ac94 100644 --- a/x-pack/test/api_integration/apis/metrics_ui/helpers.ts +++ b/x-pack/test/api_integration/apis/metrics_ui/helpers.ts @@ -6,9 +6,6 @@ */ import { apm, timerange } from '@kbn/apm-synthtrace-client'; -import { SuperTest, Test } from 'supertest'; - -export type KibanaSupertest = SuperTest; // generates traces, metrics for services export function generateServicesData({ diff --git a/x-pack/test/api_integration/apis/slos/fetch_historical_summary.ts b/x-pack/test/api_integration/apis/slos/fetch_historical_summary.ts new file mode 100644 index 0000000000000..94cccf1e14938 --- /dev/null +++ b/x-pack/test/api_integration/apis/slos/fetch_historical_summary.ts @@ -0,0 +1,131 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license 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 { + SLO_DESTINATION_INDEX_NAME, + SLO_DESTINATION_INDEX_PATTERN, +} from '@kbn/slo-plugin/common/constants'; +import { ALL_VALUE } from '@kbn/slo-schema'; +import moment from 'moment'; +import { FtrProviderContext } from '../../ftr_provider_context'; + +export default function ({ getService }: FtrProviderContext) { + const esClient = getService('es'); + const esDeleteAllIndices = getService('esDeleteAllIndices'); + const sloApi = getService('slo'); + + const SLO_ID = 'slo-fake-1'; + // Failing: See https://github.com/elastic/kibana/issues/183750 + describe.skip('fetch historical summary', () => { + before(async () => { + const now = moment().startOf('minute'); + const curr = now.clone().subtract(30, 'days'); + const end = now.clone().add(5, 'minutes'); + + const batchOperations = []; + while (curr.isSameOrBefore(end)) { + batchOperations.push([ + { index: { _index: SLO_DESTINATION_INDEX_NAME } }, + { + '@timestamp': curr.toISOString(), + slo: { + id: SLO_ID, + revision: 1, + instanceId: ALL_VALUE, + numerator: 90, + denominator: 100, + isGoodSlice: 1, + groupings: {}, + }, + }, + ]); + curr.add(1, 'minute'); + } + + await esClient.bulk({ + index: SLO_DESTINATION_INDEX_NAME, + operations: batchOperations.flat(), + refresh: 'wait_for', + }); + + await esClient.indices.refresh({ index: SLO_DESTINATION_INDEX_NAME }); + }); + + after(async () => { + await esDeleteAllIndices(SLO_DESTINATION_INDEX_PATTERN); + }); + + it('computes the historical summary for a rolling occurrences SLO', async () => { + const response = await sloApi.fetchHistoricalSummary({ + list: [ + { + sloId: SLO_ID, + instanceId: ALL_VALUE, + timeWindow: { + duration: '7d', + type: 'rolling', + }, + budgetingMethod: 'occurrences', + objective: { + target: 0.9, + }, + groupBy: ALL_VALUE, + revision: 1, + }, + ], + }); + expect(response[0].sloId).to.eql(SLO_ID); + expect(response[0].instanceId).to.eql(ALL_VALUE); + expect(response[0].data).to.have.length(168); // 7 days * 24 hours/day * 1 bucket/hour + const last = response[0].data.pop(); + expect(last?.errorBudget).to.eql({ + consumed: 1, + initial: 0.1, + isEstimated: false, + remaining: 0, + }); + expect(last?.sliValue).to.eql(0.9); + expect(last?.status).to.eql('HEALTHY'); + }); + + it('computes the historical summary for a rolling timeslices SLO', async () => { + const response = await sloApi.fetchHistoricalSummary({ + list: [ + { + sloId: SLO_ID, + instanceId: ALL_VALUE, + timeWindow: { + duration: '7d', + type: 'rolling', + }, + budgetingMethod: 'timeslices', + objective: { + target: 0.9, + timesliceTarget: 0.8, + timesliceWindow: '1m', + }, + groupBy: ALL_VALUE, + revision: 1, + }, + ], + }); + expect(response[0].sloId).to.eql(SLO_ID); + expect(response[0].instanceId).to.eql(ALL_VALUE); + expect(response[0].data).to.have.length(168); // 7 days * 24 hours/day * 1 bucket/hour + const last = response[0].data.pop(); + expect(last?.errorBudget).to.eql({ + consumed: 0, + initial: 0.1, + isEstimated: false, + remaining: 1, + }); + expect(last?.sliValue).to.eql(1); + expect(last?.status).to.eql('HEALTHY'); + }); + }); +} diff --git a/x-pack/test/api_integration/apis/slos/index.ts b/x-pack/test/api_integration/apis/slos/index.ts index 6276dd4a4cf6f..c80a0c58e5ecc 100644 --- a/x-pack/test/api_integration/apis/slos/index.ts +++ b/x-pack/test/api_integration/apis/slos/index.ts @@ -14,5 +14,6 @@ export default function ({ loadTestFile }: FtrProviderContext) { loadTestFile(require.resolve('./get_slo')); loadTestFile(require.resolve('./update_slo')); loadTestFile(require.resolve('./reset_slo')); + loadTestFile(require.resolve('./fetch_historical_summary')); }); } diff --git a/x-pack/test/api_integration/apis/telemetry/telemetry.ts b/x-pack/test/api_integration/apis/telemetry/telemetry.ts index 3652b32d9a372..203189906f812 100644 --- a/x-pack/test/api_integration/apis/telemetry/telemetry.ts +++ b/x-pack/test/api_integration/apis/telemetry/telemetry.ts @@ -50,7 +50,7 @@ function getCacheDetails(body: UnencryptedTelemetryPayload): CacheDetails[] { * @param timestamp The new timestamp to be set */ function updateMonitoringDates( - esSupertest: SuperTest.SuperTest, + esSupertest: SuperTest.Agent, fromTimestamp: string, toTimestamp: string, timestamp: string diff --git a/x-pack/test/api_integration/services/slo.ts b/x-pack/test/api_integration/services/slo.ts index 4d28786df56a5..c7b765dddf613 100644 --- a/x-pack/test/api_integration/services/slo.ts +++ b/x-pack/test/api_integration/services/slo.ts @@ -5,11 +5,21 @@ * 2.0. */ -import { CreateSLOInput, FindSLODefinitionsResponse } from '@kbn/slo-schema'; import { SLO_SUMMARY_DESTINATION_INDEX_NAME } from '@kbn/slo-plugin/common/constants'; +import { + CreateSLOInput, + fetchHistoricalSummaryParamsSchema, + FetchHistoricalSummaryResponse, + FindSLODefinitionsResponse, +} from '@kbn/slo-schema'; +import * as t from 'io-ts'; import { waitForIndexToBeEmpty } from '../apis/slos/helper/wait_for_index_state'; import { FtrProviderContext } from '../ftr_provider_context'; +type FetchHistoricalSummaryParams = t.OutputOf< + typeof fetchHistoricalSummaryParamsSchema.props.body +>; + export function SloApiProvider({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const esClient = getService('es'); @@ -49,5 +59,16 @@ export function SloApiProvider({ getService }: FtrProviderContext) { } await waitForIndexToBeEmpty({ esClient, indexName: SLO_SUMMARY_DESTINATION_INDEX_NAME }); }, + async fetchHistoricalSummary( + params: FetchHistoricalSummaryParams + ): Promise { + const { body } = await supertest + .post(`/internal/observability/slos/_historical_summary`) + .set('kbn-xsrf', 'foo') + .set('elastic-api-version', '1') + .send(params); + + return body; + }, }; } diff --git a/x-pack/test/apm_api_integration/common/apm_api_supertest.ts b/x-pack/test/apm_api_integration/common/apm_api_supertest.ts index 9e4f25a7c7c7b..330de33dc7ab6 100644 --- a/x-pack/test/apm_api_integration/common/apm_api_supertest.ts +++ b/x-pack/test/apm_api_integration/common/apm_api_supertest.ts @@ -15,7 +15,7 @@ import type { import type { APIEndpoint } from '@kbn/apm-plugin/server'; import { formatRequest } from '@kbn/server-route-repository'; -export function createApmApiClient(st: supertest.SuperTest) { +export function createApmApiClient(st: supertest.Agent) { return async ( options: { type?: 'form-data'; diff --git a/x-pack/test/apm_api_integration/common/bettertest.ts b/x-pack/test/apm_api_integration/common/bettertest.ts index e1132be3f9a77..8665d200fd15f 100644 --- a/x-pack/test/apm_api_integration/common/bettertest.ts +++ b/x-pack/test/apm_api_integration/common/bettertest.ts @@ -30,7 +30,7 @@ export interface BetterTestResponse { * This is useful for tests that expect a 200 response * It also makes it easier to debug tests that fail because of a 500 response. */ -export function getBettertest(st: supertest.SuperTest) { +export function getBettertest(st: supertest.Agent) { return async ({ pathname, method = 'get', 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 e4cc8d302ba4a..5da6ee4f860d0 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 @@ -8,7 +8,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 type { Agent as SuperTestAgent } from 'supertest'; 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'; @@ -26,7 +26,7 @@ export async function createApmRule({ params, actions = [], }: { - supertest: SuperTest; + supertest: SuperTestAgent; ruleTypeId: T; name: string; params: ApmRuleParamsType[T]; @@ -111,7 +111,7 @@ export async function runRuleSoon({ supertest, }: { ruleId: string; - supertest: SuperTest; + supertest: SuperTestAgent; }): Promise> { return pRetry( async () => { @@ -143,13 +143,13 @@ export async function deleteRuleById({ supertest, ruleId, }: { - supertest: SuperTest; + supertest: SuperTestAgent; ruleId: string; }) { await supertest.delete(`/api/alerting/rule/${ruleId}`).set('kbn-xsrf', 'foo'); } -export async function deleteApmRules(supertest: SuperTest) { +export async function deleteApmRules(supertest: SuperTestAgent) { const res = await supertest.get( `/api/alerting/rules/_find?filter=alert.attributes.consumer:apm&per_page=10000` ); @@ -180,7 +180,7 @@ export async function createIndexConnector({ supertest, name, }: { - supertest: SuperTest; + supertest: SuperTestAgent; name: string; }) { const { body } = await supertest @@ -228,7 +228,7 @@ export async function deleteAllActionConnectors({ supertest, es, }: { - supertest: SuperTest; + supertest: SuperTestAgent; es: Client; }): Promise { const res = await supertest.get(`/api/actions/connectors`); @@ -245,7 +245,7 @@ async function deleteActionConnector({ supertest, actionId, }: { - supertest: SuperTest; + supertest: SuperTestAgent; actionId: string; }) { return supertest.delete(`/api/actions/connector/${actionId}`).set('kbn-xsrf', 'foo'); 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 ae97266ee084c..2fae6c9643ff7 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 @@ -7,7 +7,7 @@ import { Client } from '@elastic/elasticsearch'; import { ToolingLog } from '@kbn/tooling-log'; -import type { SuperTest, Test } from 'supertest'; +import type { Agent as SuperTestAgent } from 'supertest'; import { clearKibanaApmEventLog, deleteApmRules, @@ -22,7 +22,7 @@ export async function cleanupRuleAndAlertState({ logger, }: { es: Client; - supertest: SuperTest; + supertest: SuperTestAgent; logger: ToolingLog; }) { try { diff --git a/x-pack/test/apm_api_integration/tests/alerts/helpers/wait_for_active_rule.ts b/x-pack/test/apm_api_integration/tests/alerts/helpers/wait_for_active_rule.ts index 29dc20840cec5..a2ee7253e9b8c 100644 --- a/x-pack/test/apm_api_integration/tests/alerts/helpers/wait_for_active_rule.ts +++ b/x-pack/test/apm_api_integration/tests/alerts/helpers/wait_for_active_rule.ts @@ -17,7 +17,7 @@ export async function waitForActiveRule({ logger, }: { ruleId: string; - supertest: SuperTest.SuperTest; + supertest: SuperTest.Agent; logger?: ToolingLog; }): Promise> { return pRetry( diff --git a/x-pack/test/cases_api_integration/common/lib/alerts.ts b/x-pack/test/cases_api_integration/common/lib/alerts.ts index a74524c448493..8df074b0d3474 100644 --- a/x-pack/test/cases_api_integration/common/lib/alerts.ts +++ b/x-pack/test/cases_api_integration/common/lib/alerts.ts @@ -30,7 +30,7 @@ import { createComment, deleteAllComments } from './api'; import { postCaseReq } from './mock'; export const createSecuritySolutionAlerts = async ( - supertest: SuperTest.SuperTest, + supertest: SuperTest.Agent, log: ToolingLog, numberOfSignals: number = 1 ): Promise> => { @@ -47,7 +47,7 @@ export const createSecuritySolutionAlerts = async ( }; export const getSecuritySolutionAlerts = async ( - supertest: SuperTest.SuperTest, + supertest: SuperTest.Agent, alertIds: string[] ): Promise> => { const { body: updatedAlert } = await supertest @@ -70,7 +70,7 @@ export const getAlertById = async ({ expectedHttpCode = 200, auth = { user: superUser, space: null }, }: { - supertest: SuperTest.SuperTest; + supertest: SuperTest.Agent; id: string; index: string; expectedHttpCode?: number; @@ -97,7 +97,7 @@ export const createCaseAttachAlertAndDeleteAlert = async ({ alerts, getAlerts, }: { - supertest: SuperTest.SuperTest; + supertest: SuperTest.Agent; totalCases: number; indexOfCaseToDelete: number; owner: string; @@ -145,7 +145,7 @@ export const createCaseAttachAlertAndDeleteCase = async ({ alerts, getAlerts, }: { - supertest: SuperTest.SuperTest; + supertest: SuperTest.Agent; totalCases: number; indicesOfCaseToDelete: number[]; owner: string; @@ -194,7 +194,7 @@ export const createCaseAndAttachAlert = async ({ alerts, getAlerts, }: { - supertest: SuperTest.SuperTest; + supertest: SuperTest.Agent; totalCases: number; owner: string; alerts: Alerts; diff --git a/x-pack/test/cases_api_integration/common/lib/api/attachments.ts b/x-pack/test/cases_api_integration/common/lib/api/attachments.ts index 1dbee9fbd4616..2f598f5a23b11 100644 --- a/x-pack/test/cases_api_integration/common/lib/api/attachments.ts +++ b/x-pack/test/cases_api_integration/common/lib/api/attachments.ts @@ -33,7 +33,7 @@ export const bulkGetAttachments = async ({ expectedHttpCode = 200, auth = { user: superUser, space: null }, }: { - supertest: SuperTest.SuperTest; + supertest: SuperTest.Agent; attachmentIds: string[]; caseId: string; auth?: { user: User; space: string | null }; @@ -57,12 +57,12 @@ export const createComment = async ({ expectedHttpCode = 200, headers = {}, }: { - supertest: SuperTest.SuperTest; + supertest: SuperTest.Agent; caseId: string; params: AttachmentRequest; auth?: { user: User; space: string | null } | null; expectedHttpCode?: number; - headers?: Record; + headers?: Record; }): Promise => { const apiCall = supertest.post( `${getSpaceUrlPrefix(auth?.space)}${CASES_URL}/${caseId}/comments` @@ -86,7 +86,7 @@ export const bulkCreateAttachments = async ({ auth = { user: superUser, space: null }, expectedHttpCode = 200, }: { - supertest: SuperTest.SuperTest; + supertest: SuperTest.Agent; caseId: string; params: BulkCreateAttachmentsRequest; auth?: { user: User; space: string | null }; @@ -110,7 +110,7 @@ export const createCaseAndBulkCreateAttachments = async ({ auth = { user: superUser, space: null }, expectedHttpCode = 200, }: { - supertest: SuperTest.SuperTest; + supertest: SuperTest.Agent; numberOfAttachments?: number; auth?: { user: User; space: string | null }; expectedHttpCode?: number; @@ -156,7 +156,7 @@ export const deleteComment = async ({ expectedHttpCode = 204, auth = { user: superUser, space: null }, }: { - supertest: SuperTest.SuperTest; + supertest: SuperTest.Agent; caseId: string; commentId: string; expectedHttpCode?: number; @@ -178,7 +178,7 @@ export const deleteAllComments = async ({ expectedHttpCode = 204, auth = { user: superUser, space: null }, }: { - supertest: SuperTest.SuperTest; + supertest: SuperTest.Agent; caseId: string; expectedHttpCode?: number; auth?: { user: User; space: string | null }; @@ -199,7 +199,7 @@ export const getAllComments = async ({ expectedHttpCode = 200, auth = { user: superUser, space: null }, }: { - supertest: SuperTest.SuperTest; + supertest: SuperTest.Agent; caseId: string; auth?: { user: User; space: string | null }; expectedHttpCode?: number; @@ -219,7 +219,7 @@ export const getComment = async ({ expectedHttpCode = 200, auth = { user: superUser, space: null }, }: { - supertest: SuperTest.SuperTest; + supertest: SuperTest.Agent; caseId: string; commentId: string; expectedHttpCode?: number; @@ -241,12 +241,12 @@ export const updateComment = async ({ auth = { user: superUser, space: null }, headers = {}, }: { - supertest: SuperTest.SuperTest; + supertest: SuperTest.Agent; caseId: string; req: AttachmentPatchRequest; expectedHttpCode?: number; auth?: { user: User; space: string | null } | null; - headers?: Record; + headers?: Record; }): Promise => { const apiCall = supertest.patch( `${getSpaceUrlPrefix(auth?.space)}${CASES_URL}/${caseId}/comments` @@ -269,7 +269,7 @@ export const bulkDeleteFileAttachments = async ({ expectedHttpCode = 204, auth = { user: superUser, space: null }, }: { - supertest: SuperTest.SuperTest; + supertest: SuperTest.Agent; caseId: string; fileIds: string[]; expectedHttpCode?: number; @@ -290,7 +290,7 @@ export const findAttachments = async ({ expectedHttpCode = 200, auth = { user: superUser, space: null }, }: { - supertest: SuperTest.SuperTest; + supertest: SuperTest.Agent; caseId: string; query?: Record; expectedHttpCode?: number; diff --git a/x-pack/test/cases_api_integration/common/lib/api/case.ts b/x-pack/test/cases_api_integration/common/lib/api/case.ts index a6605d8e83aab..dd1b668b429cf 100644 --- a/x-pack/test/cases_api_integration/common/lib/api/case.ts +++ b/x-pack/test/cases_api_integration/common/lib/api/case.ts @@ -15,11 +15,11 @@ import { superUser } from '../authentication/users'; import { getSpaceUrlPrefix, setupAuth } from './helpers'; export const createCase = async ( - supertest: SuperTest.SuperTest, + supertest: SuperTest.Agent, params: CasePostRequest, expectedHttpCode: number = 200, auth: { user: User; space: string | null } | null = { user: superUser, space: null }, - headers: Record = {} + headers: Record = {} ): Promise => { const apiCall = supertest.post(`${getSpaceUrlPrefix(auth?.space)}${CASES_URL}`); @@ -44,7 +44,7 @@ export const deleteCases = async ({ expectedHttpCode = 204, auth = { user: superUser, space: null }, }: { - supertest: SuperTest.SuperTest; + supertest: SuperTest.Agent; caseIDs: string[]; expectedHttpCode?: number; auth?: { user: User; space: string | null }; diff --git a/x-pack/test/cases_api_integration/common/lib/api/configuration.ts b/x-pack/test/cases_api_integration/common/lib/api/configuration.ts index cfaa18b430c11..c74c6be78da82 100644 --- a/x-pack/test/cases_api_integration/common/lib/api/configuration.ts +++ b/x-pack/test/cases_api_integration/common/lib/api/configuration.ts @@ -60,11 +60,11 @@ export const getConfigurationOutput = (update = false, overwrite = {}): Partial< }; export const createConfiguration = async ( - supertest: SuperTest.SuperTest, + supertest: SuperTest.Agent, req: ConfigurationRequest = getConfigurationRequest(), expectedHttpCode: number = 200, auth: { user: User; space: string | null } | null = { user: superUser, space: null }, - headers: Record = {} + headers: Record = {} ): Promise => { const apiCall = supertest.post(`${getSpaceUrlPrefix(auth?.space)}${CASE_CONFIGURE_URL}`); @@ -86,7 +86,7 @@ export const getConfiguration = async ({ expectedHttpCode = 200, auth = { user: superUser, space: null }, }: { - supertest: SuperTest.SuperTest; + supertest: SuperTest.Agent; query?: Record; expectedHttpCode?: number; auth?: { user: User; space: string | null }; @@ -102,12 +102,12 @@ export const getConfiguration = async ({ }; export const updateConfiguration = async ( - supertest: SuperTest.SuperTest, + supertest: SuperTest.Agent, id: string, req: ConfigurationPatchRequest, expectedHttpCode: number = 200, auth: { user: User; space: string | null } | null = { user: superUser, space: null }, - headers: Record = {} + headers: Record = {} ): Promise => { const apiCall = supertest.patch(`${getSpaceUrlPrefix(auth?.space)}${CASE_CONFIGURE_URL}/${id}`); diff --git a/x-pack/test/cases_api_integration/common/lib/api/connectors.ts b/x-pack/test/cases_api_integration/common/lib/api/connectors.ts index 0eb6854cb735d..3bd959b031ae5 100644 --- a/x-pack/test/cases_api_integration/common/lib/api/connectors.ts +++ b/x-pack/test/cases_api_integration/common/lib/api/connectors.ts @@ -194,7 +194,7 @@ export const getCaseConnectors = async ({ expectedHttpCode = 200, auth = { user: superUser, space: null }, }: { - supertest: SuperTest.SuperTest; + supertest: SuperTest.Agent; expectedHttpCode?: number; auth?: { user: User; space: string | null }; }): Promise => { @@ -215,13 +215,13 @@ export const createCaseWithConnector = async ({ createCaseReq = getPostCaseRequest(), headers = {}, }: { - supertest: SuperTest.SuperTest; + supertest: SuperTest.Agent; serviceNowSimulatorURL: string; actionsRemover: ActionsRemover; configureReq?: Record; auth?: { user: User; space: string | null } | null; createCaseReq?: CasePostRequest; - headers?: Record; + headers?: Record; }): Promise<{ postedCase: Case; connector: CreateConnectorResponse; @@ -288,7 +288,7 @@ export const createConnector = async ({ expectedHttpCode = 200, auth = { user: superUser, space: null }, }: { - supertest: SuperTest.SuperTest; + supertest: SuperTest.Agent; req: Record; expectedHttpCode?: number; auth?: { user: User; space: string | null }; @@ -309,7 +309,7 @@ export const getConnectors = async ({ expectedHttpCode = 200, auth = { user: superUser, space: null }, }: { - supertest: SuperTest.SuperTest; + supertest: SuperTest.Agent; caseId: string; expectedHttpCode?: number; auth?: { user: User; space: string | null }; @@ -329,7 +329,7 @@ export const executeConnector = async ({ expectedHttpCode = 200, auth = { user: superUser, space: null }, }: { - supertest: SuperTest.SuperTest; + supertest: SuperTest.Agent; connectorId: string; req: Record; expectedHttpCode?: number; @@ -352,7 +352,7 @@ export const executeSystemConnector = async ({ expectedHttpCode = 200, auth = { user: superUser, space: null }, }: { - supertest: SuperTest.SuperTest; + supertest: SuperTest.Agent; connectorId: string; req: Record; expectedHttpCode?: number; diff --git a/x-pack/test/cases_api_integration/common/lib/api/files.ts b/x-pack/test/cases_api_integration/common/lib/api/files.ts index 71951564c6a28..8e2710603020f 100644 --- a/x-pack/test/cases_api_integration/common/lib/api/files.ts +++ b/x-pack/test/cases_api_integration/common/lib/api/files.ts @@ -23,7 +23,7 @@ export const downloadFile = async ({ expectedHttpCode = 200, auth = { user: superUser, space: null }, }: { - supertest: SuperTest.SuperTest; + supertest: SuperTest.Agent; fileId: string; kind: string; mimeType: string; @@ -49,7 +49,7 @@ export const deleteFileForFileKind = async ({ expectedHttpCode = 200, auth = { user: superUser, space: null }, }: { - supertest: SuperTest.SuperTest; + supertest: SuperTest.Agent; fileKind: string; id: string; expectedHttpCode?: number; @@ -72,7 +72,7 @@ export const deleteFiles = async ({ expectedHttpCode = 200, auth = { user: superUser, space: null }, }: { - supertest: SuperTest.SuperTest; + supertest: SuperTest.Agent; files: string[]; expectedHttpCode?: number; auth?: { user: User; space: string | null }; @@ -91,7 +91,7 @@ export const deleteAllFilesForKind = async ({ auth = { user: superUser, space: null }, expectedHttpCode = 200, }: { - supertest: SuperTest.SuperTest; + supertest: SuperTest.Agent; kind: string; expectedHttpCode?: number; auth?: { user: User; space: string | null }; @@ -124,7 +124,7 @@ export const deleteAllFiles = async ({ expectedHttpCode = 200, ignoreErrors = true, }: { - supertest: SuperTest.SuperTest; + supertest: SuperTest.Agent; expectedHttpCode?: number; auth?: { user: User; space: string | null }; ignoreErrors?: boolean; @@ -165,7 +165,7 @@ export const getFileById = async ({ expectedHttpCode = 200, auth = { user: superUser, space: null }, }: { - supertest: SuperTest.SuperTest; + supertest: SuperTest.Agent; id: string; kind: string; expectedHttpCode?: number; @@ -185,7 +185,7 @@ export const listFiles = async ({ expectedHttpCode = 200, auth = { user: superUser, space: null }, }: { - supertest: SuperTest.SuperTest; + supertest: SuperTest.Agent; params: Parameters[0]; expectedHttpCode?: number; auth?: { user: User; space: string | null }; @@ -213,7 +213,7 @@ export const createFile = async ({ expectedHttpCode = 200, auth = { user: superUser, space: null }, }: { - supertest: SuperTest.SuperTest; + supertest: SuperTest.Agent; params: CreateFileSchema; expectedHttpCode?: number; auth?: { user: User; space: string | null }; @@ -238,7 +238,7 @@ export const uploadFile = async ({ expectedHttpCode = 200, auth = { user: superUser, space: null }, }: { - supertest: SuperTest.SuperTest; + supertest: SuperTest.Agent; data: string | object; kind: string; fileId: string; @@ -264,7 +264,7 @@ export const createAndUploadFile = async ({ expectedHttpCode = 200, auth = { user: superUser, space: null }, }: { - supertest: SuperTest.SuperTest; + supertest: SuperTest.Agent; data: string | object; createFileParams: CreateFileSchema; expectedHttpCode?: number; diff --git a/x-pack/test/cases_api_integration/common/lib/api/index.ts b/x-pack/test/cases_api_integration/common/lib/api/index.ts index 0b7f9c542a6d0..6582601f0f1a9 100644 --- a/x-pack/test/cases_api_integration/common/lib/api/index.ts +++ b/x-pack/test/cases_api_integration/common/lib/api/index.ts @@ -129,7 +129,7 @@ export const setStatus = async ({ supertest, cases, }: { - supertest: SuperTest.SuperTest; + supertest: SuperTest.Agent; cases: SetStatusCasesParams[]; }): Promise => { const { body }: { body: Cases } = await supertest @@ -143,7 +143,7 @@ export const setStatus = async ({ /** * Add case as a connector */ -export const createCaseAction = async (supertest: SuperTest.SuperTest) => { +export const createCaseAction = async (supertest: SuperTest.Agent) => { const { body: createdAction } = await supertest .post('/api/actions/connector') .set('kbn-xsrf', 'foo') @@ -159,10 +159,7 @@ export const createCaseAction = async (supertest: SuperTest.SuperTest, - id: string -) => { +export const deleteCaseAction = async (supertest: SuperTest.Agent, id: string) => { await supertest.delete(`/api/actions/connector/${id}`).set('kbn-xsrf', 'foo'); }; @@ -418,11 +415,11 @@ export const updateCase = async ({ auth = { user: superUser, space: null }, headers = {}, }: { - supertest: SuperTest.SuperTest; + supertest: SuperTest.Agent; params: CasesPatchRequest; expectedHttpCode?: number; auth?: { user: User; space: string | null } | null; - headers?: Record; + headers?: Record; }): Promise => { const apiCall = supertest.patch(`${getSpaceUrlPrefix(auth?.space)}${CASES_URL}`); @@ -444,7 +441,7 @@ export const getAllCasesStatuses = async ({ auth = { user: superUser, space: null }, query = {}, }: { - supertest: SuperTest.SuperTest; + supertest: SuperTest.Agent; expectedHttpCode?: number; auth?: { user: User; space: string | null }; query?: Record; @@ -465,7 +462,7 @@ export const getCase = async ({ expectedHttpCode = 200, auth = { user: superUser, space: null }, }: { - supertest: SuperTest.SuperTest; + supertest: SuperTest.Agent; caseId: string; includeComments?: boolean; expectedHttpCode?: number; @@ -490,7 +487,7 @@ export const getCaseMetrics = async ({ expectedHttpCode = 200, auth = { user: superUser, space: null }, }: { - supertest: SuperTest.SuperTest; + supertest: SuperTest.Agent; caseId: string; features: CaseMetricsFeature[] | CaseMetricsFeature; expectedHttpCode?: number; @@ -512,7 +509,7 @@ export const resolveCase = async ({ expectedHttpCode = 200, auth = { user: superUser, space: null }, }: { - supertest: SuperTest.SuperTest; + supertest: SuperTest.Agent; caseId: string; includeComments?: boolean; expectedHttpCode?: number; @@ -537,7 +534,7 @@ export const findCases = async ({ expectedHttpCode = 200, auth = { user: superUser, space: null }, }: { - supertest: SuperTest.SuperTest; + supertest: SuperTest.Agent; query?: Record; expectedHttpCode?: number; auth?: { user: User; space: string | null }; @@ -560,7 +557,7 @@ export const getCasesByAlert = async ({ expectedHttpCode = 200, auth = { user: superUser, space: null }, }: { - supertest: SuperTest.SuperTest; + supertest: SuperTest.Agent; alertID: string; query?: Record; expectedHttpCode?: number; @@ -581,7 +578,7 @@ export const getTags = async ({ expectedHttpCode = 200, auth = { user: superUser, space: null }, }: { - supertest: SuperTest.SuperTest; + supertest: SuperTest.Agent; query?: Record; expectedHttpCode?: number; auth?: { user: User; space: string | null }; @@ -602,7 +599,7 @@ export const getReporters = async ({ expectedHttpCode = 200, auth = { user: superUser, space: null }, }: { - supertest: SuperTest.SuperTest; + supertest: SuperTest.Agent; query?: Record; expectedHttpCode?: number; auth?: { user: User; space: string | null }; @@ -623,7 +620,7 @@ export const getCategories = async ({ expectedHttpCode = 200, auth = { user: superUser, space: null }, }: { - supertest: SuperTest.SuperTest; + supertest: SuperTest.Agent; query?: Record; expectedHttpCode?: number; auth?: { user: User; space: string | null }; @@ -646,12 +643,12 @@ export const pushCase = async ({ auth = { user: superUser, space: null }, headers = {}, }: { - supertest: SuperTest.SuperTest; + supertest: SuperTest.Agent; caseId: string; connectorId: string; expectedHttpCode?: number; auth?: { user: User; space: string | null } | null; - headers?: Record; + headers?: Record; }): Promise => { const apiCall = supertest.post( `${getSpaceUrlPrefix(auth?.space)}${CASES_URL}/${caseId}/connector/${connectorId}/_push` @@ -674,7 +671,7 @@ export const getAlertsAttachedToCase = async ({ expectedHttpCode = 200, auth = { user: superUser, space: null }, }: { - supertest: SuperTest.SuperTest; + supertest: SuperTest.Agent; caseId: string; expectedHttpCode?: number; auth?: { user: User; space: string | null }; @@ -727,7 +724,7 @@ export const getCasesMetrics = async ({ expectedHttpCode = 200, auth = { user: superUser, space: null }, }: { - supertest: SuperTest.SuperTest; + supertest: SuperTest.Agent; features: string[] | string; query?: Record; expectedHttpCode?: number; @@ -774,7 +771,7 @@ export const bulkGetCases = async ({ expectedHttpCode = 200, auth = { user: superUser, space: null }, }: { - supertest: SuperTest.SuperTest; + supertest: SuperTest.Agent; ids: string[]; fields?: string[]; expectedHttpCode?: number; @@ -796,7 +793,7 @@ export const searchCases = async ({ expectedHttpCode = 200, auth = { user: superUser, space: null }, }: { - supertest: SuperTest.SuperTest; + supertest: SuperTest.Agent; body?: Record; expectedHttpCode?: number; auth?: { user: User; space: string | null }; @@ -820,13 +817,13 @@ export const replaceCustomField = async ({ auth = { user: superUser, space: null }, headers = {}, }: { - supertest: SuperTest.SuperTest; + supertest: SuperTest.Agent; caseId: string; customFieldId: string; params: CustomFieldPutRequest; expectedHttpCode?: number; auth?: { user: User; space: string | null } | null; - headers?: Record; + headers?: Record; }): Promise => { const apiCall = supertest.put( `${getSpaceUrlPrefix( diff --git a/x-pack/test/cases_api_integration/common/lib/api/user_actions.ts b/x-pack/test/cases_api_integration/common/lib/api/user_actions.ts index fc4f8382d3508..4a0f38b5dcc90 100644 --- a/x-pack/test/cases_api_integration/common/lib/api/user_actions.ts +++ b/x-pack/test/cases_api_integration/common/lib/api/user_actions.ts @@ -42,7 +42,7 @@ export const getCaseUserActions = async ({ expectedHttpCode = 200, auth = { user: superUser, space: null }, }: { - supertest: SuperTest.SuperTest; + supertest: SuperTest.Agent; caseID: string; expectedHttpCode?: number; auth?: { user: User; space: string | null }; @@ -61,7 +61,7 @@ export const findCaseUserActions = async ({ expectedHttpCode = 200, auth = { user: superUser, space: null }, }: { - supertest: SuperTest.SuperTest; + supertest: SuperTest.Agent; caseID: string; options?: UserActionFindRequest; expectedHttpCode?: number; @@ -82,7 +82,7 @@ export const getCaseUserActionStats = async ({ expectedHttpCode = 200, auth = { user: superUser, space: null }, }: { - supertest: SuperTest.SuperTest; + supertest: SuperTest.Agent; caseID: string; expectedHttpCode?: number; auth?: { user: User; space: string | null }; @@ -101,7 +101,7 @@ export const getCaseUsers = async ({ expectedHttpCode = 200, auth = { user: superUser, space: null }, }: { - supertest: SuperTest.SuperTest; + supertest: SuperTest.Agent; caseId: string; expectedHttpCode?: number; auth?: { user: User; space: string | null }; diff --git a/x-pack/test/cases_api_integration/common/lib/api/user_profiles.ts b/x-pack/test/cases_api_integration/common/lib/api/user_profiles.ts index bc78feab4070c..f9a66fe0f7962 100644 --- a/x-pack/test/cases_api_integration/common/lib/api/user_profiles.ts +++ b/x-pack/test/cases_api_integration/common/lib/api/user_profiles.ts @@ -38,7 +38,7 @@ export const bulkGetUserProfiles = async ({ expectedHttpCode = 200, auth = { user: superUser, space: null }, }: { - supertest: SuperTest.SuperTest; + supertest: SuperTest.Agent; req: BulkGetUserProfilesParams; expectedHttpCode?: number; auth?: { user: User; space: string | null }; @@ -62,7 +62,7 @@ export const suggestUserProfiles = async ({ expectedHttpCode = 200, auth = { user: superUser, space: null }, }: { - supertest: SuperTest.SuperTest; + supertest: SuperTest.Agent; req: SuggestUserProfilesRequest; expectedHttpCode?: number; auth?: { user: User; space: string | null }; @@ -89,10 +89,10 @@ export const updateUserProfileAvatar = async ({ expectedHttpCode = 200, headers = {}, }: { - supertest: SuperTest.SuperTest; + supertest: SuperTest.Agent; req: UserProfileAvatarData; expectedHttpCode?: number; - headers?: Record; + headers?: Record; }): Promise => { await supertest .post('/internal/security/user_profile/_data') @@ -106,7 +106,7 @@ export const loginUsers = async ({ supertest, users = [superUser], }: { - supertest: SuperTest.SuperTest; + supertest: SuperTest.Agent; users?: User[]; }) => { const cookies: Cookie[] = []; diff --git a/x-pack/test/cases_api_integration/security_and_spaces/tests/common/cases/bulk_create_cases.ts b/x-pack/test/cases_api_integration/security_and_spaces/tests/common/cases/bulk_create_cases.ts index 8177649f22ab3..c07d858e4b389 100644 --- a/x-pack/test/cases_api_integration/security_and_spaces/tests/common/cases/bulk_create_cases.ts +++ b/x-pack/test/cases_api_integration/security_and_spaces/tests/common/cases/bulk_create_cases.ts @@ -52,7 +52,7 @@ export default ({ getService }: FtrProviderContext): void => { expectedHttpCode = 200, auth = { user: superUser, space: null }, }: { - superTestService?: SuperTest.SuperTest; + superTestService?: SuperTest.Agent; data: object; expectedHttpCode?: number; auth?: { user: User; space: string | null }; diff --git a/x-pack/test/cases_api_integration/security_and_spaces/tests/common/cases/delete_cases.ts b/x-pack/test/cases_api_integration/security_and_spaces/tests/common/cases/delete_cases.ts index 4c3239fe0d126..ef0e09f1a477d 100644 --- a/x-pack/test/cases_api_integration/security_and_spaces/tests/common/cases/delete_cases.ts +++ b/x-pack/test/cases_api_integration/security_and_spaces/tests/common/cases/delete_cases.ts @@ -700,7 +700,7 @@ const createCaseWithFiles = async ({ owner, auth = { user: superUser, space: null }, }: { - supertest: SuperTest.SuperTest; + supertest: SuperTest.Agent; fileKind: string; owner: string; auth?: { user: User; space: string | null }; diff --git a/x-pack/test/cases_api_integration/security_and_spaces/tests/common/cases/import_export.ts b/x-pack/test/cases_api_integration/security_and_spaces/tests/common/cases/import_export.ts index 060b6463c0451..3aa11c83947ad 100644 --- a/x-pack/test/cases_api_integration/security_and_spaces/tests/common/cases/import_export.ts +++ b/x-pack/test/cases_api_integration/security_and_spaces/tests/common/cases/import_export.ts @@ -161,7 +161,7 @@ export default ({ getService }: FtrProviderContext): void => { }); }; -const expectImportToHaveOneCase = async (supertestService: supertest.SuperTest) => { +const expectImportToHaveOneCase = async (supertestService: supertest.Agent) => { const findResponse = await findCases({ supertest: supertestService, query: {} }); expect(findResponse.total).to.eql(1); expect(findResponse.cases[0].title).to.eql('A case with a connector'); diff --git a/x-pack/test/cases_api_integration/security_and_spaces/tests/trial/connectors/cases/cases_connector.ts b/x-pack/test/cases_api_integration/security_and_spaces/tests/trial/connectors/cases/cases_connector.ts index b0fcd30fa5a42..060222473c15b 100644 --- a/x-pack/test/cases_api_integration/security_and_spaces/tests/trial/connectors/cases/cases_connector.ts +++ b/x-pack/test/cases_api_integration/security_and_spaces/tests/trial/connectors/cases/cases_connector.ts @@ -1352,7 +1352,7 @@ const executeConnectorAndVerifyCorrectness = async ({ connectorId, req, }: { - supertest: SuperTest.SuperTest; + supertest: SuperTest.Agent; connectorId: string; req: Record; }) => { diff --git a/x-pack/test/common/services/bsearch_secure.ts b/x-pack/test/common/services/bsearch_secure.ts index 0ab967462767f..01050d1bb60c0 100644 --- a/x-pack/test/common/services/bsearch_secure.ts +++ b/x-pack/test/common/services/bsearch_secure.ts @@ -28,7 +28,7 @@ const getSpaceUrlPrefix = (spaceId?: string): string => { }; interface SendOptions { - supertestWithoutAuth: SuperTest.SuperTest; + supertestWithoutAuth: SuperTest.Agent; auth: { username: string; password: string }; referer?: string; kibanaVersion?: string; diff --git a/x-pack/test/common/services/index.ts b/x-pack/test/common/services/index.ts index a613fb8899c6c..b5045fd94f8e5 100644 --- a/x-pack/test/common/services/index.ts +++ b/x-pack/test/common/services/index.ts @@ -11,6 +11,7 @@ import { InfraLogViewsServiceProvider } from './infra_log_views'; import { SpacesServiceProvider } from './spaces'; import { BsearchSecureService } from './bsearch_secure'; import { ApmSynthtraceKibanaClientProvider } from './apm_synthtrace_kibana_client'; +import { InfraSynthtraceKibanaClientProvider } from './infra_synthtrace_kibana_client'; export const services = { ...kibanaCommonServices, @@ -19,4 +20,5 @@ export const services = { spaces: SpacesServiceProvider, secureBsearch: BsearchSecureService, apmSynthtraceKibanaClient: ApmSynthtraceKibanaClientProvider, + infraSynthtraceKibanaClient: InfraSynthtraceKibanaClientProvider, }; diff --git a/x-pack/test/common/services/infra_synthtrace_kibana_client.ts b/x-pack/test/common/services/infra_synthtrace_kibana_client.ts new file mode 100644 index 0000000000000..5a8a3c4e06578 --- /dev/null +++ b/x-pack/test/common/services/infra_synthtrace_kibana_client.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 url from 'url'; +import { kbnTestConfig } from '@kbn/test'; +import { InfraSynthtraceKibanaClient, createLogger, LogLevel } from '@kbn/apm-synthtrace'; + +const getKibanaServerUrlWithAuth = () => { + const kibanaServerUrl = url.format(kbnTestConfig.getUrlParts() as url.UrlObject); + const kibanaServerUrlWithAuth = url + .format({ + ...url.parse(kibanaServerUrl), + auth: `elastic:${kbnTestConfig.getUrlParts().password}`, + }) + .slice(0, -1); + return kibanaServerUrlWithAuth; +}; + +export function InfraSynthtraceKibanaClientProvider() { + const kibanaServerUrlWithAuth = getKibanaServerUrlWithAuth(); + const target = kibanaServerUrlWithAuth; + const logger = createLogger(LogLevel.debug); + const username = 'elastic'; + const password = kbnTestConfig.getUrlParts().password || 'changeme'; + const kibanaClient = new InfraSynthtraceKibanaClient({ + target, + logger, + username, + password, + }); + + return kibanaClient; +} diff --git a/x-pack/test/common/utils/security_solution/detections_response/alerts/create_alerts_index.ts b/x-pack/test/common/utils/security_solution/detections_response/alerts/create_alerts_index.ts index 932db176942d9..da7f7b2cf36a6 100644 --- a/x-pack/test/common/utils/security_solution/detections_response/alerts/create_alerts_index.ts +++ b/x-pack/test/common/utils/security_solution/detections_response/alerts/create_alerts_index.ts @@ -17,7 +17,7 @@ import { countDownTest } from '../count_down_test'; * @param supertest The supertest client library */ export const createAlertsIndex = async ( - supertest: SuperTest.SuperTest, + supertest: SuperTest.Agent, log: ToolingLog ): Promise => { await countDownTest( diff --git a/x-pack/test/common/utils/security_solution/detections_response/alerts/delete_all_alerts.ts b/x-pack/test/common/utils/security_solution/detections_response/alerts/delete_all_alerts.ts index e15aa4453282a..f29237b237694 100644 --- a/x-pack/test/common/utils/security_solution/detections_response/alerts/delete_all_alerts.ts +++ b/x-pack/test/common/utils/security_solution/detections_response/alerts/delete_all_alerts.ts @@ -16,7 +16,7 @@ import { countDownTest } from '../count_down_test'; * For use inside of afterEach blocks of tests */ export const deleteAllAlerts = async ( - supertest: SuperTest.SuperTest, + supertest: SuperTest.Agent, log: ToolingLog, es: Client, index: Array<'.alerts-security.alerts-*' | '.preview.alerts-security.alerts-*'> = [ diff --git a/x-pack/test/common/utils/security_solution/detections_response/alerts/get_alerts_by_id.ts b/x-pack/test/common/utils/security_solution/detections_response/alerts/get_alerts_by_id.ts index 1a3f7e29c26c6..92791edd5ea7e 100644 --- a/x-pack/test/common/utils/security_solution/detections_response/alerts/get_alerts_by_id.ts +++ b/x-pack/test/common/utils/security_solution/detections_response/alerts/get_alerts_by_id.ts @@ -20,7 +20,7 @@ import { getQueryAlertsId } from './get_query_alerts_ids'; * @param ids Rule id */ export const getAlertsById = async ( - supertest: SuperTest.SuperTest, + supertest: SuperTest.Agent, log: ToolingLog, id: string ): Promise> => { diff --git a/x-pack/test/common/utils/security_solution/detections_response/alerts/get_alerts_by_ids.ts b/x-pack/test/common/utils/security_solution/detections_response/alerts/get_alerts_by_ids.ts index 1cfc922d76677..d090a39ff3779 100644 --- a/x-pack/test/common/utils/security_solution/detections_response/alerts/get_alerts_by_ids.ts +++ b/x-pack/test/common/utils/security_solution/detections_response/alerts/get_alerts_by_ids.ts @@ -23,7 +23,7 @@ import { routeWithNamespace } from '../route_with_namespace'; * @param ids Array of the rule ids */ export const getAlertsByIds = async ( - supertest: SuperTest.SuperTest, + supertest: SuperTest.Agent, log: ToolingLog, ids: string[], size?: number, diff --git a/x-pack/test/common/utils/security_solution/detections_response/alerts/wait_for_alerts_to_be_present.ts b/x-pack/test/common/utils/security_solution/detections_response/alerts/wait_for_alerts_to_be_present.ts index f7e873f98d4c7..5772861f6e636 100644 --- a/x-pack/test/common/utils/security_solution/detections_response/alerts/wait_for_alerts_to_be_present.ts +++ b/x-pack/test/common/utils/security_solution/detections_response/alerts/wait_for_alerts_to_be_present.ts @@ -18,7 +18,7 @@ import { waitFor } from '../wait_for'; * @param numberOfAlerts The number of alerts to wait for, default is 1 */ export const waitForAlertsToBePresent = async ( - supertest: SuperTest.SuperTest, + supertest: SuperTest.Agent, log: ToolingLog, numberOfAlerts = 1, alertIds: string[], diff --git a/x-pack/test/common/utils/security_solution/detections_response/rules/create_rule.ts b/x-pack/test/common/utils/security_solution/detections_response/rules/create_rule.ts index ac6e44b2aab83..b1fe58770abfd 100644 --- a/x-pack/test/common/utils/security_solution/detections_response/rules/create_rule.ts +++ b/x-pack/test/common/utils/security_solution/detections_response/rules/create_rule.ts @@ -27,7 +27,7 @@ import { routeWithNamespace } from '../route_with_namespace'; * @param rule The rule to create */ export const createRule = async ( - supertest: SuperTest.SuperTest, + supertest: SuperTest.Agent, log: ToolingLog, rule: RuleCreateProps, namespace?: string diff --git a/x-pack/test/common/utils/security_solution/detections_response/rules/delete_all_rules.ts b/x-pack/test/common/utils/security_solution/detections_response/rules/delete_all_rules.ts index 8fe87827e4e25..66bf65ccfbc20 100644 --- a/x-pack/test/common/utils/security_solution/detections_response/rules/delete_all_rules.ts +++ b/x-pack/test/common/utils/security_solution/detections_response/rules/delete_all_rules.ts @@ -19,7 +19,7 @@ import { countDownTest } from '../count_down_test'; * @param supertest The supertest agent. */ export const deleteAllRules = async ( - supertest: SuperTest.SuperTest, + supertest: SuperTest.Agent, log: ToolingLog ): Promise => { await countDownTest( diff --git a/x-pack/test/common/utils/security_solution/detections_response/rules/delete_rule.ts b/x-pack/test/common/utils/security_solution/detections_response/rules/delete_rule.ts index f4eff397aba0b..5b3e28f05e093 100644 --- a/x-pack/test/common/utils/security_solution/detections_response/rules/delete_rule.ts +++ b/x-pack/test/common/utils/security_solution/detections_response/rules/delete_rule.ts @@ -17,7 +17,7 @@ import { DETECTION_ENGINE_RULES_URL } from '@kbn/security-solution-plugin/common * @param ruleId The rule id to delete */ export const deleteRule = async ( - supertest: SuperTest.SuperTest, + supertest: SuperTest.Agent, ruleId: string ): Promise => { const response = await supertest diff --git a/x-pack/test/common/utils/security_solution/detections_response/rules/wait_for_rule_status.ts b/x-pack/test/common/utils/security_solution/detections_response/rules/wait_for_rule_status.ts index af0838b29613d..975b8dbef3b72 100644 --- a/x-pack/test/common/utils/security_solution/detections_response/rules/wait_for_rule_status.ts +++ b/x-pack/test/common/utils/security_solution/detections_response/rules/wait_for_rule_status.ts @@ -16,7 +16,7 @@ import { waitFor } from '../wait_for'; import { routeWithNamespace } from '../route_with_namespace'; interface WaitForRuleStatusBaseParams { - supertest: SuperTest.SuperTest; + supertest: SuperTest.Agent; log: ToolingLog; afterDate?: Date; namespace?: string; diff --git a/x-pack/test/common/utils/synthtrace/infra_es_client.ts b/x-pack/test/common/utils/synthtrace/infra_es_client.ts new file mode 100644 index 0000000000000..7e39942a9a46c --- /dev/null +++ b/x-pack/test/common/utils/synthtrace/infra_es_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 { Client } from '@elastic/elasticsearch'; +import { InfraSynthtraceEsClient, createLogger, LogLevel } from '@kbn/apm-synthtrace'; + +export async function getInfraSynthtraceEsClient(client: Client) { + return new InfraSynthtraceEsClient({ + client, + logger: createLogger(LogLevel.info), + refreshAfterIndex: true, + }); +} diff --git a/x-pack/test/dataset_quality_api_integration/common/dataset_quality_api_supertest.ts b/x-pack/test/dataset_quality_api_integration/common/dataset_quality_api_supertest.ts index 79818e970a2ab..66823c794b017 100644 --- a/x-pack/test/dataset_quality_api_integration/common/dataset_quality_api_supertest.ts +++ b/x-pack/test/dataset_quality_api_integration/common/dataset_quality_api_supertest.ts @@ -12,7 +12,7 @@ import type { APIEndpoint } from '@kbn/dataset-quality-plugin/server/routes'; import { formatRequest } from '@kbn/server-route-repository'; import type { APIClientRequestParamsOf, APIReturnType } from '@kbn/dataset-quality-plugin/common'; -export function createDatasetQualityApiClient(st: supertest.SuperTest) { +export function createDatasetQualityApiClient(st: supertest.Agent) { return async ( options: { type?: 'form-data'; diff --git a/x-pack/test/dataset_quality_api_integration/tests/integrations/package_utils.ts b/x-pack/test/dataset_quality_api_integration/tests/integrations/package_utils.ts index 4aa403ee6d62a..ae2b9a01fa475 100644 --- a/x-pack/test/dataset_quality_api_integration/tests/integrations/package_utils.ts +++ b/x-pack/test/dataset_quality_api_integration/tests/integrations/package_utils.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { SuperTest, Test } from 'supertest'; +import { Agent as SuperTestAgent } from 'supertest'; export interface IntegrationPackage { name: string; @@ -26,7 +26,7 @@ export async function installCustomIntegration({ supertest, customIntegration, }: { - supertest: SuperTest; + supertest: SuperTestAgent; customIntegration: CustomIntegration; }) { const { integrationName, datasets } = customIntegration; @@ -41,7 +41,7 @@ export async function installPackage({ supertest, pkg, }: { - supertest: SuperTest; + supertest: SuperTestAgent; pkg: IntegrationPackage; }) { const { name, version } = pkg; @@ -56,7 +56,7 @@ export async function uninstallPackage({ supertest, pkg, }: { - supertest: SuperTest; + supertest: SuperTestAgent; pkg: IntegrationPackage; }) { const { name, version } = pkg; diff --git a/x-pack/test/fleet_api_integration/apis/agents/actions.ts b/x-pack/test/fleet_api_integration/apis/agents/actions.ts index 0e592cf9281fd..57b367f8c4bd0 100644 --- a/x-pack/test/fleet_api_integration/apis/agents/actions.ts +++ b/x-pack/test/fleet_api_integration/apis/agents/actions.ts @@ -26,7 +26,7 @@ export default function (providerContext: FtrProviderContext) { }); describe('POST /agents/{agentId}/actions', () => { - it('should return a 200 if this a valid SETTINGS action request', async () => { + it('should return a 200 if this a SETTINGS action request with a valid log level', async () => { const { body: apiResponse } = await supertest .post(`/api/fleet/agents/agent1/actions`) .set('kbn-xsrf', 'xx') @@ -42,7 +42,23 @@ export default function (providerContext: FtrProviderContext) { expect(apiResponse.item.data).to.eql({ log_level: 'debug' }); }); - it('should return a 400 if this a invalid SETTINGS action request', async () => { + it('should return a 200 if this a SETTINGS action request with null log level', async () => { + const { body: apiResponse } = await supertest + .post(`/api/fleet/agents/agent1/actions`) + .set('kbn-xsrf', 'xx') + .send({ + action: { + type: 'SETTINGS', + data: { log_level: null }, + }, + }) + .expect(200); + + expect(apiResponse.item.type).to.eql('SETTINGS'); + expect(apiResponse.item.data).to.eql({ log_level: null }); + }); + + it('should return a 400 if this a SETTINGS action request with an invalid log level', async () => { const { body: apiResponse } = await supertest .post(`/api/fleet/agents/agent1/actions`) .set('kbn-xsrf', 'xx') diff --git a/x-pack/test/fleet_api_integration/apis/epm/install_by_upload.ts b/x-pack/test/fleet_api_integration/apis/epm/install_by_upload.ts index f086ad8785d8d..6fe31c67c65a2 100644 --- a/x-pack/test/fleet_api_integration/apis/epm/install_by_upload.ts +++ b/x-pack/test/fleet_api_integration/apis/epm/install_by_upload.ts @@ -9,6 +9,7 @@ import fs from 'fs'; import path from 'path'; import expect from '@kbn/expect'; import { INGEST_SAVED_OBJECT_INDEX } from '@kbn/core-saved-objects-server'; +import { HTTPError } from 'superagent'; import { FtrProviderContext } from '../../../api_integration/ftr_provider_context'; import { skipIfNoDockerRegistry } from '../../helpers'; @@ -167,7 +168,7 @@ export default function (providerContext: FtrProviderContext) { .type('application/gzip') .send(buf) .expect(400); - expect(res.error.text).to.equal( + expect((res.error as HTTPError).text).to.equal( '{"statusCode":400,"error":"Bad Request","message":"Archive seems empty. Assumed content type was application/gzip, check if this matches the archive type."}' ); }); @@ -180,7 +181,7 @@ export default function (providerContext: FtrProviderContext) { .type('application/zip') .send(buf) .expect(400); - expect(res.error.text).to.equal( + expect((res.error as HTTPError).text).to.equal( '{"statusCode":400,"error":"Bad Request","message":"Error during extraction of package: Error: end of central directory record signature not found. Assumed content type was application/zip, check if this matches the archive type."}' ); }); @@ -193,7 +194,7 @@ export default function (providerContext: FtrProviderContext) { .type('application/zip') .send(buf) .expect(400); - expect(res.error.text).to.equal( + expect((res.error as HTTPError).text).to.equal( '{"statusCode":400,"error":"Bad Request","message":"Package contains more than one top-level directory; top-level directory found: apache-0.1.4; filePath: apache-0.1.3/manifest.yml"}' ); }); @@ -206,7 +207,7 @@ export default function (providerContext: FtrProviderContext) { .type('application/zip') .send(buf) .expect(400); - expect(res.error.text).to.equal( + expect((res.error as HTTPError).text).to.equal( '{"statusCode":400,"error":"Bad Request","message":"Manifest file apache-0.1.4/manifest.yml not found in paths."}' ); }); @@ -219,7 +220,7 @@ export default function (providerContext: FtrProviderContext) { .type('application/zip') .send(buf) .expect(400); - expect(res.error.text).to.equal( + expect((res.error as HTTPError).text).to.equal( '{"statusCode":400,"error":"Bad Request","message":"Could not parse top-level package manifest at top-level directory apache-0.1.4: YAMLException: bad indentation of a mapping entry at line 2, column 7:\\n name: apache\\n ^."}' ); }); @@ -232,7 +233,7 @@ export default function (providerContext: FtrProviderContext) { .type('application/zip') .send(buf) .expect(400); - expect(res.error.text).to.equal( + expect((res.error as HTTPError).text).to.equal( '{"statusCode":400,"error":"Bad Request","message":"Invalid top-level package manifest at top-level directory apache-0.1.4 (package name: apache): one or more fields missing of name, version, description, title, format_version, owner."}' ); }); @@ -245,7 +246,7 @@ export default function (providerContext: FtrProviderContext) { .type('application/zip') .send(buf) .expect(400); - expect(res.error.text).to.equal( + expect((res.error as HTTPError).text).to.equal( '{"statusCode":400,"error":"Bad Request","message":"Name thisIsATypo and version 0.1.4 do not match top-level directory apache-0.1.4"}' ); }); diff --git a/x-pack/test/fleet_api_integration/helpers.ts b/x-pack/test/fleet_api_integration/helpers.ts index bf8729dba368b..2d9febe190892 100644 --- a/x-pack/test/fleet_api_integration/helpers.ts +++ b/x-pack/test/fleet_api_integration/helpers.ts @@ -15,7 +15,7 @@ import { } from '@kbn/fleet-plugin/common'; import { KbnClient } from '@kbn/test'; import { UNINSTALL_TOKENS_SAVED_OBJECT_TYPE } from '@kbn/fleet-plugin/common'; -import { SuperTest, Test } from 'supertest'; +import { Agent as SuperTestAgent } from 'supertest'; import { FtrProviderContext } from '../api_integration/ftr_provider_context'; export function warnAndSkipTest(mochaContext: Mocha.Context, log: ToolingLog) { @@ -109,7 +109,7 @@ export async function generateAgent( }); } -export function setPrereleaseSetting(supertest: SuperTest) { +export function setPrereleaseSetting(supertest: SuperTestAgent) { before(async () => { await supertest .put('/api/fleet/settings') @@ -126,7 +126,7 @@ export function setPrereleaseSetting(supertest: SuperTest) { } export const generateNAgentPolicies = async ( - supertest: SuperTest, + supertest: SuperTestAgent, number: number, overwrite?: Partial ): Promise => { @@ -142,7 +142,7 @@ export const generateNAgentPolicies = async ( }; export const generateAgentPolicy = async ( - supertest: SuperTest, + supertest: SuperTestAgent, overwrite?: Partial ): Promise => { const response = await supertest diff --git a/x-pack/test/functional/apps/dashboard/group3/reporting/screenshots.ts b/x-pack/test/functional/apps/dashboard/group3/reporting/screenshots.ts index e250d5972247b..d7bd90c5e74d6 100644 --- a/x-pack/test/functional/apps/dashboard/group3/reporting/screenshots.ts +++ b/x-pack/test/functional/apps/dashboard/group3/reporting/screenshots.ts @@ -155,7 +155,8 @@ export default function ({ }); }); - describe('Preserve Layout', () => { + // FLAKY: https://github.com/elastic/kibana/issues/183566 + describe.skip('Preserve Layout', () => { before(async () => { await loadEcommerce(); }); diff --git a/x-pack/test/functional/apps/infra/constants.ts b/x-pack/test/functional/apps/infra/constants.ts index fcead1cf9dc26..4c1d0d29a6ca4 100644 --- a/x-pack/test/functional/apps/infra/constants.ts +++ b/x-pack/test/functional/apps/infra/constants.ts @@ -51,7 +51,11 @@ export const ML_JOB_IDS = [ export const HOSTS_LINK_LOCAL_STORAGE_KEY = 'inventoryUI:hostsLinkClicked'; export const INVENTORY_PATH = 'metrics/inventory'; -export const NODE_DETAILS_PATH = 'detail/host'; +export const NODE_DETAILS_PATH = 'detail'; export const HOSTS_VIEW_PATH = 'metrics/hosts'; export const DATE_PICKER_FORMAT = 'MMM D, YYYY @ HH:mm:ss.SSS'; + +export const DATE_WITH_DOCKER_DATA_FROM = '2023-03-28T18:20:00.000Z'; +export const DATE_WITH_DOCKER_DATA_TO = '2023-03-28T18:21:00.000Z'; +export const DATE_WITH_DOCKER_DATA = '03/28/2023 6:20:59 PM'; diff --git a/x-pack/test/functional/apps/infra/helpers.ts b/x-pack/test/functional/apps/infra/helpers.ts index 51356acadf146..2ddabf314390f 100644 --- a/x-pack/test/functional/apps/infra/helpers.ts +++ b/x-pack/test/functional/apps/infra/helpers.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { apm, timerange } from '@kbn/apm-synthtrace-client'; +import { apm, timerange, infra } from '@kbn/apm-synthtrace-client'; const SERVICE_PREFIX = 'service'; // generates traces, metrics for services @@ -46,3 +46,26 @@ export function generateAddServicesToExistingHost({ ) ); } + +export function generateDockerContainersData({ + from, + to, + count = 1, +}: { + from: string; + to: string; + count?: number; +}) { + const range = timerange(from, to); + + const containers = Array(count) + .fill(0) + .map((_, idx) => infra.dockerContainer(`container-id-${idx}`)); + + return range + .interval('30s') + .rate(1) + .generator((timestamp) => + containers.flatMap((container) => container.metrics().timestamp(timestamp)) + ); +} diff --git a/x-pack/test/functional/apps/infra/home_page.ts b/x-pack/test/functional/apps/infra/home_page.ts index df22e6ac8ccba..5e0dd1d36d50f 100644 --- a/x-pack/test/functional/apps/infra/home_page.ts +++ b/x-pack/test/functional/apps/infra/home_page.ts @@ -8,17 +8,25 @@ import expect from '@kbn/expect'; import { parse } from 'url'; import { KUBERNETES_TOUR_STORAGE_KEY } from '@kbn/infra-plugin/public/pages/metrics/inventory_view/components/kubernetes_tour'; +import { InfraSynthtraceEsClient } from '@kbn/apm-synthtrace'; import { FtrProviderContext } from '../../ftr_provider_context'; import { DATES, INVENTORY_PATH } from './constants'; +import { generateDockerContainersData } from './helpers'; +import { getInfraSynthtraceEsClient } from '../../../common/utils/synthtrace/infra_es_client'; const DATE_WITH_DATA = DATES.metricsAndLogs.hosts.withData; const DATE_WITHOUT_DATA = DATES.metricsAndLogs.hosts.withoutData; const DATE_WITH_POD_WITH_DATA = DATES.metricsAndLogs.pods.withData; +const DATE_WITH_DOCKER_DATA_FROM = '2023-03-28T18:20:00.000Z'; +const DATE_WITH_DOCKER_DATA_TO = '2023-03-28T18:21:00.000Z'; +const DATE_WITH_DOCKER_DATA = '03/28/2023 6:20:00 PM'; export default ({ getPageObjects, getService }: FtrProviderContext) => { const esArchiver = getService('esArchiver'); const browser = getService('browser'); const retry = getService('retry'); + const esClient = getService('es'); + const infraSynthtraceKibanaClient = getService('infraSynthtraceKibanaClient'); const pageObjects = getPageObjects([ 'common', 'header', @@ -355,7 +363,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { await returnTo(INVENTORY_PATH); }); - it('Should redirect to Node Details page', async () => { + it('Should redirect to Pod Details page', async () => { await pageObjects.infraHome.goToPods(); await pageObjects.infraHome.goToTime(DATE_WITH_POD_WITH_DATA); await pageObjects.infraHome.clickOnFirstNode(); @@ -370,6 +378,41 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { await returnTo(INVENTORY_PATH); }); + + describe('Redirect to Container Details page', () => { + let synthEsClient: InfraSynthtraceEsClient; + before(async () => { + const version = await infraSynthtraceKibanaClient.fetchLatestSystemPackageVersion(); + await infraSynthtraceKibanaClient.installSystemPackage(version); + synthEsClient = await getInfraSynthtraceEsClient(esClient); + await synthEsClient.index( + generateDockerContainersData({ + from: DATE_WITH_DOCKER_DATA_FROM, + to: DATE_WITH_DOCKER_DATA_TO, + count: 5, + }) + ); + }); + + after(async () => { + return await synthEsClient.clean(); + }); + it('Should redirect to Container Details page', async () => { + await pageObjects.infraHome.goToContainer(); + await pageObjects.infraHome.goToTime(DATE_WITH_DOCKER_DATA); + await pageObjects.infraHome.clickOnFirstNode(); + await pageObjects.infraHome.clickOnGoToNodeDetails(); + + await retry.try(async () => { + const documentTitle = await browser.getTitle(); + expect(documentTitle).to.contain( + 'container-id-4 - Inventory - Infrastructure - Observability - Elastic' + ); + }); + + await returnTo(INVENTORY_PATH); + }); + }); }); }); diff --git a/x-pack/test/functional/apps/infra/node_details.ts b/x-pack/test/functional/apps/infra/node_details.ts index 88a8dfe9b2aa2..47792ec4bb2ba 100644 --- a/x-pack/test/functional/apps/infra/node_details.ts +++ b/x-pack/test/functional/apps/infra/node_details.ts @@ -7,14 +7,26 @@ import moment from 'moment'; import expect from '@kbn/expect'; -import { enableInfrastructureProfilingIntegration } from '@kbn/observability-plugin/common'; +import { InfraSynthtraceEsClient } from '@kbn/apm-synthtrace'; +import { + enableInfrastructureContainerAssetView, + enableInfrastructureProfilingIntegration, +} from '@kbn/observability-plugin/common'; import { ALERT_STATUS_ACTIVE, ALERT_STATUS_RECOVERED, ALERT_STATUS_UNTRACKED, } from '@kbn/rule-data-utils'; import { FtrProviderContext } from '../../ftr_provider_context'; -import { DATES, NODE_DETAILS_PATH, DATE_PICKER_FORMAT } from './constants'; +import { + DATES, + NODE_DETAILS_PATH, + DATE_PICKER_FORMAT, + DATE_WITH_DOCKER_DATA_FROM, + DATE_WITH_DOCKER_DATA_TO, +} from './constants'; +import { getInfraSynthtraceEsClient } from '../../../common/utils/synthtrace/infra_es_client'; +import { generateDockerContainersData } from './helpers'; const START_HOST_ALERTS_DATE = moment.utc(DATES.metricsAndLogs.hosts.min); const END_HOST_ALERTS_DATE = moment.utc(DATES.metricsAndLogs.hosts.max); @@ -32,6 +44,8 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { const browser = getService('browser'); const kibanaServer = getService('kibanaServer'); const esArchiver = getService('esArchiver'); + const infraSynthtraceKibanaClient = getService('infraSynthtraceKibanaClient'); + const esClient = getService('es'); const retry = getService('retry'); const testSubjects = getService('testSubjects'); const pageObjects = getPageObjects([ @@ -50,10 +64,10 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { return queryParams.toString(); }; - const navigateToNodeDetails = async (assetId: string, assetName: string) => { + const navigateToNodeDetails = async (assetId: string, assetName: string, assetType: string) => { await pageObjects.common.navigateToUrlWithBrowserHistory( 'infraOps', - `/${NODE_DETAILS_PATH}/${assetId}`, + `/${NODE_DETAILS_PATH}/${assetType}/${assetId}`, getNodeDetailsUrl(assetName), { insertTimestamp: false, @@ -79,6 +93,12 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { await pageObjects.header.waitUntilLoadingHasFinished(); }; + const setInfrastructureContainerAssetViewUiSetting = async (value: boolean = true) => { + await kibanaServer.uiSettings.update({ [enableInfrastructureContainerAssetView]: value }); + await browser.refresh(); + await pageObjects.header.waitUntilLoadingHasFinished(); + }; + describe('Node Details', () => { describe('#With Asset Details', () => { before(async () => { @@ -90,7 +110,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { ]); await browser.setWindowSize(1600, 1200); - await navigateToNodeDetails('Jennys-MBP.fritz.box', 'Jennys-MBP.fritz.box'); + await navigateToNodeDetails('Jennys-MBP.fritz.box', 'Jennys-MBP.fritz.box', 'host'); await pageObjects.header.waitUntilLoadingHasFinished(); }); @@ -102,7 +122,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { ]); }); - describe('#Date picker', () => { + describe('#Date picker: host', () => { before(async () => { await pageObjects.assetDetails.clickOverviewTab(); @@ -247,7 +267,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { const ALL_ALERTS = ACTIVE_ALERTS + RECOVERED_ALERTS; const COLUMNS = 11; before(async () => { - await navigateToNodeDetails('demo-stack-apache-01', 'demo-stack-apache-01'); + await navigateToNodeDetails('demo-stack-apache-01', 'demo-stack-apache-01', 'host'); await pageObjects.header.waitUntilLoadingHasFinished(); await pageObjects.timePicker.setAbsoluteRange( @@ -259,7 +279,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { }); after(async () => { - await navigateToNodeDetails('Jennys-MBP.fritz.box', 'Jennys-MBP.fritz.box'); + await navigateToNodeDetails('Jennys-MBP.fritz.box', 'Jennys-MBP.fritz.box', 'host'); await pageObjects.header.waitUntilLoadingHasFinished(); await pageObjects.timePicker.setAbsoluteRange( @@ -482,7 +502,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { describe('Host with alerts and no processes', () => { before(async () => { - await navigateToNodeDetails('demo-stack-mysql-01', 'demo-stack-mysql-01'); + await navigateToNodeDetails('demo-stack-mysql-01', 'demo-stack-mysql-01', 'host'); await pageObjects.timePicker.setAbsoluteRange( START_HOST_ALERTS_DATE.format(DATE_PICKER_FORMAT), END_HOST_ALERTS_DATE.format(DATE_PICKER_FORMAT) @@ -516,7 +536,11 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { describe('#With Kubernetes section', () => { before(async () => { - await navigateToNodeDetails('demo-stack-kubernetes-01', 'demo-stack-kubernetes-01'); + await navigateToNodeDetails( + 'demo-stack-kubernetes-01', + 'demo-stack-kubernetes-01', + 'host' + ); await pageObjects.header.waitUntilLoadingHasFinished(); }); @@ -597,6 +621,57 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { }); }); }); + + describe('#Asset Type: container', () => { + let synthEsClient: InfraSynthtraceEsClient; + before(async () => { + const version = await infraSynthtraceKibanaClient.fetchLatestSystemPackageVersion(); + await infraSynthtraceKibanaClient.installSystemPackage(version); + synthEsClient = await getInfraSynthtraceEsClient(esClient); + await synthEsClient.index( + generateDockerContainersData({ + from: DATE_WITH_DOCKER_DATA_FROM, + to: DATE_WITH_DOCKER_DATA_TO, + count: 1, + }) + ); + }); + + after(async () => { + await synthEsClient.clean(); + }); + + describe('when container asset view is disabled', () => { + it('should show old view of container details', async () => { + await setInfrastructureContainerAssetViewUiSetting(false); + await navigateToNodeDetails('container-id-0', 'container-id-0', 'container'); + await pageObjects.header.waitUntilLoadingHasFinished(); + await testSubjects.find('metricsEmptyViewState'); + }); + }); + + describe('when container asset view is enabled', () => { + it('should show asset container details page', async () => { + await setInfrastructureContainerAssetViewUiSetting(true); + await navigateToNodeDetails('container-id-0', 'container-id-0', 'container'); + await pageObjects.header.waitUntilLoadingHasFinished(); + + await pageObjects.assetDetails.getOverviewTab(); + }); + + [ + { metric: 'cpu', chartsCount: 1 }, + { metric: 'memory', chartsCount: 1 }, + ].forEach(({ metric, chartsCount }) => { + it(`should render ${chartsCount} ${metric} chart(s) in the Metrics section`, async () => { + const charts = await pageObjects.assetDetails.getOverviewTabDockerMetricCharts( + metric + ); + expect(charts.length).to.equal(chartsCount); + }); + }); + }); + }); }); }); }; diff --git a/x-pack/test/functional/apps/observability_logs_explorer/columns_selection.ts b/x-pack/test/functional/apps/observability_logs_explorer/columns_selection.ts index d61ce9e734eba..1c64c85534d66 100644 --- a/x-pack/test/functional/apps/observability_logs_explorer/columns_selection.ts +++ b/x-pack/test/functional/apps/observability_logs_explorer/columns_selection.ts @@ -130,9 +130,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { expect(cellValue.includes('error.message')).to.be(false); expect(cellValue.includes('event.original')).to.be(false); - const cellAttribute = await cellElement.findByTestSubject( - 'logsExplorerCellDescriptionList' - ); + const cellAttribute = await cellElement.findByTestSubject('discoverCellDescriptionList'); expect(cellAttribute).not.to.be.empty(); }); }); diff --git a/x-pack/test/functional/apps/security/index.ts b/x-pack/test/functional/apps/security/index.ts index 009c270d3c2a3..a65db6d3d3cf8 100644 --- a/x-pack/test/functional/apps/security/index.ts +++ b/x-pack/test/functional/apps/security/index.ts @@ -18,5 +18,6 @@ export default function ({ loadTestFile }: FtrProviderContext) { loadTestFile(require.resolve('./user_email')); loadTestFile(require.resolve('./role_mappings')); loadTestFile(require.resolve('./remote_cluster_security_roles')); + loadTestFile(require.resolve('./role_description')); }); } diff --git a/x-pack/test/functional/apps/security/role_description.ts b/x-pack/test/functional/apps/security/role_description.ts new file mode 100644 index 0000000000000..eb272dec3d0a5 --- /dev/null +++ b/x-pack/test/functional/apps/security/role_description.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 expect from '@kbn/expect'; +import { FtrProviderContext } from '../../ftr_provider_context'; + +export default function ({ getService, getPageObjects }: FtrProviderContext) { + const testSubjects = getService('testSubjects'); + const security = getService('security'); + const PageObjects = getPageObjects(['security', 'settings', 'common', 'header']); + + describe('Role Description', function () { + before(async () => { + await security.testUser.setRoles(['cluster_security_manager']); + await PageObjects.security.initTests(); + await PageObjects.settings.navigateTo(); + await PageObjects.security.clickElasticsearchRoles(); + }); + + after(async () => { + // NOTE: Logout needs to happen before anything else to avoid flaky behavior + await PageObjects.security.forceLogout(); + await security.role.delete('a-role-with-description'); + await security.role.delete('a-role-without-description'); + await security.testUser.restoreDefaults(); + }); + + it('Can create role with description', async () => { + await PageObjects.security.clickCreateNewRole(); + await testSubjects.setValue('roleFormNameInput', 'a-role-with-description'); + await testSubjects.setValue('roleFormDescriptionInput', 'role description'); + await PageObjects.security.clickSaveEditRole(); + + const columnDescription = await testSubjects.getVisibleText( + 'roleRowDescription-a-role-with-description' + ); + expect(columnDescription).to.equal('role description'); + + await PageObjects.settings.clickLinkText('a-role-with-description'); + const name = await testSubjects.getAttribute('roleFormNameInput', 'value'); + const description = await testSubjects.getAttribute('roleFormDescriptionInput', 'value'); + + expect(name).to.equal('a-role-with-description'); + expect(description).to.equal('role description'); + + await PageObjects.security.clickCancelEditRole(); + }); + + it('Can create role without description', async () => { + await PageObjects.security.clickCreateNewRole(); + await testSubjects.setValue('roleFormNameInput', 'a-role-without-description'); + await PageObjects.security.clickSaveEditRole(); + + await PageObjects.settings.clickLinkText('a-role-without-description'); + const name = await testSubjects.getAttribute('roleFormNameInput', 'value'); + const description = await testSubjects.getAttribute('roleFormDescriptionInput', 'value'); + + expect(name).to.equal('a-role-without-description'); + expect(description).to.equal(''); + + await PageObjects.security.clickCancelEditRole(); + }); + }); +} diff --git a/x-pack/test/functional/page_objects/asset_details.ts b/x-pack/test/functional/page_objects/asset_details.ts index bbb5ebead305b..32efd9f315ad2 100644 --- a/x-pack/test/functional/page_objects/asset_details.ts +++ b/x-pack/test/functional/page_objects/asset_details.ts @@ -30,6 +30,10 @@ export function AssetDetailsProvider({ getService }: FtrProviderContext) { return testSubjects.click('infraAssetDetailsOverviewTab'); }, + async getOverviewTab() { + return testSubjects.find('infraAssetDetailsOverviewTab'); + }, + async getAssetDetailsKPITileValue(type: string) { const element = await testSubjects.find(`infraAssetDetailsKPI${type}`); const div = await element.findByClassName('echMetricText__value'); @@ -103,6 +107,15 @@ export function AssetDetailsProvider({ getService }: FtrProviderContext) { return section.findAllByCssSelector('[data-test-subj*="infraAssetDetailsMetricChart"]'); }, + async getOverviewTabDockerMetricCharts(metric: string) { + const container = await testSubjects.find('infraAssetDetailsOverviewTabContent'); + const section = await container.findByTestSubject( + `infraAssetDetailsDockerChartsSection${metric}` + ); + + return section.findAllByCssSelector('[data-test-subj*="infraAssetDetailsMetricChart"]'); + }, + async getOverviewTabKubernetesMetricCharts() { const container = await testSubjects.find('infraAssetDetailsOverviewTabContent'); const section = await container.findByTestSubject(`infraAssetDetailsKubernetesChartsSection`); diff --git a/x-pack/test/functional/page_objects/infra_home_page.ts b/x-pack/test/functional/page_objects/infra_home_page.ts index 68df8c69784a9..f112e76ee809a 100644 --- a/x-pack/test/functional/page_objects/infra_home_page.ts +++ b/x-pack/test/functional/page_objects/infra_home_page.ts @@ -212,10 +212,10 @@ export function InfraHomePageProvider({ getService, getPageObjects }: FtrProvide return testSubjects.click('goToPods'); }, - async goToDocker() { + async goToContainer() { await testSubjects.click('openInventorySwitcher'); await testSubjects.find('goToHost'); - return testSubjects.click('goToDocker'); + return testSubjects.click('goToContainer'); }, async goToSettings() { diff --git a/x-pack/test/functional/services/ml/api.ts b/x-pack/test/functional/services/ml/api.ts index 0d5cbfa47b00b..fdbbad01d003b 100644 --- a/x-pack/test/functional/services/ml/api.ts +++ b/x-pack/test/functional/services/ml/api.ts @@ -226,6 +226,32 @@ export function MachineLearningAPIProvider({ getService }: FtrProviderContext) { ); }, + async getInferenceEndpoint(inferenceId: string) { + const { status } = await esSupertest.get(`/_inference/${inferenceId}`); + return status === 200; + }, + + async createInferenceEndpoint(inferenceId: string, taskType: string, requestBody: object) { + const found = await this.getInferenceEndpoint(inferenceId); + if (found) { + log.debug(`Inference endpoint '${inferenceId}' already exists. Nothing to create.`); + return; + } + const { body, status } = await esSupertest + .put(`/_inference/${taskType}/${inferenceId}`) + .send(requestBody); + this.assertResponseStatusCode(200, status, body); + + return body; + }, + + async deleteInferenceEndpoint(inferenceId: string, taskType: string) { + const { body, status } = await esSupertest.delete(`/_inference/${taskType}/${inferenceId}`); + this.assertResponseStatusCode(200, status, body); + + return body; + }, + async createIndex( indices: string, mappings?: Record | estypes.MappingTypeMapping, diff --git a/x-pack/test/functional/services/transform/api.ts b/x-pack/test/functional/services/transform/api.ts index 5aad29fff8942..15751c91253ec 100644 --- a/x-pack/test/functional/services/transform/api.ts +++ b/x-pack/test/functional/services/transform/api.ts @@ -237,7 +237,7 @@ export function TransformAPIProvider({ getService }: FtrProviderContext) { ); const { body, status } = await esSupertest .put(`/_transform/${transformId}${deferValidation ? '?defer_validation=true' : ''}`) - .set(headers) + .set(headers as Record) .send(transformConfig); this.assertResponseStatusCode(200, status, body); } else { diff --git a/x-pack/test/functional_with_es_ssl/apps/cases/group2/attachment_framework.ts b/x-pack/test/functional_with_es_ssl/apps/cases/group2/attachment_framework.ts index c45df81316e81..876e4d2123019 100644 --- a/x-pack/test/functional_with_es_ssl/apps/cases/group2/attachment_framework.ts +++ b/x-pack/test/functional_with_es_ssl/apps/cases/group2/attachment_framework.ts @@ -24,7 +24,7 @@ import { import { FtrProviderContext } from '../../../ftr_provider_context'; const createLogStashDataView = async ( - supertest: SuperTest.SuperTest + supertest: SuperTest.Agent ): Promise<{ data_view: { id: string } }> => { const { body } = await supertest .post(`/api/data_views/data_view`) @@ -36,7 +36,7 @@ const createLogStashDataView = async ( }; const deleteLogStashDataView = async ( - supertest: SuperTest.SuperTest, + supertest: SuperTest.Agent, dataViewId: string ): Promise => { await supertest diff --git a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/alerts_page.ts b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/alerts_page.ts index 8223a5d0d29b1..6fd04fdaa23c9 100644 --- a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/alerts_page.ts +++ b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/alerts_page.ts @@ -25,9 +25,9 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { const security = getService('security'); const pageObjects = getPageObjects(['common', 'triggersActionsUI', 'header']); const log = getService('log'); + const retry = getService('retry'); - // Failing: See https://github.com/elastic/kibana/issues/181795 - describe.skip('Stack alerts page', function () { + describe('Stack alerts page', function () { describe('Loads the page with limited privileges', () => { beforeEach(async () => { await security.testUser.restoreDefaults(); @@ -54,13 +54,20 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { shouldUseHashForSubUrl: false, } ); - await pageObjects.triggersActionsUI.clickAlertsPageShowQueryMenuButton(); - const quickFilters = await pageObjects.triggersActionsUI.getAlertsPageQuickFilters(); - const solutionFilters = getSolutionNamesFromFilters(quickFilters); - expect(solutionFilters).to.have.length(2); - expect(solutionFilters[0]).to.equal('Stack management'); - // Observability is included because of multi-consumer rules - expect(solutionFilters[1]).to.equal('Observability'); + + await pageObjects.header.waitUntilLoadingHasFinished(); + + await retry.try(async () => { + if (!(await testSubjects.exists('queryBarMenuPanel'))) { + await pageObjects.triggersActionsUI.clickAlertsPageShowQueryMenuButton(); + } + const quickFilters = await pageObjects.triggersActionsUI.getAlertsPageQuickFilters(); + const solutionFilters = getSolutionNamesFromFilters(quickFilters); + expect(solutionFilters).to.have.length(2); + expect(solutionFilters[0]).to.equal('Stack management'); + // Observability is included because of multi-consumer rules + expect(solutionFilters[1]).to.equal('Observability'); + }); }); }); diff --git a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/connectors/utils.ts b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/connectors/utils.ts index 09dffef846cd5..e96ec17eb9c2e 100644 --- a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/connectors/utils.ts +++ b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/connectors/utils.ts @@ -48,10 +48,7 @@ export const createSlackConnector = async ({ return connector; }; -export const getConnectorByName = async ( - name: string, - supertest: SuperTest.SuperTest -) => { +export const getConnectorByName = async (name: string, supertest: SuperTest.Agent) => { const { body } = await supertest .get(`/api/actions/connectors`) .set('kbn-xsrf', 'foo') @@ -65,7 +62,7 @@ export async function createRuleWithActionsAndParams( testRunUuid: string, params: Record = {}, overwrites: Record = {}, - supertest: SuperTest.SuperTest + supertest: SuperTest.Agent ) { return await createAlwaysFiringRule( { @@ -94,7 +91,7 @@ export async function createRuleWithActionsAndParams( async function createAlwaysFiringRule( overwrites: Record = {}, - supertest: SuperTest.SuperTest + supertest: SuperTest.Agent ) { const { body: createdRule } = await supertest .post(`/api/alerting/rule`) @@ -109,10 +106,7 @@ async function createAlwaysFiringRule( return createdRule; } -export async function getAlertSummary( - ruleId: string, - supertest: SuperTest.SuperTest -) { +export async function getAlertSummary(ruleId: string, supertest: SuperTest.Agent) { const { body: summary } = await supertest .get(`/internal/alerting/rule/${encodeURIComponent(ruleId)}/_alert_summary`) .expect(200); diff --git a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/details.ts b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/details.ts index 3aee927ffcfd2..b71f659b10baa 100644 --- a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/details.ts +++ b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/details.ts @@ -987,46 +987,44 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { }); }); - // FLAKY: https://github.com/elastic/kibana/issues/173666 - describe.skip('Execution log', () => { + describe('Execution log', () => { const testRunUuid = uuidv4(); - let rule: any; - before(async () => { + after(async () => { + await objectRemover.removeAll(); + }); + + it('renders the event log list and can filter/sort', async () => { await pageObjects.common.navigateToApp('triggersActions'); + await testSubjects.click('rulesTab'); const alerts = [{ id: 'us-central' }]; - rule = await createRuleWithActionsAndParams( - testRunUuid, - { - instances: alerts, - }, - { - schedule: { interval: '1s' }, - } - ); - - // refresh to see rule - await browser.refresh(); - await pageObjects.header.waitUntilLoadingHasFinished(); - - // click on first rule - await pageObjects.triggersActionsUI.clickOnAlertInAlertsList(rule.name); + const rule = await createRuleWithActionsAndParams(testRunUuid, { + instances: alerts, + }); - // await first run to complete so we have an initial state await retry.try(async () => { const { alerts: alertInstances } = await getAlertSummary(rule.id); expect(Object.keys(alertInstances).length).to.eql(alerts.length); }); - }); - after(async () => { - await objectRemover.removeAll(); - }); + // Run again to generate some event logs + await retry.try(async () => { + await supertest + .post(`/internal/alerting/rule/${rule.id}/_run_soon`) + .set('kbn-xsrf', 'foo') + .expect(204); + }); + + await pageObjects.common.navigateToApp('triggersActions'); + await testSubjects.click('rulesTab'); + await pageObjects.header.waitUntilLoadingHasFinished(); + + await pageObjects.triggersActionsUI.clickOnAlertInAlertsList(rule.name); + await pageObjects.header.waitUntilLoadingHasFinished(); - it('renders the event log list and can filter/sort', async () => { - await browser.refresh(); await (await testSubjects.find('eventLogListTab')).click(); + await pageObjects.header.waitUntilLoadingHasFinished(); // Check to see if the experimental is enabled, if not, just return const tabbedContentExists = await testSubjects.exists('ruleDetailsTabbedContent'); @@ -1034,12 +1032,6 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { return; } - // Ensure we have some log data to work with - await new Promise((resolve) => setTimeout(resolve, 5000)); - - const refreshButton = await testSubjects.find('superDatePickerApplyTimeButton'); - await refreshButton.click(); - // List, date picker, and status picker all exists await testSubjects.existOrFail('eventLogList'); await testSubjects.existOrFail('ruleEventLogListDatePicker'); @@ -1051,7 +1043,10 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { expect(statusNumber.getVisibleText()).to.eql(0); await statusFilter.click(); + await testSubjects.click('eventLogStatusFilter-success'); + await pageObjects.header.waitUntilLoadingHasFinished(); + await statusFilter.click(); statusFilter = await testSubjects.find('eventLogStatusFilterButton'); diff --git a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/rules_list/bulk_actions.ts b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/rules_list/bulk_actions.ts index 740cbd4f78e20..109289e76a570 100644 --- a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/rules_list/bulk_actions.ts +++ b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/rules_list/bulk_actions.ts @@ -35,8 +35,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { await testSubjects.click('rulesTab'); } - // Failing: See https://github.com/elastic/kibana/issues/177130 - describe.skip('rules list bulk actions', () => { + describe('rules list bulk actions', () => { before(async () => { await pageObjects.common.navigateToApp('triggersActions'); await testSubjects.click('rulesTab'); @@ -59,12 +58,15 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { }); await refreshAlertsList(); + await pageObjects.header.waitUntilLoadingHasFinished(); + await testSubjects.click(`checkboxSelectRow-${rule1.id}`); await testSubjects.click(`checkboxSelectRow-${rule2.id}`); await testSubjects.click('showBulkActionButton'); await testSubjects.click('bulkSnooze'); await testSubjects.existOrFail('snoozePanel'); await testSubjects.click('linkSnooze1h'); + await pageObjects.header.waitUntilLoadingHasFinished(); await retry.try(async () => { const toastTitle = await toasts.getTitleAndDismiss(); @@ -72,8 +74,11 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { }); await pageObjects.triggersActionsUI.searchAlerts(rule1.name); + await pageObjects.header.waitUntilLoadingHasFinished(); await testSubjects.existOrFail('rulesListNotifyBadge-snoozed'); + await pageObjects.triggersActionsUI.searchAlerts(rule2.name); + await pageObjects.header.waitUntilLoadingHasFinished(); await testSubjects.existOrFail('rulesListNotifyBadge-snoozed'); }); @@ -98,12 +103,15 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { }); await refreshAlertsList(); + await pageObjects.header.waitUntilLoadingHasFinished(); + await testSubjects.click(`checkboxSelectRow-${rule1.id}`); await testSubjects.click(`checkboxSelectRow-${rule2.id}`); await testSubjects.click('showBulkActionButton'); await testSubjects.click('bulkUnsnooze'); await testSubjects.existOrFail('bulkUnsnoozeConfirmationModal'); await testSubjects.click('confirmModalConfirmButton'); + await pageObjects.header.waitUntilLoadingHasFinished(); await retry.try(async () => { const toastTitle = await toasts.getTitleAndDismiss(); @@ -111,12 +119,15 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { }); await pageObjects.triggersActionsUI.searchAlerts(rule1.name); + await pageObjects.header.waitUntilLoadingHasFinished(); await testSubjects.missingOrFail('rulesListNotifyBadge-snoozed'); + await pageObjects.triggersActionsUI.searchAlerts(rule2.name); + await pageObjects.header.waitUntilLoadingHasFinished(); await testSubjects.missingOrFail('rulesListNotifyBadge-snoozed'); }); - it('should allow rules to be scheduled', async () => { + it('should allow rule snooze to be scheduled', async () => { const rule1 = await createAlert({ supertest, objectRemover, @@ -129,6 +140,8 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { }); await refreshAlertsList(); + await pageObjects.header.waitUntilLoadingHasFinished(); + await testSubjects.click(`checkboxSelectRow-${rule1.id}`); await testSubjects.click(`checkboxSelectRow-${rule2.id}`); await testSubjects.click('showBulkActionButton'); @@ -136,14 +149,18 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { await testSubjects.existOrFail('ruleSnoozeScheduler'); await testSubjects.click('scheduler-saveSchedule'); + await pageObjects.header.waitUntilLoadingHasFinished(); + await retry.try(async () => { const toastTitle = await toasts.getTitleAndDismiss(); expect(toastTitle).to.eql('Updated snooze settings for 2 rules.'); }); await pageObjects.triggersActionsUI.searchAlerts(rule1.name); + await pageObjects.header.waitUntilLoadingHasFinished(); await testSubjects.existOrFail('rulesListNotifyBadge-scheduled'); await pageObjects.triggersActionsUI.searchAlerts(rule2.name); + await pageObjects.header.waitUntilLoadingHasFinished(); await testSubjects.existOrFail('rulesListNotifyBadge-scheduled'); }); @@ -168,21 +185,25 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { }); await refreshAlertsList(); + await pageObjects.header.waitUntilLoadingHasFinished(); + await testSubjects.click(`checkboxSelectRow-${rule1.id}`); await testSubjects.click(`checkboxSelectRow-${rule2.id}`); await testSubjects.click('showBulkActionButton'); await testSubjects.click('bulkRemoveSnoozeSchedule'); await testSubjects.existOrFail('bulkRemoveScheduleConfirmationModal'); await testSubjects.click('confirmModalConfirmButton'); + await pageObjects.header.waitUntilLoadingHasFinished(); - await retry.try(async () => { - const toastTitle = await toasts.getTitleAndDismiss(); - expect(toastTitle).to.eql('Updated snooze settings for 2 rules.'); - }); + const toastTitle = await toasts.getTitleAndDismiss(); + expect(toastTitle).to.eql('Updated snooze settings for 2 rules.'); await pageObjects.triggersActionsUI.searchAlerts(rule1.name); + await pageObjects.header.waitUntilLoadingHasFinished(); await testSubjects.missingOrFail('rulesListNotifyBadge-scheduled'); + await pageObjects.triggersActionsUI.searchAlerts(rule2.name); + await pageObjects.header.waitUntilLoadingHasFinished(); await testSubjects.missingOrFail('rulesListNotifyBadge-scheduled'); }); @@ -199,6 +220,8 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { }); await refreshAlertsList(); + await pageObjects.header.waitUntilLoadingHasFinished(); + await testSubjects.click(`checkboxSelectRow-${rule1.id}`); await testSubjects.click('selectAllRulesButton'); await testSubjects.click(`checkboxSelectRow-${rule2.id}`); @@ -206,11 +229,10 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { await testSubjects.click('updateAPIKeys'); await testSubjects.existOrFail('updateApiKeyIdsConfirmation'); await testSubjects.click('confirmModalConfirmButton'); + await pageObjects.header.waitUntilLoadingHasFinished(); - await retry.try(async () => { - const toastTitle = await toasts.getTitleAndDismiss(); - expect(toastTitle).to.eql('Updated API key for 1 rule.'); - }); + const toastTitle = await toasts.getTitleAndDismiss(); + expect(toastTitle).to.eql('Updated API key for 1 rule.'); }); it('should apply filters to bulk actions when using the select all button', async () => { @@ -230,11 +252,15 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { }); await refreshAlertsList(); + await pageObjects.header.waitUntilLoadingHasFinished(); + expect(await testSubjects.getVisibleText('totalRulesCount')).to.be('3 rules'); await testSubjects.click('ruleTypeFilterButton'); - await testSubjects.existOrFail('ruleTypetest.noopFilterOption'); await testSubjects.click('ruleTypetest.noopFilterOption'); + await pageObjects.header.waitUntilLoadingHasFinished(); + await testSubjects.click('ruleTypeFilterButton'); + await testSubjects.click(`checkboxSelectRow-${rule1.id}`); await testSubjects.click('selectAllRulesButton'); @@ -242,28 +268,37 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { await testSubjects.click('bulkDisable'); await testSubjects.existOrFail('untrackAlertsModal'); await testSubjects.click('confirmModalConfirmButton'); + await pageObjects.header.waitUntilLoadingHasFinished(); - await retry.try(async () => { - const toastTitle = await toasts.getTitleAndDismiss(); - expect(toastTitle).to.eql('Disabled 2 rules'); - }); + let toastTitle = await toasts.getTitleAndDismiss(); + expect(toastTitle).to.eql('Disabled 2 rules'); await testSubjects.click('rules-list-clear-filter'); await refreshAlertsList(); + await pageObjects.header.waitUntilLoadingHasFinished(); await pageObjects.triggersActionsUI.searchAlerts(rule1.name); + await pageObjects.header.waitUntilLoadingHasFinished(); expect(await testSubjects.getVisibleText('statusDropdown')).to.be('Disabled'); + await pageObjects.triggersActionsUI.searchAlerts(rule2.name); + await pageObjects.header.waitUntilLoadingHasFinished(); expect(await testSubjects.getVisibleText('statusDropdown')).to.be('Enabled'); + await pageObjects.triggersActionsUI.searchAlerts(rule3.name); + await pageObjects.header.waitUntilLoadingHasFinished(); expect(await testSubjects.getVisibleText('statusDropdown')).to.be('Disabled'); await testSubjects.click('rules-list-clear-filter'); + await pageObjects.header.waitUntilLoadingHasFinished(); await refreshAlertsList(); + await pageObjects.header.waitUntilLoadingHasFinished(); await testSubjects.click('ruleStatusFilterButton'); - await testSubjects.existOrFail('ruleStatusFilterOption-enabled'); await testSubjects.click('ruleStatusFilterOption-enabled'); + await pageObjects.header.waitUntilLoadingHasFinished(); + await testSubjects.click('ruleStatusFilterButton'); + await testSubjects.click(`checkboxSelectRow-${rule2.id}`); await testSubjects.click('selectAllRulesButton'); @@ -271,24 +306,16 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { await testSubjects.click('bulkDelete'); await testSubjects.existOrFail('rulesDeleteConfirmation'); await testSubjects.click('confirmModalConfirmButton'); + await pageObjects.header.waitUntilLoadingHasFinished(); - await retry.try(async () => { - const toastTitle = await toasts.getTitleAndDismiss(); - expect(toastTitle).to.eql('Deleted 1 rule'); - }); + toastTitle = await toasts.getTitleAndDismiss(); + expect(toastTitle).to.eql('Deleted 1 rule'); await testSubjects.click('rules-list-clear-filter'); + await pageObjects.header.waitUntilLoadingHasFinished(); await refreshAlertsList(); - - await retry.try( - async () => { - expect(await testSubjects.getVisibleText('totalRulesCount')).to.be('2 rules'); - }, - async () => { - // If the delete fails, make sure rule2 gets cleaned up - objectRemover.add(rule2.id, 'alert', 'alerts'); - } - ); + await pageObjects.header.waitUntilLoadingHasFinished(); + expect(await testSubjects.getVisibleText('totalRulesCount')).to.be('2 rules'); }); }); }; diff --git a/x-pack/test/monitoring_api_integration/packages.ts b/x-pack/test/monitoring_api_integration/packages.ts index 284bba089a55c..981845eb460dc 100644 --- a/x-pack/test/monitoring_api_integration/packages.ts +++ b/x-pack/test/monitoring_api_integration/packages.ts @@ -30,10 +30,7 @@ export const getPackagesArgs = (): string[] => { export const bundledPackagesLocation = path.join(path.dirname(__filename), '/fixtures/packages'); -export function installPackage( - supertest: SuperTest.SuperTest, - packageName: SupportedPackage -) { +export function installPackage(supertest: SuperTest.Agent, packageName: SupportedPackage) { const pkg = PACKAGES.find(({ name }) => name === packageName); const request = supertest .post('/api/fleet/epm/packages') diff --git a/x-pack/test/observability_ai_assistant_api_integration/common/observability_ai_assistant_api_client.ts b/x-pack/test/observability_ai_assistant_api_integration/common/observability_ai_assistant_api_client.ts index cb59adca9a86a..865620a2d028a 100644 --- a/x-pack/test/observability_ai_assistant_api_integration/common/observability_ai_assistant_api_client.ts +++ b/x-pack/test/observability_ai_assistant_api_integration/common/observability_ai_assistant_api_client.ts @@ -15,7 +15,7 @@ import supertest from 'supertest'; import { format } from 'url'; import { Subtract } from 'utility-types'; -export function createObservabilityAIAssistantApiClient(st: supertest.SuperTest) { +export function createObservabilityAIAssistantApiClient(st: supertest.Agent) { return ( options: { type?: 'form-data'; @@ -70,17 +70,62 @@ type WithoutPromise> = Subtract>; // end(one:string) // end(one:string, two:string) // } -// would lose the first signature. This keeps up to four signatures. +// would lose the first signature. This keeps up to eight signatures. type OverloadedParameters = T extends { (...args: infer A1): any; (...args: infer A2): any; (...args: infer A3): any; (...args: infer A4): any; + (...args: infer A5): any; + (...args: infer A6): any; + (...args: infer A7): any; + (...args: infer A8): any; } + ? A1 | A2 | A3 | A4 | A5 | A6 | A7 | A8 + : T extends { + (...args: infer A1): any; + (...args: infer A2): any; + (...args: infer A3): any; + (...args: infer A4): any; + (...args: infer A5): any; + (...args: infer A6): any; + (...args: infer A7): any; + } + ? A1 | A2 | A3 | A4 | A5 | A6 | A7 + : T extends { + (...args: infer A1): any; + (...args: infer A2): any; + (...args: infer A3): any; + (...args: infer A4): any; + (...args: infer A5): any; + (...args: infer A6): any; + } + ? A1 | A2 | A3 | A4 | A5 | A6 + : T extends { + (...args: infer A1): any; + (...args: infer A2): any; + (...args: infer A3): any; + (...args: infer A4): any; + (...args: infer A5): any; + } + ? A1 | A2 | A3 | A4 | A5 + : T extends { + (...args: infer A1): any; + (...args: infer A2): any; + (...args: infer A3): any; + (...args: infer A4): any; + } ? A1 | A2 | A3 | A4 - : T extends { (...args: infer A1): any; (...args: infer A2): any; (...args: infer A3): any } + : T extends { + (...args: infer A1): any; + (...args: infer A2): any; + (...args: infer A3): any; + } ? A1 | A2 | A3 - : T extends { (...args: infer A1): any; (...args: infer A2): any } + : T extends { + (...args: infer A1): any; + (...args: infer A2): any; + } ? A1 | A2 : T extends (...args: infer A) => any ? A diff --git a/x-pack/test/observability_ai_assistant_api_integration/tests/connectors/connectors.spec.ts b/x-pack/test/observability_ai_assistant_api_integration/tests/connectors/connectors.spec.ts index d5e726012c869..d51edffc9a1a8 100644 --- a/x-pack/test/observability_ai_assistant_api_integration/tests/connectors/connectors.spec.ts +++ b/x-pack/test/observability_ai_assistant_api_integration/tests/connectors/connectors.spec.ts @@ -6,7 +6,7 @@ */ import expect from '@kbn/expect'; -import type { SuperTest, Test } from 'supertest'; +import type { Agent as SuperTestAgent } from 'supertest'; import { FtrProviderContext } from '../../common/ftr_provider_context'; export default function ApiTest({ getService }: FtrProviderContext) { @@ -71,7 +71,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { }); } -export async function deleteAllActionConnectors(supertest: SuperTest): Promise { +export async function deleteAllActionConnectors(supertest: SuperTestAgent): Promise { const res = await supertest.get(`/api/actions/connectors`); const body = res.body as Array<{ id: string; connector_type_id: string; name: string }>; diff --git a/x-pack/test/observability_api_integration/common/obs_api_supertest.ts b/x-pack/test/observability_api_integration/common/obs_api_supertest.ts index e0788dcd6785d..69d7083f838e4 100644 --- a/x-pack/test/observability_api_integration/common/obs_api_supertest.ts +++ b/x-pack/test/observability_api_integration/common/obs_api_supertest.ts @@ -24,7 +24,7 @@ export type APIClientRequestParamsOf = ClientRequ TEndpoint >; -export function createObsApiClient(st: supertest.SuperTest) { +export function createObsApiClient(st: supertest.Agent) { return async ( options: { type?: 'form-data'; diff --git a/x-pack/test/observability_onboarding_api_integration/common/observability_onboarding_api_supertest.ts b/x-pack/test/observability_onboarding_api_integration/common/observability_onboarding_api_supertest.ts index c679c91e96525..199230e92c4ae 100644 --- a/x-pack/test/observability_onboarding_api_integration/common/observability_onboarding_api_supertest.ts +++ b/x-pack/test/observability_onboarding_api_integration/common/observability_onboarding_api_supertest.ts @@ -15,7 +15,7 @@ import type { import type { APIEndpoint } from '@kbn/observability-onboarding-plugin/server/routes'; import { formatRequest } from '@kbn/server-route-repository'; -export function createObservabilityOnboardingApiClient(st: supertest.SuperTest) { +export function createObservabilityOnboardingApiClient(st: supertest.Agent) { return async ( options: { type?: 'form-data'; diff --git a/x-pack/test/observability_onboarding_api_integration/configs/index.ts b/x-pack/test/observability_onboarding_api_integration/configs/index.ts index 8708ef8235d55..57e56a9b022a7 100644 --- a/x-pack/test/observability_onboarding_api_integration/configs/index.ts +++ b/x-pack/test/observability_onboarding_api_integration/configs/index.ts @@ -8,11 +8,11 @@ import { mapValues } from 'lodash'; import { createTestConfig, CreateTestConfig } from '../common/config'; -export const MOCKED_PUBLIC_BASE_URL = 'http://mockedPublicBaseUrl'; +export const MOCKED_PUBLIC_BASE_URL = 'http://mockedpublicbaseurl'; // my.mocked.domain$myMockedEsUr$myKibanaMockedUrl export const MOCKED_ENCODED_CLOUD_ID = 'bXkubW9ja2VkLmRvbWFpbiRteU1vY2tlZEVzVXJsJG15TW9ja2VkS2liYW5hVXJs'; -export const MOCKED_KIBANA_URL = 'https://myMockedKibanaUrl.my.mocked.domain:443'; +export const MOCKED_KIBANA_URL = 'https://mymockedkibanaurl.my.mocked.domain'; export const observabilityOnboardingDebugLogger = { name: 'plugins.observabilityOnboarding', diff --git a/x-pack/test/observability_onboarding_api_integration/tests/logs/environment.spec.ts b/x-pack/test/observability_onboarding_api_integration/tests/logs/environment.spec.ts index 41a14061b4059..2f7b514d54a57 100644 --- a/x-pack/test/observability_onboarding_api_integration/tests/logs/environment.spec.ts +++ b/x-pack/test/observability_onboarding_api_integration/tests/logs/environment.spec.ts @@ -29,7 +29,8 @@ export default function ApiTest({ getService }: FtrProviderContext) { ); expect(request.body.scriptDownloadUrl).to.match( new RegExp( - `${MOCKED_PUBLIC_BASE_URL}/.+?/plugins/observabilityOnboarding/assets/standalone_agent_setup.sh` + `${MOCKED_PUBLIC_BASE_URL}/.+?/plugins/observabilityOnboarding/assets/standalone_agent_setup.sh`, + 'i' ) ); }); @@ -45,7 +46,8 @@ export default function ApiTest({ getService }: FtrProviderContext) { ); expect(request.body.scriptDownloadUrl).to.match( new RegExp( - `${MOCKED_KIBANA_URL}/.+?/plugins/observabilityOnboarding/assets/standalone_agent_setup.sh` + `${MOCKED_KIBANA_URL}/.+?/plugins/observabilityOnboarding/assets/standalone_agent_setup.sh`, + 'i' ) ); }); diff --git a/x-pack/test/profiling_api_integration/common/api_supertest.ts b/x-pack/test/profiling_api_integration/common/api_supertest.ts index 11d7564248caf..dcd5c892d3b77 100644 --- a/x-pack/test/profiling_api_integration/common/api_supertest.ts +++ b/x-pack/test/profiling_api_integration/common/api_supertest.ts @@ -10,7 +10,7 @@ import request from 'superagent'; import supertest from 'supertest'; import { format } from 'url'; -export function createProfilingApiClient(st: supertest.SuperTest) { +export function createProfilingApiClient(st: supertest.Agent) { return async (options: { endpoint: string; params?: { diff --git a/x-pack/test/profiling_api_integration/common/bettertest.ts b/x-pack/test/profiling_api_integration/common/bettertest.ts index ca679a24539ac..ec2fd13763853 100644 --- a/x-pack/test/profiling_api_integration/common/bettertest.ts +++ b/x-pack/test/profiling_api_integration/common/bettertest.ts @@ -23,7 +23,7 @@ export type BetterTest = (options: { * This is useful for tests that expect a 200 response * It also makes it easier to debug tests that fail because of a 500 response. */ -export function getBettertest(st: supertest.SuperTest): BetterTest { +export function getBettertest(st: supertest.Agent): BetterTest { return async ({ pathname, method = 'get', query, body }) => { const url = format({ pathname, query }); @@ -60,7 +60,7 @@ export class BetterTestError extends Error { const req = res.req as any; super( `Unhandled BetterTestError: -Status: "${res.status}" +Status: "${res.status}" Path: "${req.method} ${req.path}" Body: ${JSON.stringify(res.body)}` ); diff --git a/x-pack/test/saved_object_api_integration/common/lib/create_users_and_roles.ts b/x-pack/test/saved_object_api_integration/common/lib/create_users_and_roles.ts index e0fed03efb94d..eb7a729ff5c96 100644 --- a/x-pack/test/saved_object_api_integration/common/lib/create_users_and_roles.ts +++ b/x-pack/test/saved_object_api_integration/common/lib/create_users_and_roles.ts @@ -5,11 +5,11 @@ * 2.0. */ -import type { SuperTest } from 'supertest'; +import type { Agent as SuperTestAgent } from 'supertest'; import type { Client } from '@elastic/elasticsearch'; import { AUTHENTICATION } from './authentication'; -export const createUsersAndRoles = async (es: Client, supertest: SuperTest) => { +export const createUsersAndRoles = async (es: Client, supertest: SuperTestAgent) => { await supertest .put('/api/security/role/kibana_legacy_user') .send({ diff --git a/x-pack/test/saved_object_api_integration/common/suites/bulk_create.ts b/x-pack/test/saved_object_api_integration/common/suites/bulk_create.ts index 38a4a8d8db8c7..6b79b34489111 100644 --- a/x-pack/test/saved_object_api_integration/common/suites/bulk_create.ts +++ b/x-pack/test/saved_object_api_integration/common/suites/bulk_create.ts @@ -258,7 +258,7 @@ export function bulkCreateTestSuiteFactory(context: FtrProviderContext) { const query = test.overwrite ? '?overwrite=true' : ''; await supertest .post(`${getUrlPrefix(spaceId)}/api/saved_objects/_bulk_create${query}`) - .auth(user?.username, user?.password) + .auth(user?.username!, user?.password!) .send(requestBody) .expect(test.responseStatusCode) .then(test.responseBody); diff --git a/x-pack/test/saved_object_api_integration/common/suites/bulk_delete.ts b/x-pack/test/saved_object_api_integration/common/suites/bulk_delete.ts index 578f8a4e0cd1f..f7fe4ba4061ce 100644 --- a/x-pack/test/saved_object_api_integration/common/suites/bulk_delete.ts +++ b/x-pack/test/saved_object_api_integration/common/suites/bulk_delete.ts @@ -138,7 +138,7 @@ export function bulkDeleteTestSuiteFactory(context: FtrProviderContext) { const query = testForce && testForce === true ? '?force=true' : ''; await supertest .post(`${getUrlPrefix(spaceId)}/api/saved_objects/_bulk_delete${query}`) - .auth(user?.username, user?.password) + .auth(user?.username!, user?.password!) .send(requestBody) .expect(test.responseStatusCode) .then(test.responseBody); diff --git a/x-pack/test/saved_object_api_integration/common/suites/bulk_get.ts b/x-pack/test/saved_object_api_integration/common/suites/bulk_get.ts index 15a51c3db3364..d25d1e0a5d87c 100644 --- a/x-pack/test/saved_object_api_integration/common/suites/bulk_get.ts +++ b/x-pack/test/saved_object_api_integration/common/suites/bulk_get.ts @@ -125,7 +125,7 @@ export function bulkGetTestSuiteFactory(context: FtrProviderContext) { it(`should return ${test.responseStatusCode} ${test.title}`, async () => { await supertest .post(`${getUrlPrefix(spaceId)}/api/saved_objects/_bulk_get`) - .auth(user?.username, user?.password) + .auth(user?.username!, user?.password!) .send(test.request) .expect(test.responseStatusCode) .then(test.responseBody); diff --git a/x-pack/test/saved_object_api_integration/common/suites/bulk_resolve.ts b/x-pack/test/saved_object_api_integration/common/suites/bulk_resolve.ts index a203865e294aa..b3c8669d48216 100644 --- a/x-pack/test/saved_object_api_integration/common/suites/bulk_resolve.ts +++ b/x-pack/test/saved_object_api_integration/common/suites/bulk_resolve.ts @@ -6,7 +6,7 @@ */ import expect from '@kbn/expect'; -import { SuperTest } from 'supertest'; +import { Agent as SuperTestAgent } from 'supertest'; import { TEST_CASES } from './resolve'; import { SPACES } from '../lib/spaces'; import { @@ -29,7 +29,7 @@ export interface BulkResolveTestCase extends TestCase { export { TEST_CASES }; // re-export the (non-bulk) resolve test cases -export function bulkResolveTestSuiteFactory(esArchiver: any, supertest: SuperTest) { +export function bulkResolveTestSuiteFactory(esArchiver: any, supertest: SuperTestAgent) { const expectSavedObjectForbidden = expectResponses.forbiddenTypes('bulk_get'); const expectResponseBody = ( @@ -119,7 +119,7 @@ export function bulkResolveTestSuiteFactory(esArchiver: any, supertest: SuperTes it(`should return ${test.responseStatusCode} ${test.title}`, async () => { await supertest .post(`${getUrlPrefix(spaceId)}/api/saved_objects/_bulk_resolve`) - .auth(user?.username, user?.password) + .auth(user?.username!, user?.password!) .send(test.request) .expect(test.responseStatusCode) .then(test.responseBody); diff --git a/x-pack/test/saved_object_api_integration/common/suites/bulk_update.ts b/x-pack/test/saved_object_api_integration/common/suites/bulk_update.ts index e79089615e7ee..384b8db8aa0a7 100644 --- a/x-pack/test/saved_object_api_integration/common/suites/bulk_update.ts +++ b/x-pack/test/saved_object_api_integration/common/suites/bulk_update.ts @@ -6,7 +6,7 @@ */ import expect from '@kbn/expect'; -import { SuperTest } from 'supertest'; +import { Agent as SuperTestAgent } from 'supertest'; import { SAVED_OBJECT_TEST_CASES as CASES } from '../lib/saved_object_test_cases'; import { SPACES } from '../lib/spaces'; import { expectResponses, getUrlPrefix, getTestTitle } from '../lib/saved_object_test_utils'; @@ -36,7 +36,7 @@ const createRequest = ({ type, id, namespace }: BulkUpdateTestCase) => ({ ...(namespace && { namespace }), // individual "object namespace" string }); -export function bulkUpdateTestSuiteFactory(esArchiver: any, supertest: SuperTest) { +export function bulkUpdateTestSuiteFactory(esArchiver: any, supertest: SuperTestAgent) { const expectSavedObjectForbidden = expectResponses.forbiddenTypes('bulk_update'); const expectResponseBody = ( @@ -118,7 +118,7 @@ export function bulkUpdateTestSuiteFactory(esArchiver: any, supertest: SuperTest const requestBody = test.request.map((x) => ({ ...x, ...attrs })); await supertest .put(`${getUrlPrefix(spaceId)}/api/saved_objects/_bulk_update`) - .auth(user?.username, user?.password) + .auth(user?.username!, user?.password!) .send(requestBody) .expect(test.responseStatusCode) .then(test.responseBody); diff --git a/x-pack/test/saved_object_api_integration/common/suites/create.ts b/x-pack/test/saved_object_api_integration/common/suites/create.ts index dfad5e638a708..b12fef1c7cade 100644 --- a/x-pack/test/saved_object_api_integration/common/suites/create.ts +++ b/x-pack/test/saved_object_api_integration/common/suites/create.ts @@ -6,7 +6,7 @@ */ import expect from '@kbn/expect'; -import { SuperTest } from 'supertest'; +import { Agent as SuperTestAgent } from 'supertest'; import { SAVED_OBJECT_TEST_CASES as CASES } from '../lib/saved_object_test_cases'; import { SPACES, ALL_SPACES_ID } from '../lib/spaces'; import { @@ -85,7 +85,7 @@ const createRequest = ({ type, id, initialNamespaces }: CreateTestCase) => ({ initialNamespaces, }); -export function createTestSuiteFactory(esArchiver: any, supertest: SuperTest) { +export function createTestSuiteFactory(esArchiver: any, supertest: SuperTestAgent) { const expectSavedObjectForbidden = expectResponses.forbiddenTypes('create'); const expectResponseBody = (testCase: CreateTestCase, user?: TestUser): ExpectResponseBody => @@ -155,7 +155,7 @@ export function createTestSuiteFactory(esArchiver: any, supertest: SuperTest = Object.freeze({ */ const createRequest = ({ type, id, force }: DeleteTestCase) => ({ type, id, force }); -export function deleteTestSuiteFactory(es: Client, esArchiver: any, supertest: SuperTest) { +export function deleteTestSuiteFactory(es: Client, esArchiver: any, supertest: SuperTestAgent) { const expectSavedObjectForbidden = expectResponses.forbiddenTypes('delete'); const expectResponseBody = (testCase: DeleteTestCase): ExpectResponseBody => @@ -118,7 +118,7 @@ export function deleteTestSuiteFactory(es: Client, esArchiver: any, supertest: S await supertest .delete(`${getUrlPrefix(spaceId)}/api/saved_objects/${type}/${id}`) .query({ ...(force && { force }) }) - .auth(user?.username, user?.password) + .auth(user?.username!, user?.password!) .expect(test.responseStatusCode) .then(test.responseBody); }); diff --git a/x-pack/test/saved_object_api_integration/common/suites/export.ts b/x-pack/test/saved_object_api_integration/common/suites/export.ts index 6df4c2f8dd12c..b7936f94a98fb 100644 --- a/x-pack/test/saved_object_api_integration/common/suites/export.ts +++ b/x-pack/test/saved_object_api_integration/common/suites/export.ts @@ -6,7 +6,7 @@ */ import expect from '@kbn/expect'; -import { SuperTest } from 'supertest'; +import { Agent as SuperTestAgent } from 'supertest'; import { SAVED_OBJECT_TEST_CASES, CONFLICT_TEST_CASES, @@ -154,7 +154,7 @@ const EMPTY_RESULT = { missingReferences: [], }; -export function exportTestSuiteFactory(esArchiver: any, supertest: SuperTest) { +export function exportTestSuiteFactory(esArchiver: any, supertest: SuperTestAgent) { const expectSavedObjectForbiddenBulkGet = expectResponses.forbiddenTypes('bulk_get'); const expectResponseBody = (testCase: ExportTestCase): ExpectResponseBody => @@ -259,7 +259,7 @@ export function exportTestSuiteFactory(esArchiver: any, supertest: SuperTest { await supertest .post(`${getUrlPrefix(spaceId)}/api/saved_objects/_export`) - .auth(user?.username, user?.password) + .auth(user?.username!, user?.password!) .send(test.request) .expect(test.responseStatusCode) .then(test.responseBody); diff --git a/x-pack/test/saved_object_api_integration/common/suites/find.ts b/x-pack/test/saved_object_api_integration/common/suites/find.ts index 202fc02dbfc1c..c7afc205f5b6f 100644 --- a/x-pack/test/saved_object_api_integration/common/suites/find.ts +++ b/x-pack/test/saved_object_api_integration/common/suites/find.ts @@ -6,7 +6,7 @@ */ import expect from '@kbn/expect'; -import { SuperTest } from 'supertest'; +import { Agent as SuperTestAgent } from 'supertest'; import querystring from 'querystring'; import { SAVED_OBJECT_TEST_CASES, @@ -187,7 +187,7 @@ export const createRequest = ({ query }: FindTestCase) => ({ query }); const getTestTitle = ({ failure, title }: FindTestCase) => `${failure?.reason || 'success'} ["${title}"]`; -export function findTestSuiteFactory(esArchiver: any, supertest: SuperTest) { +export function findTestSuiteFactory(esArchiver: any, supertest: SuperTestAgent) { const expectResponseBody = (testCase: FindTestCase, user?: TestUser): ExpectResponseBody => async (response: Record) => { @@ -298,7 +298,7 @@ export function findTestSuiteFactory(esArchiver: any, supertest: SuperTest) await supertest .get(`${getUrlPrefix(spaceId)}/api/saved_objects/_find${query}`) - .auth(user?.username, user?.password) + .auth(user?.username!, user?.password!) .expect(test.responseStatusCode) .then(test.responseBody); }); diff --git a/x-pack/test/saved_object_api_integration/common/suites/get.ts b/x-pack/test/saved_object_api_integration/common/suites/get.ts index b106930103f84..024f061d2cb23 100644 --- a/x-pack/test/saved_object_api_integration/common/suites/get.ts +++ b/x-pack/test/saved_object_api_integration/common/suites/get.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { SuperTest } from 'supertest'; +import { Agent as SuperTestAgent } from 'supertest'; import { SAVED_OBJECT_TEST_CASES as CASES } from '../lib/saved_object_test_cases'; import { SPACES } from '../lib/spaces'; import { @@ -25,7 +25,7 @@ export type GetTestCase = TestCase; const DOES_NOT_EXIST = Object.freeze({ type: 'dashboard', id: 'does-not-exist' }); export const TEST_CASES: Record = Object.freeze({ ...CASES, DOES_NOT_EXIST }); -export function getTestSuiteFactory(esArchiver: any, supertest: SuperTest) { +export function getTestSuiteFactory(esArchiver: any, supertest: SuperTestAgent) { const expectSavedObjectForbidden = expectResponses.forbiddenTypes('get'); const expectResponseBody = (testCase: GetTestCase): ExpectResponseBody => @@ -81,7 +81,7 @@ export function getTestSuiteFactory(esArchiver: any, supertest: SuperTest) const { type, id } = test.request; await supertest .get(`${getUrlPrefix(spaceId)}/api/saved_objects/${type}/${id}`) - .auth(user?.username, user?.password) + .auth(user?.username!, user?.password!) .expect(test.responseStatusCode) .then(test.responseBody); }); diff --git a/x-pack/test/saved_object_api_integration/common/suites/import.ts b/x-pack/test/saved_object_api_integration/common/suites/import.ts index 7580521e170a6..1af1bf07510b2 100644 --- a/x-pack/test/saved_object_api_integration/common/suites/import.ts +++ b/x-pack/test/saved_object_api_integration/common/suites/import.ts @@ -6,7 +6,7 @@ */ import expect from '@kbn/expect'; -import { SuperTest } from 'supertest'; +import { Agent as SuperTestAgent } from 'supertest'; import type { Client } from '@elastic/elasticsearch'; import type { SavedObjectReference } from '@kbn/core/server'; import { SAVED_OBJECT_TEST_CASES as CASES } from '../lib/saved_object_test_cases'; @@ -121,7 +121,7 @@ export const importTestCaseFailures = { condition !== false ? { failureType: 'missing_references' } : {}, }; -export function importTestSuiteFactory(es: Client, esArchiver: any, supertest: SuperTest) { +export function importTestSuiteFactory(es: Client, esArchiver: any, supertest: SuperTestAgent) { const expectSavedObjectForbidden = (action: string, typeOrTypes: string | string[]) => expectResponses.forbiddenTypes(action)(typeOrTypes); const expectResponseBody = @@ -310,7 +310,7 @@ export function importTestSuiteFactory(es: Client, esArchiver: any, supertest: S : ''; await supertest .post(`${getUrlPrefix(spaceId)}/api/saved_objects/_import${query}`) - .auth(user?.username, user?.password) + .auth(user?.username!, user?.password!) .attach('file', Buffer.from(requestBody, 'utf8'), 'export.ndjson') .expect(test.responseStatusCode) .then(test.responseBody); diff --git a/x-pack/test/saved_object_api_integration/common/suites/resolve.ts b/x-pack/test/saved_object_api_integration/common/suites/resolve.ts index ebb71a860d744..8f03686d4cabc 100644 --- a/x-pack/test/saved_object_api_integration/common/suites/resolve.ts +++ b/x-pack/test/saved_object_api_integration/common/suites/resolve.ts @@ -6,7 +6,7 @@ */ import expect from '@kbn/expect'; -import { SuperTest } from 'supertest'; +import { Agent as SuperTestAgent } from 'supertest'; import { SAVED_OBJECT_TEST_CASES as CASES } from '../lib/saved_object_test_cases'; import { SPACES } from '../lib/spaces'; import { @@ -70,7 +70,7 @@ export const TEST_CASES = Object.freeze({ HIDDEN: CASES.HIDDEN, }); -export function resolveTestSuiteFactory(esArchiver: any, supertest: SuperTest) { +export function resolveTestSuiteFactory(esArchiver: any, supertest: SuperTestAgent) { const expectSavedObjectForbidden = expectResponses.forbiddenTypes('bulk_get'); const expectResponseBody = (testCase: ResolveTestCase): ExpectResponseBody => @@ -135,7 +135,7 @@ export function resolveTestSuiteFactory(esArchiver: any, supertest: SuperTest + supertest: SuperTestAgent ) { const expectSavedObjectForbidden = (action: string, typeOrTypes: string | string[]) => expectResponses.forbiddenTypes(action)(typeOrTypes); @@ -373,7 +373,7 @@ export function resolveImportErrorsTestSuiteFactory( const query = test.createNewCopies ? '?createNewCopies=true' : ''; await supertest .post(`${getUrlPrefix(spaceId)}/api/saved_objects/_resolve_import_errors${query}`) - .auth(user?.username, user?.password) + .auth(user?.username!, user?.password!) .field('retries', JSON.stringify(test.request.retries)) .attach('file', Buffer.from(requestBody, 'utf8'), 'export.ndjson') .expect(test.responseStatusCode) diff --git a/x-pack/test/saved_object_api_integration/common/suites/update.ts b/x-pack/test/saved_object_api_integration/common/suites/update.ts index 1fc2cef6e051a..ee37e0feccfe2 100644 --- a/x-pack/test/saved_object_api_integration/common/suites/update.ts +++ b/x-pack/test/saved_object_api_integration/common/suites/update.ts @@ -6,7 +6,7 @@ */ import expect from '@kbn/expect'; -import { SuperTest } from 'supertest'; +import { Agent as SuperTestAgent } from 'supertest'; import { SAVED_OBJECT_TEST_CASES as CASES } from '../lib/saved_object_test_cases'; import { SPACES } from '../lib/spaces'; import { expectResponses, getUrlPrefix, getTestTitle } from '../lib/saved_object_test_utils'; @@ -34,7 +34,7 @@ export const TEST_CASES: Record = Object.freeze({ const createRequest = ({ type, id, upsert }: UpdateTestCase) => ({ type, id, upsert }); -export function updateTestSuiteFactory(esArchiver: any, supertest: SuperTest) { +export function updateTestSuiteFactory(esArchiver: any, supertest: SuperTestAgent) { const expectSavedObjectForbidden = expectResponses.forbiddenTypes('update'); const expectResponseBody = (testCase: UpdateTestCase): ExpectResponseBody => @@ -94,7 +94,7 @@ export function updateTestSuiteFactory(esArchiver: any, supertest: SuperTest { + this.timeout(120000); + + for (const targetURL of [ + '///example.com', + '//example.com', + 'https://example.com', + + '/\t/example.com', + '/\n/example.com', + '/\r/example.com', + + '/\t//example.com', + '/\n//example.com', + '/\r//example.com', + + '//\t/example.com', + '//\n/example.com', + '//\r/example.com', + + 'ht\ttps://example.com', + 'ht\ntps://example.com', + 'ht\rtps://example.com', + ]) { + await browser.get( + `${deployment.getHostPort()}/login?next=${encodeURIComponent(targetURL)}` + ); + + await PageObjects.common.waitUntilUrlIncludes('next='); + await PageObjects.security.loginSelector.login('basic', 'basic1'); + // We need to make sure that both path and hash are respected. + const currentURL = parse(await browser.getCurrentUrl()); + + expect(currentURL.pathname).to.eql('/app/home'); + await PageObjects.security.forceLogout(); + } + }); + it('can login with SSO preserving original URL', async () => { await PageObjects.common.navigateToUrl('management', 'security/users', { ensureCurrentUrl: false, diff --git a/x-pack/test/security_functional/tests/oidc/url_capture.ts b/x-pack/test/security_functional/tests/oidc/url_capture.ts index 10ef8ff01c95e..6553ef193fc3b 100644 --- a/x-pack/test/security_functional/tests/oidc/url_capture.ts +++ b/x-pack/test/security_functional/tests/oidc/url_capture.ts @@ -63,5 +63,43 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const currentURL = parse(await browser.getCurrentUrl()); expect(currentURL.path).to.eql('/authentication/app?one=two'); }); + + it('resets invalid target URL', async () => { + this.timeout(120000); + + for (const targetURL of [ + '///example.com', + '//example.com', + 'https://example.com', + + '/\t/example.com', + '/\n/example.com', + '/\r/example.com', + + '/\t//example.com', + '/\n//example.com', + '/\r//example.com', + + '//\t/example.com', + '//\n/example.com', + '//\r/example.com', + + 'ht\ttps://example.com', + 'ht\ntps://example.com', + 'ht\rtps://example.com', + ]) { + await browser.get( + `${deployment.getHostPort()}/internal/security/capture-url?next=${encodeURIComponent( + targetURL + )}` + ); + + await find.byCssSelector('[data-test-subj="userMenuButton"]', 20000); + expect(parse(await browser.getCurrentUrl()).pathname).to.eql('/app/home'); + + await browser.get(deployment.getHostPort() + '/logout'); + await PageObjects.common.waitUntilUrlIncludes('logged_out'); + } + }); }); } diff --git a/x-pack/test/security_functional/tests/saml/url_capture.ts b/x-pack/test/security_functional/tests/saml/url_capture.ts index 1199255f96bf1..0193d3d870701 100644 --- a/x-pack/test/security_functional/tests/saml/url_capture.ts +++ b/x-pack/test/security_functional/tests/saml/url_capture.ts @@ -63,5 +63,43 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const currentURL = parse(await browser.getCurrentUrl()); expect(currentURL.path).to.eql('/authentication/app?one=two'); }); + + it('resets invalid target URL', async () => { + this.timeout(120000); + + for (const targetURL of [ + '///example.com', + '//example.com', + 'https://example.com', + + '/\t/example.com', + '/\n/example.com', + '/\r/example.com', + + '/\t//example.com', + '/\n//example.com', + '/\r//example.com', + + '//\t/example.com', + '//\n/example.com', + '//\r/example.com', + + 'ht\ttps://example.com', + 'ht\ntps://example.com', + 'ht\rtps://example.com', + ]) { + await browser.get( + `${deployment.getHostPort()}/internal/security/capture-url?next=${encodeURIComponent( + targetURL + )}` + ); + + await find.byCssSelector('[data-test-subj="userMenuButton"]', 20000); + expect(parse(await browser.getCurrentUrl()).pathname).to.eql('/app/home'); + + await browser.get(deployment.getHostPort() + '/logout'); + await PageObjects.common.waitUntilUrlIncludes('logged_out'); + } + }); }); } diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/detection_engine/exceptions/workflows/basic_license_essentials_tier/create_endpoint_exceptions.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/detection_engine/exceptions/workflows/basic_license_essentials_tier/create_endpoint_exceptions.ts index 728d5328a9174..53a9cc91a6005 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/detection_engine/exceptions/workflows/basic_license_essentials_tier/create_endpoint_exceptions.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/detection_engine/exceptions/workflows/basic_license_essentials_tier/create_endpoint_exceptions.ts @@ -43,7 +43,7 @@ interface Host { * @returns The array of hosts sorted */ export const getHostHits = async ( - supertest: SuperTest.SuperTest, + supertest: SuperTest.Agent, log: ToolingLog, id: string ): Promise => { diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/detection_engine/rule_execution_logic/trial_license_complete_tier/execution_logic/utils.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/detection_engine/rule_execution_logic/trial_license_complete_tier/execution_logic/utils.ts index ec6fac6cf2bcd..31278019dad3e 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/detection_engine/rule_execution_logic/trial_license_complete_tier/execution_logic/utils.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/detection_engine/rule_execution_logic/trial_license_complete_tier/execution_logic/utils.ts @@ -10,10 +10,7 @@ import supertest from 'supertest'; import { NodeMetrics } from '@kbn/task-manager-plugin/server/routes/metrics'; import { RetryService } from '@kbn/ftr-common-functional-services'; -export const getMetricsRequest = ( - request: supertest.SuperTest, - reset: boolean = false -) => { +export const getMetricsRequest = (request: supertest.Agent, reset: boolean = false) => { return request .get(`/api/task_manager/metrics${reset ? '' : '?reset=false'}`) .set('kbn-xsrf', 'foo') @@ -22,7 +19,7 @@ export const getMetricsRequest = ( }; export const getMetricsWithRetry = ( - request: supertest.SuperTest, + request: supertest.Agent, retry: RetryService, reset: boolean = false, callback?: (metrics: NodeMetrics) => boolean diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_bulk_actions/trial_license_complete_tier/perform_bulk_action.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_bulk_actions/trial_license_complete_tier/perform_bulk_action.ts index f728b011b6801..22ac52dc2a333 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_bulk_actions/trial_license_complete_tier/perform_bulk_action.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_bulk_actions/trial_license_complete_tier/perform_bulk_action.ts @@ -142,6 +142,10 @@ export default ({ getService }: FtrProviderContext): void => { ], max_signals: 100, setup: '# some setup markdown', + required_fields: [ + { name: '@timestamp', type: 'date' }, + { name: 'my-non-ecs-field', type: 'keyword' }, + ], }; const mockRule = getCustomQueryRuleParams(defaultableFields); diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_creation/basic_license_essentials_tier/create_rules.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_creation/basic_license_essentials_tier/create_rules.ts index 63b1a4dfecdc7..925961c5a3720 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_creation/basic_license_essentials_tier/create_rules.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_creation/basic_license_essentials_tier/create_rules.ts @@ -9,8 +9,8 @@ import expect from 'expect'; import { RuleCreateProps } from '@kbn/security-solution-plugin/common/api/detection_engine'; import { - getSimpleRule, getCustomQueryRuleParams, + getSimpleRule, getSimpleRuleOutputWithoutRuleId, getSimpleRuleWithoutRuleId, removeServerGeneratedProperties, @@ -70,7 +70,7 @@ export default ({ getService }: FtrProviderContext) => { }); it('should create a rule with defaultable fields', async () => { - const expectedRule = getCustomQueryRuleParams({ + const ruleCreateProperties = getCustomQueryRuleParams({ rule_id: 'rule-1', max_signals: 200, setup: '# some setup markdown', @@ -78,10 +78,22 @@ export default ({ getService }: FtrProviderContext) => { { package: 'package-a', version: '^1.2.3' }, { package: 'package-b', integration: 'integration-b', version: '~1.1.1' }, ], + required_fields: [ + { name: '@timestamp', type: 'date' }, + { name: 'my-non-ecs-field', type: 'keyword' }, + ], }); + const expectedRule = { + ...ruleCreateProperties, + required_fields: [ + { name: '@timestamp', type: 'date', ecs: true }, + { name: 'my-non-ecs-field', type: 'keyword', ecs: false }, + ], + }; + const { body: createdRuleResponse } = await securitySolutionApi - .createRule({ body: expectedRule }) + .createRule({ body: ruleCreateProperties }) .expect(200); expect(createdRuleResponse).toMatchObject(expectedRule); @@ -207,6 +219,32 @@ export default ({ getService }: FtrProviderContext) => { ); }); }); + + describe('required_fields', () => { + it('creates a rule with required_fields defaulted to an empty array when not present', async () => { + const customQueryRuleParams = getCustomQueryRuleParams({ + rule_id: 'rule-without-required-fields', + }); + + expect(customQueryRuleParams.required_fields).toBeUndefined(); + + const { body } = await securitySolutionApi + .createRule({ + body: customQueryRuleParams, + }) + .expect(200); + + expect(body.required_fields).toEqual([]); + + const { body: createdRule } = await securitySolutionApi + .readRule({ + query: { rule_id: 'rule-without-required-fields' }, + }) + .expect(200); + + expect(createdRule.required_fields).toEqual([]); + }); + }); }); }); }; diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_creation/basic_license_essentials_tier/create_rules_bulk.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_creation/basic_license_essentials_tier/create_rules_bulk.ts index dc02f8450f411..4356c8b82b8b4 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_creation/basic_license_essentials_tier/create_rules_bulk.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_creation/basic_license_essentials_tier/create_rules_bulk.ts @@ -69,7 +69,7 @@ export default ({ getService }: FtrProviderContext): void => { }); it('should create a rule with defaultable fields', async () => { - const expectedRule = getCustomQueryRuleParams({ + const ruleCreateProperties = getCustomQueryRuleParams({ rule_id: 'rule-1', max_signals: 200, setup: '# some setup markdown', @@ -77,10 +77,22 @@ export default ({ getService }: FtrProviderContext): void => { { package: 'package-a', version: '^1.2.3' }, { package: 'package-b', integration: 'integration-b', version: '~1.1.1' }, ], + required_fields: [ + { name: '@timestamp', type: 'date' }, + { name: 'my-non-ecs-field', type: 'keyword' }, + ], }); + const expectedRule = { + ...ruleCreateProperties, + required_fields: [ + { name: '@timestamp', type: 'date', ecs: true }, + { name: 'my-non-ecs-field', type: 'keyword', ecs: false }, + ], + }; + const { body: createdRulesBulkResponse } = await securitySolutionApi - .bulkCreateRules({ body: [expectedRule] }) + .bulkCreateRules({ body: [ruleCreateProperties] }) .expect(200); expect(createdRulesBulkResponse[0]).toMatchObject(expectedRule); diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_import_export/basic_license_essentials_tier/export_rules.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_import_export/basic_license_essentials_tier/export_rules.ts index 5986e4d40fe3a..783d0bb42fd87 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_import_export/basic_license_essentials_tier/export_rules.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_import_export/basic_license_essentials_tier/export_rules.ts @@ -57,9 +57,22 @@ export default ({ getService }: FtrProviderContext): void => { { package: 'package-b', integration: 'integration-b', version: '~1.1.1' }, ], setup: '# some setup markdown', + required_fields: [ + { name: '@timestamp', type: 'date' }, + { name: 'my-non-ecs-field', type: 'keyword' }, + ], }; + const ruleToExport = getCustomQueryRuleParams(defaultableFields); + const expectedRule = { + ...ruleToExport, + required_fields: [ + { name: '@timestamp', type: 'date', ecs: true }, + { name: 'my-non-ecs-field', type: 'keyword', ecs: false }, + ], + }; + await securitySolutionApi.createRule({ body: ruleToExport }); const { body } = await securitySolutionApi @@ -69,7 +82,7 @@ export default ({ getService }: FtrProviderContext): void => { const exportedRule = JSON.parse(body.toString().split(/\n/)[0]); - expect(exportedRule).toMatchObject(defaultableFields); + expect(exportedRule).toMatchObject(expectedRule); }); it('should have export summary reflecting a number of rules', async () => { diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_import_export/basic_license_essentials_tier/import_rules.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_import_export/basic_license_essentials_tier/import_rules.ts index 71f40086a29f6..fb02b47067f8e 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_import_export/basic_license_essentials_tier/import_rules.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_import_export/basic_license_essentials_tier/import_rules.ts @@ -125,11 +125,25 @@ export default ({ getService }: FtrProviderContext): void => { { package: 'package-a', version: '^1.2.3' }, { package: 'package-b', integration: 'integration-b', version: '~1.1.1' }, ], + required_fields: [ + { name: '@timestamp', type: 'date' }, + { name: 'my-non-ecs-field', type: 'keyword' }, + ], }; + const ruleToImport = getCustomQueryRuleParams({ ...defaultableFields, rule_id: 'rule-1', }); + + const expectedRule = { + ...ruleToImport, + required_fields: [ + { name: '@timestamp', type: 'date', ecs: true }, + { name: 'my-non-ecs-field', type: 'keyword', ecs: false }, + ], + }; + const ndjson = combineToNdJson(ruleToImport); await securitySolutionApi @@ -143,7 +157,7 @@ export default ({ getService }: FtrProviderContext): void => { }) .expect(200); - expect(importedRule).toMatchObject(ruleToImport); + expect(importedRule).toMatchObject(expectedRule); }); it('should be able to import two rules', async () => { diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_patch/basic_license_essentials_tier/patch_rules.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_patch/basic_license_essentials_tier/patch_rules.ts index bdbbc271c26e5..a2658ed2fb285 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_patch/basic_license_essentials_tier/patch_rules.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_patch/basic_license_essentials_tier/patch_rules.ts @@ -61,7 +61,7 @@ export default ({ getService }: FtrProviderContext) => { }); it('should patch defaultable fields', async () => { - const expectedRule = getCustomQueryRuleParams({ + const rulePatchProperties = getCustomQueryRuleParams({ rule_id: 'rule-1', max_signals: 200, setup: '# some setup markdown', @@ -69,8 +69,14 @@ export default ({ getService }: FtrProviderContext) => { { package: 'package-a', version: '^1.2.3' }, { package: 'package-b', integration: 'integration-b', version: '~1.1.1' }, ], + required_fields: [{ name: '@timestamp', type: 'date' }], }); + const expectedRule = { + ...rulePatchProperties, + required_fields: [{ name: '@timestamp', type: 'date', ecs: true }], + }; + await securitySolutionApi.createRule({ body: getCustomQueryRuleParams({ rule_id: 'rule-1' }), }); @@ -78,10 +84,7 @@ export default ({ getService }: FtrProviderContext) => { const { body: patchedRuleResponse } = await securitySolutionApi .patchRule({ body: { - rule_id: 'rule-1', - max_signals: expectedRule.max_signals, - setup: expectedRule.setup, - related_integrations: expectedRule.related_integrations, + ...rulePatchProperties, }, }) .expect(200); diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_patch/basic_license_essentials_tier/patch_rules_bulk.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_patch/basic_license_essentials_tier/patch_rules_bulk.ts index 539c39061aa5f..a04245eac5517 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_patch/basic_license_essentials_tier/patch_rules_bulk.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_patch/basic_license_essentials_tier/patch_rules_bulk.ts @@ -60,7 +60,7 @@ export default ({ getService }: FtrProviderContext) => { }); it('should patch defaultable fields', async () => { - const expectedRule = getCustomQueryRuleParams({ + const rulePatchProperties = getCustomQueryRuleParams({ rule_id: 'rule-1', max_signals: 200, setup: '# some setup markdown', @@ -68,8 +68,14 @@ export default ({ getService }: FtrProviderContext) => { { package: 'package-a', version: '^1.2.3' }, { package: 'package-b', integration: 'integration-b', version: '~1.1.1' }, ], + required_fields: [{ name: '@timestamp', type: 'date' }], }); + const expectedRule = { + ...rulePatchProperties, + required_fields: [{ name: '@timestamp', type: 'date', ecs: true }], + }; + await securitySolutionApi.createRule({ body: getCustomQueryRuleParams({ rule_id: 'rule-1' }), }); @@ -78,10 +84,7 @@ export default ({ getService }: FtrProviderContext) => { .bulkPatchRules({ body: [ { - rule_id: 'rule-1', - max_signals: expectedRule.max_signals, - setup: expectedRule.setup, - related_integrations: expectedRule.related_integrations, + ...rulePatchProperties, }, ], }) diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_update/basic_license_essentials_tier/update_rules.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_update/basic_license_essentials_tier/update_rules.ts index ccf598a00da2e..33505f9d150d6 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_update/basic_license_essentials_tier/update_rules.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_update/basic_license_essentials_tier/update_rules.ts @@ -66,7 +66,7 @@ export default ({ getService }: FtrProviderContext) => { }); it('should update a rule with defaultable fields', async () => { - const expectedRule = getCustomQueryRuleParams({ + const ruleUpdateProperties = getCustomQueryRuleParams({ rule_id: 'rule-1', max_signals: 200, setup: '# some setup markdown', @@ -74,15 +74,21 @@ export default ({ getService }: FtrProviderContext) => { { package: 'package-a', version: '^1.2.3' }, { package: 'package-b', integration: 'integration-b', version: '~1.1.1' }, ], + required_fields: [{ name: '@timestamp', type: 'date' }], }); + const expectedRule = { + ...ruleUpdateProperties, + required_fields: [{ name: '@timestamp', type: 'date', ecs: true }], + }; + await securitySolutionApi.createRule({ body: getCustomQueryRuleParams({ rule_id: 'rule-1' }), }); const { body: updatedRuleResponse } = await securitySolutionApi .updateRule({ - body: expectedRule, + body: ruleUpdateProperties, }) .expect(200); @@ -273,6 +279,33 @@ export default ({ getService }: FtrProviderContext) => { ); }); }); + + describe('required_fields', () => { + it('should reset required fields field to default value on update when not present', async () => { + const expectedRule = getCustomQueryRuleParams({ + rule_id: 'required-fields-default-value-test', + required_fields: [], + }); + + await securitySolutionApi.createRule({ + body: getCustomQueryRuleParams({ + rule_id: 'required-fields-default-value-test', + required_fields: [{ name: 'host.name', type: 'keyword' }], + }), + }); + + const { body: updatedRuleResponse } = await securitySolutionApi + .updateRule({ + body: getCustomQueryRuleParams({ + rule_id: 'required-fields-default-value-test', + required_fields: undefined, + }), + }) + .expect(200); + + expect(updatedRuleResponse).toMatchObject(expectedRule); + }); + }); }); }); }; diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_update/basic_license_essentials_tier/update_rules_bulk.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_update/basic_license_essentials_tier/update_rules_bulk.ts index fc7c7229ef107..effc64a241cc5 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_update/basic_license_essentials_tier/update_rules_bulk.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_update/basic_license_essentials_tier/update_rules_bulk.ts @@ -65,7 +65,7 @@ export default ({ getService }: FtrProviderContext) => { }); it('should update a rule with defaultable fields', async () => { - const expectedRule = getCustomQueryRuleParams({ + const ruleUpdateProperties = getCustomQueryRuleParams({ rule_id: 'rule-1', max_signals: 200, setup: '# some setup markdown', @@ -73,15 +73,21 @@ export default ({ getService }: FtrProviderContext) => { { package: 'package-a', version: '^1.2.3' }, { package: 'package-b', integration: 'integration-b', version: '~1.1.1' }, ], + required_fields: [{ name: '@timestamp', type: 'date' }], }); + const expectedRule = { + ...ruleUpdateProperties, + required_fields: [{ name: '@timestamp', type: 'date', ecs: true }], + }; + await securitySolutionApi.createRule({ body: getCustomQueryRuleParams({ rule_id: 'rule-1' }), }); const { body: updatedRulesBulkResponse } = await securitySolutionApi .bulkUpdateRules({ - body: [expectedRule], + body: [ruleUpdateProperties], }) .expect(200); diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/actions/create_new_webhook_action.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/actions/create_new_webhook_action.ts index 79ea9738372f0..79a5b715f9fe1 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/actions/create_new_webhook_action.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/actions/create_new_webhook_action.ts @@ -17,9 +17,7 @@ import { getWebHookAction } from './get_web_hook_action'; * * @param supertest The supertest deps */ -export const createWebHookRuleAction = async ( - supertest: SuperTest.SuperTest -): Promise => { +export const createWebHookRuleAction = async (supertest: SuperTest.Agent): Promise => { return ( await supertest .post('/api/actions/action') diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/alerts/get_alerts.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/alerts/get_alerts.ts index 21d8233c8496b..70caaa4edfd2c 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/alerts/get_alerts.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/alerts/get_alerts.ts @@ -18,7 +18,7 @@ import { refreshIndex } from '..'; import { getAlertsByIds, waitForRuleStatus } from '../../../../../common/utils/security_solution'; export type GetAlerts = ( - supertest: SuperTest.SuperTest, + supertest: SuperTest.Agent, log: ToolingLog, es: Client, rule: RuleResponse, diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/alerts/migrations/finalize_alerts_migration.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/alerts/migrations/finalize_alerts_migration.ts index 02a7475f54aac..1f7d03cab9c5e 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/alerts/migrations/finalize_alerts_migration.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/alerts/migrations/finalize_alerts_migration.ts @@ -21,7 +21,7 @@ export const finalizeAlertsMigration = async ({ supertest, log, }: { - supertest: SuperTest.SuperTest; + supertest: SuperTest.Agent; log: ToolingLog; migrationIds: string[]; }): Promise => { diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/alerts/migrations/start_alerts_migration.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/alerts/migrations/start_alerts_migration.ts index 5d472221154c1..304cf11d79dce 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/alerts/migrations/start_alerts_migration.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/alerts/migrations/start_alerts_migration.ts @@ -21,7 +21,7 @@ export const startAlertsMigration = async ({ supertest, log, }: { - supertest: SuperTest.SuperTest; + supertest: SuperTest.Agent; log: ToolingLog; indices: string[]; }): Promise => { diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/alerts/wait_for_alert_to_complete.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/alerts/wait_for_alert_to_complete.ts index 7d942198bc0d5..d6799e6be611c 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/alerts/wait_for_alert_to_complete.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/alerts/wait_for_alert_to_complete.ts @@ -11,7 +11,7 @@ import type SuperTest from 'supertest'; import { waitFor } from '../../../../../common/utils/security_solution'; export const waitForAlertToComplete = async ( - supertest: SuperTest.SuperTest, + supertest: SuperTest.Agent, log: ToolingLog, id: string ): Promise => { diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/connectors/create_connector.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/connectors/create_connector.ts index 0ca8f88166c89..c6c67e37ebf24 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/connectors/create_connector.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/connectors/create_connector.ts @@ -15,7 +15,7 @@ export interface CreateConnectorBody { } export async function createConnector( - supertest: SuperTest.SuperTest, + supertest: SuperTest.Agent, connector: CreateConnectorBody, id = '' ): Promise { diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/connectors/delete_connector.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/connectors/delete_connector.ts index 683f845fd8bf8..1003c7cd8880b 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/connectors/delete_connector.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/connectors/delete_connector.ts @@ -7,9 +7,6 @@ import type SuperTest from 'supertest'; -export function deleteConnector( - supertest: SuperTest.SuperTest, - connectorId: string -): SuperTest.Test { +export function deleteConnector(supertest: SuperTest.Agent, connectorId: string): SuperTest.Test { return supertest.delete(`/api/actions/connector/${connectorId}`).set('kbn-xsrf', 'foo'); } diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/connectors/get_connector.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/connectors/get_connector.ts index 8f7e4830372f9..9132b188ecd33 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/connectors/get_connector.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/connectors/get_connector.ts @@ -9,7 +9,7 @@ import { Connector } from '@kbn/actions-plugin/server/application/connector/type import type SuperTest from 'supertest'; export async function getConnector( - supertest: SuperTest.SuperTest, + supertest: SuperTest.Agent, connectorId: string ): Promise { const response = await supertest diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/exception_list_and_item/item/create_exception_list_item.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/exception_list_and_item/item/create_exception_list_item.ts index fccbd3e243b17..39f202c13bce6 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/exception_list_and_item/item/create_exception_list_item.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/exception_list_and_item/item/create_exception_list_item.ts @@ -22,7 +22,7 @@ import { EXCEPTION_LIST_ITEM_URL } from '@kbn/securitysolution-list-constants'; * @param log The tooling logger */ export const createExceptionListItem = async ( - supertest: SuperTest.SuperTest, + supertest: SuperTest.Agent, log: ToolingLog, exceptionListItem: CreateExceptionListItemSchema ): Promise => { diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/exception_list_and_item/list/create_container_with_endpoint_entries.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/exception_list_and_item/list/create_container_with_endpoint_entries.ts index 7541514448b5c..442d341815c2f 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/exception_list_and_item/list/create_container_with_endpoint_entries.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/exception_list_and_item/list/create_container_with_endpoint_entries.ts @@ -27,7 +27,7 @@ import { createExceptionList } from './create_exception_list'; * @param osTypes The os types to optionally add or not to add to the container */ export const createContainerWithEndpointEntries = async ( - supertest: SuperTest.SuperTest, + supertest: SuperTest.Agent, log: ToolingLog, endpointEntries: Array<{ entries: NonEmptyEntriesArray; diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/exception_list_and_item/list/create_container_with_entries.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/exception_list_and_item/list/create_container_with_entries.ts index 973e0d1962a75..36aa1fb0e0652 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/exception_list_and_item/list/create_container_with_entries.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/exception_list_and_item/list/create_container_with_entries.ts @@ -23,7 +23,7 @@ import { waitFor } from '../../../../../../common/utils/security_solution'; * @param osTypes The os types to optionally add or not to add to the container */ export const createContainerWithEntries = async ( - supertest: SuperTest.SuperTest, + supertest: SuperTest.Agent, log: ToolingLog, entries: NonEmptyEntriesArray[] ): Promise => { diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/exception_list_and_item/list/create_exception_list.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/exception_list_and_item/list/create_exception_list.ts index 24ebabb5243b2..cae20d074a1c3 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/exception_list_and_item/list/create_exception_list.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/exception_list_and_item/list/create_exception_list.ts @@ -23,7 +23,7 @@ import { deleteExceptionList } from './delete_exception_list'; * @param log The tooling logger */ export const createExceptionList = async ( - supertest: SuperTest.SuperTest, + supertest: SuperTest.Agent, log: ToolingLog, exceptionList: CreateExceptionListSchema ): Promise => { diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/exception_list_and_item/list/delete_exception_list.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/exception_list_and_item/list/delete_exception_list.ts index 6c5558a005b97..17cc52ac8c4b6 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/exception_list_and_item/list/delete_exception_list.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/exception_list_and_item/list/delete_exception_list.ts @@ -18,7 +18,7 @@ import type { RuleResponse } from '@kbn/security-solution-plugin/common/api/dete * @param log The tooling logger */ export const deleteExceptionList = async ( - supertest: SuperTest.SuperTest, + supertest: SuperTest.Agent, log: ToolingLog, listId: string ): Promise => { diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/get_stats.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/get_stats.ts index 9415f6900a54f..bd8b3d3ea175c 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/get_stats.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/get_stats.ts @@ -22,7 +22,7 @@ import { getDetectionMetricsFromBody } from './get_detection_metrics_from_body'; * @returns The detection metrics */ export const getStats = async ( - supertest: SuperTest.SuperTest, + supertest: SuperTest.Agent, log: ToolingLog ): Promise => { const response = await supertest diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/machine_learning/machine_learning_setup.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/machine_learning/machine_learning_setup.ts index d7c7e6387c739..a9b9bf1c8ce5b 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/machine_learning/machine_learning_setup.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/machine_learning/machine_learning_setup.ts @@ -15,7 +15,7 @@ export const executeSetupModuleRequest = async ({ }: { module: string; rspCode: number; - supertest: SuperTest.SuperTest; + supertest: SuperTest.Agent; }) => { const { body } = await supertest .post(`/internal/ml/modules/setup/${module}`) @@ -40,7 +40,7 @@ export const forceStartDatafeeds = async ({ }: { jobId: string; rspCode: number; - supertest: SuperTest.SuperTest; + supertest: SuperTest.Agent; }) => { const { body } = await supertest .post(`/internal/ml/jobs/force_start_datafeeds`) diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/create_legacy_rule_action.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/create_legacy_rule_action.ts index 8e0cb59d5ee90..439dd6a44f4d8 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/create_legacy_rule_action.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/create_legacy_rule_action.ts @@ -10,7 +10,7 @@ import type SuperTest from 'supertest'; import { UPDATE_OR_CREATE_LEGACY_ACTIONS } from '@kbn/security-solution-plugin/common/constants'; export const createLegacyRuleAction = async ( - supertest: SuperTest.SuperTest, + supertest: SuperTest.Agent, alertId: string, connectorId: string ): Promise => diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/create_non_security_rule.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/create_non_security_rule.ts index 09bc0f9b81a6d..c6fd0f8d1bc78 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/create_non_security_rule.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/create_non_security_rule.ts @@ -30,9 +30,7 @@ const SIMPLE_APM_RULE_DATA = { * Created a non security rule. Helpful in tests to verify functionality works with presence of non security rules. * @param supertest The supertest deps */ -export async function createNonSecurityRule( - supertest: SuperTest.SuperTest -): Promise { +export async function createNonSecurityRule(supertest: SuperTest.Agent): Promise { await supertest .post('/api/alerting/rule') .set('kbn-xsrf', 'true') diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/create_rule_saved_object.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/create_rule_saved_object.ts index 93a6322011623..f4e3f22a0c9a6 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/create_rule_saved_object.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/create_rule_saved_object.ts @@ -21,7 +21,7 @@ import { * @param supertest */ export const createRuleThroughAlertingEndpoint = async ( - supertest: SuperTest.SuperTest, + supertest: SuperTest.Agent, rule: InternalRuleCreate ): Promise> => { const { body } = await supertest diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/create_rule_with_auth.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/create_rule_with_auth.ts index 7b5e4435a3dbb..cde330f8c76a1 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/create_rule_with_auth.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/create_rule_with_auth.ts @@ -19,7 +19,7 @@ import type { * @param rule The rule to create */ export const createRuleWithAuth = async ( - supertest: SuperTest.SuperTest, + supertest: SuperTest.Agent, rule: RuleCreateProps, auth: { user: string; pass: string } ): Promise => { diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/create_rule_with_exception_entries.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/create_rule_with_exception_entries.ts index ca2a8129b7713..a04ac5950596e 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/create_rule_with_exception_entries.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/create_rule_with_exception_entries.ts @@ -31,7 +31,7 @@ import { createRule } from '../../../../../common/utils/security_solution'; * @param osTypes The os types to optionally add or not to add to the container */ export const createRuleWithExceptionEntries = async ( - supertest: SuperTest.SuperTest, + supertest: SuperTest.Agent, log: ToolingLog, rule: RuleCreateProps, entries: NonEmptyEntriesArray[], diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/fetch_rule.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/fetch_rule.ts index 8e9e1008ff404..651bb2a595f8f 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/fetch_rule.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/fetch_rule.ts @@ -18,7 +18,7 @@ import { DETECTION_ENGINE_RULES_URL } from '@kbn/security-solution-plugin/common * @param rule The rule to create */ export const fetchRule = async ( - supertest: SuperTest.SuperTest, + supertest: SuperTest.Agent, idOrRuleId: { id: string; ruleId?: never } | { id?: never; ruleId: string } ): Promise => ( diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/find_immutable_rule_by_id.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/find_immutable_rule_by_id.ts index 55e7375c48986..f4b026748e986 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/find_immutable_rule_by_id.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/find_immutable_rule_by_id.ts @@ -17,7 +17,7 @@ import { DETECTION_ENGINE_RULES_URL } from '@kbn/security-solution-plugin/common * @param supertest The supertest deps */ export const findImmutableRuleById = async ( - supertest: SuperTest.SuperTest, + supertest: SuperTest.Agent, log: ToolingLog, ruleId: string ): Promise<{ diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/get_coverage_overview.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/get_coverage_overview.ts index f93a29b0ec149..b512494f245e2 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/get_coverage_overview.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/get_coverage_overview.ts @@ -13,7 +13,7 @@ import { } from '@kbn/security-solution-plugin/common/api/detection_engine'; export const getCoverageOverview = async ( - supertest: SuperTest.SuperTest, + supertest: SuperTest.Agent, filter?: CoverageOverviewFilter ): Promise => { const response = await supertest diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/get_rule_actions.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/get_rule_actions.ts index 3251d2b0a6b56..36784cc47aa1a 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/get_rule_actions.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/get_rule_actions.ts @@ -11,19 +11,16 @@ import { RuleActionArray } from '@kbn/securitysolution-io-ts-alerting-types'; import { getSlackAction } from '..'; import { getWebHookAction } from '..'; -const createConnector = async ( - supertest: SuperTest.SuperTest, - payload: Record -) => +const createConnector = async (supertest: SuperTest.Agent, payload: Record) => (await supertest.post('/api/actions/action').set('kbn-xsrf', 'true').send(payload).expect(200)) .body; -const createWebHookConnector = (supertest: SuperTest.SuperTest) => +const createWebHookConnector = (supertest: SuperTest.Agent) => createConnector(supertest, getWebHookAction()); -const createSlackConnector = (supertest: SuperTest.SuperTest) => +const createSlackConnector = (supertest: SuperTest.Agent) => createConnector(supertest, getSlackAction()); export const getActionsWithoutFrequencies = async ( - supertest: SuperTest.SuperTest + supertest: SuperTest.Agent ): Promise => { const webHookAction = await createWebHookConnector(supertest); const slackConnector = await createSlackConnector(supertest); @@ -44,7 +41,7 @@ export const getActionsWithoutFrequencies = async ( }; export const getActionsWithFrequencies = async ( - supertest: SuperTest.SuperTest + supertest: SuperTest.Agent ): Promise => { const webHookAction = await createWebHookConnector(supertest); const slackConnector = await createSlackConnector(supertest); @@ -67,7 +64,7 @@ export const getActionsWithFrequencies = async ( }; export const getSomeActionsWithFrequencies = async ( - supertest: SuperTest.SuperTest + supertest: SuperTest.Agent ): Promise => { const webHookAction = await createWebHookConnector(supertest); const slackConnector = await createSlackConnector(supertest); diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/patch_rule.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/patch_rule.ts index f62f49b20d622..44456c93a16cd 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/patch_rule.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/patch_rule.ts @@ -21,7 +21,7 @@ import { * @param rule The rule to create */ export const patchRule = async ( - supertest: SuperTest.SuperTest, + supertest: SuperTest.Agent, log: ToolingLog, patchedRule: RulePatchProps ): Promise => { diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/prebuilt_rules/delete_prebuilt_rules_fleet_package.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/prebuilt_rules/delete_prebuilt_rules_fleet_package.ts index 1647ff301a324..a3468ccb32b5a 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/prebuilt_rules/delete_prebuilt_rules_fleet_package.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/prebuilt_rules/delete_prebuilt_rules_fleet_package.ts @@ -13,9 +13,7 @@ import type SuperTest from 'supertest'; * * @param supertest Supertest instance */ -export async function deletePrebuiltRulesFleetPackage( - supertest: SuperTest.SuperTest -) { +export async function deletePrebuiltRulesFleetPackage(supertest: SuperTest.Agent) { const resp = await supertest .get(epmRouteService.getInfoPath('security_detection_engine')) .set('kbn-xsrf', 'true') diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/prebuilt_rules/get_installed_rules.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/prebuilt_rules/get_installed_rules.ts index f796dd06e777b..04a9c52565bf1 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/prebuilt_rules/get_installed_rules.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/prebuilt_rules/get_installed_rules.ts @@ -17,9 +17,7 @@ import { FindRulesResponse } from '@kbn/security-solution-plugin/common/api/dete * @returns Fleet install package response */ -export const getInstalledRules = async ( - supertest: SuperTest.SuperTest -): Promise => { +export const getInstalledRules = async (supertest: SuperTest.Agent): Promise => { const { body: rulesResponse } = await supertest .get(`${DETECTION_ENGINE_RULES_URL_FIND}?per_page=10000`) .set('kbn-xsrf', 'true') diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/prebuilt_rules/get_prebuilt_rules_and_timelines_status.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/prebuilt_rules/get_prebuilt_rules_and_timelines_status.ts index 7f683ca9994be..420f8a7aca1ce 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/prebuilt_rules/get_prebuilt_rules_and_timelines_status.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/prebuilt_rules/get_prebuilt_rules_and_timelines_status.ts @@ -21,7 +21,7 @@ import { refreshSavedObjectIndices } from '../../refresh_index'; */ export const getPrebuiltRulesAndTimelinesStatus = async ( es: Client, - supertest: SuperTest.SuperTest + supertest: SuperTest.Agent ): Promise => { await refreshSavedObjectIndices(es); diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/prebuilt_rules/get_prebuilt_rules_fleet_package.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/prebuilt_rules/get_prebuilt_rules_fleet_package.ts index ec69b6cfb14c2..2441e6f4dbc88 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/prebuilt_rules/get_prebuilt_rules_fleet_package.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/prebuilt_rules/get_prebuilt_rules_fleet_package.ts @@ -14,7 +14,7 @@ import type SuperTest from 'supertest'; * @param supertest Supertest instance * @returns The API endpoint response. Will have status 200 if package installed or 404 if not */ -export async function getPrebuiltRulesFleetPackage(supertest: SuperTest.SuperTest) { +export async function getPrebuiltRulesFleetPackage(supertest: SuperTest.Agent) { return await supertest .get(epmRouteService.getInfoPath('security_detection_engine')) .set('kbn-xsrf', 'true') diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/prebuilt_rules/get_prebuilt_rules_status.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/prebuilt_rules/get_prebuilt_rules_status.ts index da044637fc77b..10ca202c66f46 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/prebuilt_rules/get_prebuilt_rules_status.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/prebuilt_rules/get_prebuilt_rules_status.ts @@ -20,7 +20,7 @@ import { refreshSavedObjectIndices } from '../../refresh_index'; */ export const getPrebuiltRulesStatus = async ( es: Client, - supertest: SuperTest.SuperTest + supertest: SuperTest.Agent ): Promise => { await refreshSavedObjectIndices(es); diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/prebuilt_rules/install_fleet_package_by_url.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/prebuilt_rules/install_fleet_package_by_url.ts index 863e4d79fb006..b88a848758a8f 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/prebuilt_rules/install_fleet_package_by_url.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/prebuilt_rules/install_fleet_package_by_url.ts @@ -26,7 +26,7 @@ const ATTEMPT_TIMEOUT = 120000; export const installPrebuiltRulesPackageViaFleetAPI = async ( es: Client, - supertest: SuperTest.SuperTest, + supertest: SuperTest.Agent, retryService: RetryService ): Promise => { const fleetResponse = await retryService.tryWithRetries( @@ -66,7 +66,7 @@ export const installPrebuiltRulesPackageViaFleetAPI = async ( export const installPrebuiltRulesPackageByVersion = async ( es: Client, - supertest: SuperTest.SuperTest, + supertest: SuperTest.Agent, version: string, retryService: RetryService ): Promise => { diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/prebuilt_rules/install_mock_prebuilt_rules.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/prebuilt_rules/install_mock_prebuilt_rules.ts index 0e15f416e1238..843d0531e53ba 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/prebuilt_rules/install_mock_prebuilt_rules.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/prebuilt_rules/install_mock_prebuilt_rules.ts @@ -19,7 +19,7 @@ import { installPrebuiltRulesAndTimelines } from './install_prebuilt_rules_and_t * @returns Install prebuilt rules response */ export const installMockPrebuiltRules = async ( - supertest: SuperTest.SuperTest, + supertest: SuperTest.Agent, es: Client ): Promise => { // Ensure there are prebuilt rule saved objects before installing rules diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/prebuilt_rules/install_prebuilt_rules.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/prebuilt_rules/install_prebuilt_rules.ts index 499f97877bf16..eec88072e7d1e 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/prebuilt_rules/install_prebuilt_rules.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/prebuilt_rules/install_prebuilt_rules.ts @@ -30,7 +30,7 @@ import { refreshSavedObjectIndices } from '../../refresh_index'; */ export const installPrebuiltRules = async ( es: Client, - supertest: SuperTest.SuperTest, + supertest: SuperTest.Agent, rules?: RuleVersionSpecifier[] ): Promise => { let payload = {}; diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/prebuilt_rules/install_prebuilt_rules_and_timelines.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/prebuilt_rules/install_prebuilt_rules_and_timelines.ts index c83e8693f2390..a52a44a90bfe7 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/prebuilt_rules/install_prebuilt_rules_and_timelines.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/prebuilt_rules/install_prebuilt_rules_and_timelines.ts @@ -31,7 +31,7 @@ import { refreshSavedObjectIndices } from '../../refresh_index'; */ export const installPrebuiltRulesAndTimelines = async ( es: Client, - supertest: SuperTest.SuperTest + supertest: SuperTest.Agent ): Promise => { const response = await supertest .put(PREBUILT_RULES_URL) diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/prebuilt_rules/install_prebuilt_rules_fleet_package.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/prebuilt_rules/install_prebuilt_rules_fleet_package.ts index cbe609501a5f2..f7a7337d40241 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/prebuilt_rules/install_prebuilt_rules_fleet_package.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/prebuilt_rules/install_prebuilt_rules_fleet_package.ts @@ -36,7 +36,7 @@ export const installPrebuiltRulesFleetPackage = async ({ retryService, }: { es: Client; - supertest: SuperTest.SuperTest; + supertest: SuperTest.Agent; version?: string; overrideExistingPackage: boolean; retryService: RetryService; diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/prebuilt_rules/review_install_prebuilt_rules.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/prebuilt_rules/review_install_prebuilt_rules.ts index 573b481a3b30f..487d2dbe53044 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/prebuilt_rules/review_install_prebuilt_rules.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/prebuilt_rules/review_install_prebuilt_rules.ts @@ -16,7 +16,7 @@ import type SuperTest from 'supertest'; * @returns Review Install prebuilt rules response */ export const reviewPrebuiltRulesToInstall = async ( - supertest: SuperTest.SuperTest + supertest: SuperTest.Agent ): Promise => { const response = await supertest .post(REVIEW_RULE_INSTALLATION_URL) diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/prebuilt_rules/review_upgrade_prebuilt_rules.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/prebuilt_rules/review_upgrade_prebuilt_rules.ts index 9bbf980dcccca..17347ffcdd1e3 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/prebuilt_rules/review_upgrade_prebuilt_rules.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/prebuilt_rules/review_upgrade_prebuilt_rules.ts @@ -16,7 +16,7 @@ import type SuperTest from 'supertest'; * @returns Review Upgrade prebuilt rules response */ export const reviewPrebuiltRulesToUpgrade = async ( - supertest: SuperTest.SuperTest + supertest: SuperTest.Agent ): Promise => { const response = await supertest .post(REVIEW_RULE_UPGRADE_URL) diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/prebuilt_rules/upgrade_prebuilt_rules.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/prebuilt_rules/upgrade_prebuilt_rules.ts index c22aa9106a272..f12d0adbc65f3 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/prebuilt_rules/upgrade_prebuilt_rules.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/prebuilt_rules/upgrade_prebuilt_rules.ts @@ -26,7 +26,7 @@ import { refreshSavedObjectIndices } from '../../refresh_index'; */ export const upgradePrebuiltRules = async ( es: Client, - supertest: SuperTest.SuperTest, + supertest: SuperTest.Agent, rules?: RuleVersionSpecifier[] ): Promise => { let payload = {}; diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/preview_rule.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/preview_rule.ts index ec060c4076404..a939454e72c9f 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/preview_rule.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/preview_rule.ts @@ -27,7 +27,7 @@ export const previewRule = async ({ invocationCount = 1, timeframeEnd = new Date(), }: { - supertest: SuperTest.SuperTest; + supertest: SuperTest.Agent; rule: RuleCreateProps; invocationCount?: number; timeframeEnd?: Date; diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/preview_rule_with_exception_entries.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/preview_rule_with_exception_entries.ts index fb5d480bbbffc..f02a5d370daaa 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/preview_rule_with_exception_entries.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/preview_rule_with_exception_entries.ts @@ -35,7 +35,7 @@ export const previewRuleWithExceptionEntries = async ({ invocationCount, timeframeEnd, }: { - supertest: SuperTest.SuperTest; + supertest: SuperTest.Agent; log: ToolingLog; rule: RuleCreateProps; entries: NonEmptyEntriesArray[]; diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/update_rule.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/update_rule.ts index 5c6c69a230465..cee439311d2a1 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/update_rule.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/update_rule.ts @@ -21,7 +21,7 @@ import { * @param rule The rule to create */ export const updateRule = async ( - supertest: SuperTest.SuperTest, + supertest: SuperTest.Agent, updatedRule: RuleUpdateProps ): Promise => ( diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/telemetry/get_security_telemetry_stats.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/telemetry/get_security_telemetry_stats.ts index 462cdecbb498d..d1345597adc95 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/telemetry/get_security_telemetry_stats.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/telemetry/get_security_telemetry_stats.ts @@ -21,7 +21,7 @@ import { * @returns The detection metrics */ export const getSecurityTelemetryStats = async ( - supertest: SuperTest.SuperTest, + supertest: SuperTest.Agent, log: ToolingLog ): Promise => { const response = await supertest diff --git a/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/utils/asset_criticality.ts b/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/utils/asset_criticality.ts index 6f13a84504e1d..3a46aa56ef614 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/utils/asset_criticality.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/utils/asset_criticality.ts @@ -104,7 +104,7 @@ export const getAssetCriticalityDoc = async (opts: { }; export const assetCriticalityRouteHelpersFactory = ( - supertest: SuperTest.SuperTest, + supertest: SuperTest.Agent, namespace?: string ) => ({ status: async () => @@ -170,7 +170,7 @@ export const assetCriticalityRouteHelpersFactory = ( }); export const assetCriticalityRouteHelpersFactoryNoAuth = ( - supertestWithoutAuth: SuperTest.SuperTest, + supertestWithoutAuth: SuperTest.Agent, namespace?: string ) => ({ privilegesForUser: async ({ username, password }: { username: string; password: string }) => diff --git a/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/utils/get_risk_engine_stats.ts b/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/utils/get_risk_engine_stats.ts index 5629e0da9a89d..fd9ff0eb88177 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/utils/get_risk_engine_stats.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/utils/get_risk_engine_stats.ts @@ -22,7 +22,7 @@ import { getRiskEngineMetricsFromBody } from './get_risk_engine_metrics_from_bod * @returns The detection metrics */ export const getRiskEngineStats = async ( - supertest: SuperTest.SuperTest, + supertest: SuperTest.Agent, log: ToolingLog ): Promise => { const response = await supertest diff --git a/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/utils/risk_engine.ts b/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/utils/risk_engine.ts index be7010ab1fc7b..dbd4ed78c1896 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/utils/risk_engine.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/utils/risk_engine.ts @@ -76,7 +76,7 @@ export const createAndSyncRuleAndAlertsFactory = log, namespace, }: { - supertest: SuperTest.SuperTest; + supertest: SuperTest.Agent; log: ToolingLog; namespace?: string; }) => @@ -412,7 +412,7 @@ export const clearLegacyDashboards = async ({ supertest, log, }: { - supertest: SuperTest.SuperTest; + supertest: SuperTest.Agent; log: ToolingLog; }): Promise => { try { @@ -481,10 +481,7 @@ export const getLegacyRiskScoreDashboards = async ({ return savedObejectLens?.saved_objects.filter((s) => s?.attributes?.title?.includes('Risk')); }; -export const riskEngineRouteHelpersFactory = ( - supertest: SuperTest.SuperTest, - namespace?: string -) => ({ +export const riskEngineRouteHelpersFactory = (supertest: SuperTest.Agent, namespace?: string) => ({ init: async (expectStatusCode: number = 200) => await supertest .post(routeWithNamespace(RISK_ENGINE_INIT_URL, namespace)) @@ -536,7 +533,7 @@ interface Credentials { } export const riskEngineRouteHelpersFactoryNoAuth = ( - supertestWithoutAuth: SuperTest.SuperTest, + supertestWithoutAuth: SuperTest.Agent, namespace?: string ) => ({ privilegesForUser: async ({ username, password }: Credentials) => @@ -576,11 +573,7 @@ export const riskEngineRouteHelpersFactoryNoAuth = ( .expect(expectStatusCode), }); -export const installLegacyRiskScore = async ({ - supertest, -}: { - supertest: SuperTest.SuperTest; -}) => { +export const installLegacyRiskScore = async ({ supertest }: { supertest: SuperTest.Agent }) => { await supertest .post('/internal/risk_score') .set('kbn-xsrf', 'true') diff --git a/x-pack/test/security_solution_api_integration/test_suites/genai/invoke_ai/utils/create_connector.ts b/x-pack/test/security_solution_api_integration/test_suites/genai/invoke_ai/utils/create_connector.ts index ac2d60ad631e2..0c7823ef07885 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/genai/invoke_ai/utils/create_connector.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/genai/invoke_ai/utils/create_connector.ts @@ -45,7 +45,7 @@ const connectorSetup = { * @param spaceId The space id */ export const createConnector = async ( - supertest: SuperTest.SuperTest, + supertest: SuperTest.Agent, objectRemover: ObjectRemover, apiUrl: string, connectorType: 'bedrock' | 'openai', diff --git a/x-pack/test/security_solution_api_integration/test_suites/genai/invoke_ai/utils/post_actions_client_execute.ts b/x-pack/test/security_solution_api_integration/test_suites/genai/invoke_ai/utils/post_actions_client_execute.ts index 0477401a26533..b5ed8c15b3fb2 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/genai/invoke_ai/utils/post_actions_client_execute.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/genai/invoke_ai/utils/post_actions_client_execute.ts @@ -21,7 +21,7 @@ import { Response } from 'superagent'; export const postActionsClientExecute = async ( connectorId: string, args: any, - supertest: SuperTest.SuperTest + supertest: SuperTest.Agent ): Promise => { const response = await supertest .post(`/internal/elastic_assistant/actions/connector/${connectorId}/_execute`) diff --git a/x-pack/test/security_solution_api_integration/test_suites/investigation/saved_objects/trial_license_complete_tier/helpers.ts b/x-pack/test/security_solution_api_integration/test_suites/investigation/saved_objects/trial_license_complete_tier/helpers.ts index 38212020ba18a..1f1a4bb821082 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/investigation/saved_objects/trial_license_complete_tier/helpers.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/investigation/saved_objects/trial_license_complete_tier/helpers.ts @@ -9,10 +9,7 @@ import type SuperTest from 'supertest'; import { v4 as uuidv4 } from 'uuid'; import { TimelineType } from '@kbn/security-solution-plugin/common/api/timeline'; -export const createBasicTimeline = async ( - supertest: SuperTest.SuperTest, - titleToSaved: string -) => +export const createBasicTimeline = async (supertest: SuperTest.Agent, titleToSaved: string) => await supertest .post('/api/timeline') .set('kbn-xsrf', 'true') @@ -25,7 +22,7 @@ export const createBasicTimeline = async ( }); export const createBasicTimelineTemplate = async ( - supertest: SuperTest.SuperTest, + supertest: SuperTest.Agent, titleToSaved: string ) => await supertest diff --git a/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/utils.ts b/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/utils.ts index d45a77be0840b..c4bde53fcab7d 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/utils.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/utils.ts @@ -41,7 +41,7 @@ import { countDownTest } from '../../../common/utils/security_solution'; * @param supertest The supertest client library */ export const createListsIndex = async ( - supertest: SuperTest.SuperTest, + supertest: SuperTest.Agent, log: ToolingLog ): Promise => { return countDownTest( @@ -61,7 +61,7 @@ export const createListsIndex = async ( * @param supertest The supertest client library */ export const deleteListsIndex = async ( - supertest: SuperTest.SuperTest, + supertest: SuperTest.Agent, log: ToolingLog ): Promise => { return countDownTest( @@ -82,7 +82,7 @@ export const deleteListsIndex = async ( * @param supertest The supertest client library */ export const createExceptionListsIndex = async ( - supertest: SuperTest.SuperTest, + supertest: SuperTest.Agent, log: ToolingLog ): Promise => { return countDownTest( @@ -205,7 +205,7 @@ export const binaryToString = (res: any, callback: any): void => { * @param supertest The supertest handle */ export const deleteAllExceptions = async ( - supertest: SuperTest.SuperTest, + supertest: SuperTest.Agent, log: ToolingLog ): Promise => { await deleteAllExceptionsByType(supertest, log, 'single'); @@ -218,7 +218,7 @@ export const deleteAllExceptions = async ( * @param supertest The supertest handle */ export const deleteAllExceptionsByType = async ( - supertest: SuperTest.SuperTest, + supertest: SuperTest.Agent, log: ToolingLog, type: NamespaceType ): Promise => { @@ -260,7 +260,7 @@ export const deleteAllExceptionsByType = async ( * @param testValues Optional test values in case you're using CIDR or range based lists */ export const importFile = async ( - supertest: SuperTest.SuperTest, + supertest: SuperTest.Agent, log: ToolingLog, type: Type, contents: string[], @@ -297,7 +297,7 @@ export const importFile = async ( * @param fileName filename to import as */ export const importTextFile = async ( - supertest: SuperTest.SuperTest, + supertest: SuperTest.Agent, log: ToolingLog, type: Type, contents: string[], @@ -330,7 +330,7 @@ export const importTextFile = async ( * @param itemValue The item value to wait for */ export const waitForListItem = async ( - supertest: SuperTest.SuperTest, + supertest: SuperTest.Agent, log: ToolingLog, itemValue: string, fileName: string @@ -362,7 +362,7 @@ export const waitForListItem = async ( * @param itemValue The item value to wait for */ export const waitForListItems = async ( - supertest: SuperTest.SuperTest, + supertest: SuperTest.Agent, log: ToolingLog, itemValues: string[], fileName: string @@ -378,7 +378,7 @@ export const waitForListItems = async ( * @param itemValue The item value to wait for */ export const waitForTextListItem = async ( - supertest: SuperTest.SuperTest, + supertest: SuperTest.Agent, log: ToolingLog, itemValue: string, fileName: string @@ -417,7 +417,7 @@ export const waitForTextListItem = async ( * @param itemValue The item value to wait for */ export const waitForTextListItems = async ( - supertest: SuperTest.SuperTest, + supertest: SuperTest.Agent, log: ToolingLog, itemValues: string[], fileName: string diff --git a/x-pack/test/security_solution_cypress/cypress/cypress.config.ts b/x-pack/test/security_solution_cypress/cypress/cypress.config.ts index 387f3b7aec118..ef9a5b6130966 100644 --- a/x-pack/test/security_solution_cypress/cypress/cypress.config.ts +++ b/x-pack/test/security_solution_cypress/cypress/cypress.config.ts @@ -9,6 +9,7 @@ import { defineCypressConfig } from '@kbn/cypress-config'; import { esArchiver } from './support/es_archiver'; export default defineCypressConfig({ + chromeWebSecurity: false, defaultCommandTimeout: 60000, env: { grepFilterSpecs: true, @@ -21,8 +22,8 @@ export default defineCypressConfig({ trashAssetsBeforeRuns: false, video: false, videosFolder: '../../../target/kibana-security-solution/cypress/videos', - viewportHeight: 946, - viewportWidth: 1680, + viewportHeight: 1200, + viewportWidth: 1920, numTestsKeptInMemory: 10, e2e: { experimentalRunAllSpecs: true, @@ -30,6 +31,18 @@ export default defineCypressConfig({ experimentalCspAllowList: ['default-src', 'script-src', 'script-src-elem'], setupNodeEvents(on, config) { esArchiver(on, config); + on('before:browser:launch', (browser, launchOptions) => { + if (browser.name === 'chrome' && browser.isHeadless) { + launchOptions.args.push('--window-size=1920,1200'); + return launchOptions; + } + if (browser.family === 'chromium') { + launchOptions.args.push( + '--js-flags="--max_old_space_size=4096 --max_semi_space_size=1024"' + ); + } + return launchOptions; + }); // eslint-disable-next-line @typescript-eslint/no-var-requires require('@cypress/grep/src/plugin')(config); return config; diff --git a/x-pack/test/security_solution_cypress/cypress/cypress_ci.config.ts b/x-pack/test/security_solution_cypress/cypress/cypress_ci.config.ts index bb632fb237c9d..3fae578ab1145 100644 --- a/x-pack/test/security_solution_cypress/cypress/cypress_ci.config.ts +++ b/x-pack/test/security_solution_cypress/cypress/cypress_ci.config.ts @@ -14,6 +14,7 @@ export default defineCypressConfig({ reporterOptions: { configFile: './cypress/reporter_config.json', }, + chromeWebSecurity: false, defaultCommandTimeout: 150000, env: { grepFilterSpecs: true, @@ -30,8 +31,8 @@ export default defineCypressConfig({ trashAssetsBeforeRuns: false, video: false, videosFolder: '../../../target/kibana-security-solution/cypress/videos', - viewportHeight: 946, - viewportWidth: 1680, + viewportHeight: 1200, + viewportWidth: 1920, e2e: { baseUrl: 'http://localhost:5601', experimentalMemoryManagement: true, @@ -39,6 +40,18 @@ export default defineCypressConfig({ specPattern: './cypress/e2e/**/*.cy.ts', setupNodeEvents(on, config) { esArchiver(on, config); + on('before:browser:launch', (browser, launchOptions) => { + if (browser.name === 'chrome' && browser.isHeadless) { + launchOptions.args.push('--window-size=1920,1200'); + return launchOptions; + } + if (browser.family === 'chromium') { + launchOptions.args.push( + '--js-flags="--max_old_space_size=4096 --max_semi_space_size=1024"' + ); + } + return launchOptions; + }); // eslint-disable-next-line @typescript-eslint/no-var-requires require('@cypress/grep/src/plugin')(config); return config; diff --git a/x-pack/test/security_solution_cypress/cypress/cypress_ci_serverless.config.ts b/x-pack/test/security_solution_cypress/cypress/cypress_ci_serverless.config.ts index 80afa64fbb7a5..a5d59ca4dd4c6 100644 --- a/x-pack/test/security_solution_cypress/cypress/cypress_ci_serverless.config.ts +++ b/x-pack/test/security_solution_cypress/cypress/cypress_ci_serverless.config.ts @@ -15,6 +15,7 @@ export default defineCypressConfig({ reporterOptions: { configFile: './cypress/reporter_config.json', }, + chromeWebSecurity: false, defaultCommandTimeout: 150000, env: { grepFilterSpecs: true, @@ -31,8 +32,8 @@ export default defineCypressConfig({ trashAssetsBeforeRuns: false, video: false, videosFolder: '../../../../target/kibana-security-solution/cypress/videos', - viewportHeight: 946, - viewportWidth: 1680, + viewportHeight: 1200, + viewportWidth: 1920, e2e: { baseUrl: 'http://localhost:5601', experimentalCspAllowList: ['default-src', 'script-src', 'script-src-elem'], @@ -40,6 +41,18 @@ export default defineCypressConfig({ specPattern: './cypress/e2e/**/*.cy.ts', setupNodeEvents(on, config) { esArchiver(on, config); + on('before:browser:launch', (browser, launchOptions) => { + if (browser.name === 'chrome' && browser.isHeadless) { + launchOptions.args.push('--window-size=1920,1200'); + return launchOptions; + } + if (browser.family === 'chromium') { + launchOptions.args.push( + '--js-flags="--max_old_space_size=4096 --max_semi_space_size=1024"' + ); + } + return launchOptions; + }); samlAuthentication(on, config); // eslint-disable-next-line @typescript-eslint/no-var-requires require('@cypress/grep/src/plugin')(config); diff --git a/x-pack/test/security_solution_cypress/cypress/cypress_ci_serverless_qa.config.ts b/x-pack/test/security_solution_cypress/cypress/cypress_ci_serverless_qa.config.ts index d0d5dd3f00154..c2ad97b6ddb05 100644 --- a/x-pack/test/security_solution_cypress/cypress/cypress_ci_serverless_qa.config.ts +++ b/x-pack/test/security_solution_cypress/cypress/cypress_ci_serverless_qa.config.ts @@ -15,6 +15,7 @@ export default defineCypressConfig({ reporterOptions: { configFile: './cypress/reporter_config.json', }, + chromeWebSecurity: false, defaultCommandTimeout: 300000, env: { grepFilterSpecs: true, @@ -33,8 +34,8 @@ export default defineCypressConfig({ trashAssetsBeforeRuns: false, video: false, videosFolder: '../../../../target/kibana-security-solution/cypress/videos', - viewportHeight: 946, - viewportWidth: 1680, + viewportHeight: 1200, + viewportWidth: 1920, e2e: { baseUrl: 'http://localhost:5601', experimentalCspAllowList: ['default-src', 'script-src', 'script-src-elem'], @@ -42,6 +43,18 @@ export default defineCypressConfig({ specPattern: './cypress/e2e/**/*.cy.ts', setupNodeEvents(on, config) { esArchiver(on, config); + on('before:browser:launch', (browser, launchOptions) => { + if (browser.name === 'chrome' && browser.isHeadless) { + launchOptions.args.push('--window-size=1920,1200'); + return launchOptions; + } + if (browser.family === 'chromium') { + launchOptions.args.push( + '--js-flags="--max_old_space_size=4096 --max_semi_space_size=1024"' + ); + } + return launchOptions; + }); samlAuthentication(on, config); process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'; // eslint-disable-next-line @typescript-eslint/no-var-requires diff --git a/x-pack/test/security_solution_cypress/cypress/cypress_serverless.config.ts b/x-pack/test/security_solution_cypress/cypress/cypress_serverless.config.ts index 8f66e7f1a4173..5ca79319c8c32 100644 --- a/x-pack/test/security_solution_cypress/cypress/cypress_serverless.config.ts +++ b/x-pack/test/security_solution_cypress/cypress/cypress_serverless.config.ts @@ -11,6 +11,7 @@ import { samlAuthentication } from './support/saml_auth'; // eslint-disable-next-line import/no-default-export export default defineCypressConfig({ + chromeWebSecurity: false, defaultCommandTimeout: 60000, execTimeout: 60000, pageLoadTimeout: 60000, @@ -19,8 +20,8 @@ export default defineCypressConfig({ trashAssetsBeforeRuns: false, video: false, videosFolder: '../../../target/kibana-security-solution/cypress/videos', - viewportHeight: 946, - viewportWidth: 1680, + viewportHeight: 1200, + viewportWidth: 1920, numTestsKeptInMemory: 10, env: { grepFilterSpecs: true, @@ -32,6 +33,18 @@ export default defineCypressConfig({ experimentalMemoryManagement: true, setupNodeEvents(on, config) { esArchiver(on, config); + on('before:browser:launch', (browser, launchOptions) => { + if (browser.name === 'chrome' && browser.isHeadless) { + launchOptions.args.push('--window-size=1920,1200'); + return launchOptions; + } + if (browser.family === 'chromium') { + launchOptions.args.push( + '--js-flags="--max_old_space_size=4096 --max_semi_space_size=1024"' + ); + } + return launchOptions; + }); samlAuthentication(on, config); // eslint-disable-next-line @typescript-eslint/no-var-requires require('@cypress/grep/src/plugin')(config); diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/detection_engine/rule_creation/common_flows.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/detection_engine/rule_creation/common_flows.cy.ts index 6bf3ea611dc7f..abf8bc3934e21 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/detection_engine/rule_creation/common_flows.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/detection_engine/rule_creation/common_flows.cy.ts @@ -33,6 +33,8 @@ import { fillMaxSignals, fillNote, fillReferenceUrls, + // fillRelatedIntegrations, + // fillRequiredFields, fillRiskScore, fillRuleName, fillRuleTags, @@ -67,9 +69,13 @@ describe('Common rule creation flows', { tags: ['@ess', '@serverless'] }, () => it('Creates and enables a rule', function () { cy.log('Filling define section'); importSavedQuery(this.timelineId); - // The following step is flaky due to a recent EUI upgrade. - // Underlying EUI issue: https://github.com/elastic/eui/issues/7761 - // Issue to uncomment this once EUI fix is in place: https://github.com/elastic/kibana/issues/183485 + /* + The following steps are flaky due to a recent EUI upgrade. + + Underlying EUI issue: https://github.com/elastic/eui/issues/7761 + Issue to uncomment these once the EUI fix is in place: https://github.com/elastic/kibana/issues/183485 + */ + // fillRequiredFields(); // fillRelatedIntegrations(); cy.get(DEFINE_CONTINUE_BUTTON).click(); diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/detection_engine/value_lists/value_list_items.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/detection_engine/value_lists/value_list_items.cy.ts index 9e9a6ec8fdf61..11fb0aa197450 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/detection_engine/value_lists/value_list_items.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/detection_engine/value_lists/value_list_items.cy.ts @@ -41,7 +41,8 @@ import { import { RULES_MANAGEMENT_URL } from '../../../../urls/rules_management'; import { getDefaultUsername } from '../../../../tasks/common/users'; -describe( +// Failing: See https://github.com/elastic/kibana/issues/183713 +describe.skip( 'Value list items', { tags: ['@ess', '@serverless'], diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_management/prebuilt_rules/prebuilt_rules_preview.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_management/prebuilt_rules/prebuilt_rules_preview.cy.ts index 84198ccd702dd..15229445e54f0 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_management/prebuilt_rules/prebuilt_rules_preview.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_management/prebuilt_rules/prebuilt_rules_preview.cy.ts @@ -137,8 +137,8 @@ describe('Detection rules, Prebuilt Rules Installation and Update workflow', () { package: 'windows', version: '^1.5.0' }, ], required_fields: [ - { ecs: true, name: 'event.type', type: 'keyword' }, - { ecs: true, name: 'file.extension', type: 'keyword' }, + { name: 'event.type', type: 'keyword' }, + { name: 'file.extension', type: 'keyword' }, ], timeline_id: '3e827bab-838a-469f-bd1e-5e19a2bff2fd', timeline_title: 'Alerts Involving a Single User Timeline', diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/investigations/timeline_templates/creation.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/investigations/timeline_templates/creation.cy.ts index 40efaa1f20883..4e2da9bc9170b 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/investigations/timeline_templates/creation.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/investigations/timeline_templates/creation.cy.ts @@ -48,7 +48,8 @@ import { GLOBAL_SEARCH_BAR_FILTER_ITEM_AT } from '../../../screens/search_bar'; const mockTimeline = getTimeline(); -describe('Timeline Templates', { tags: ['@ess', '@serverless'] }, () => { +// FLAKY: https://github.com/elastic/kibana/issues/183579 +describe.skip('Timeline Templates', { tags: ['@ess', '@serverless'] }, () => { beforeEach(() => { login(); deleteTimelines(); diff --git a/x-pack/test/security_solution_cypress/cypress/screens/create_new_rule.ts b/x-pack/test/security_solution_cypress/cypress/screens/create_new_rule.ts index 88b8c2192d1bf..b0af7275ae808 100644 --- a/x-pack/test/security_solution_cypress/cypress/screens/create_new_rule.ts +++ b/x-pack/test/security_solution_cypress/cypress/screens/create_new_rule.ts @@ -115,6 +115,8 @@ export const EQL_QUERY_INPUT = '[data-test-subj="eqlQueryBarTextInput"]'; export const EQL_QUERY_VALIDATION_SPINNER = '[data-test-subj="eql-validation-loading"]'; +export const EQL_QUERY_VALIDATION_LABEL = '.euiFormLabel-isInvalid'; + export const EQL_QUERY_VALIDATION_ERROR = '[data-test-subj="eql-validation-errors-popover-button"]'; export const EQL_OPTIONS_POPOVER_TRIGGER = '[data-test-subj="eql-settings-trigger"]'; @@ -128,6 +130,9 @@ export const IMPORT_QUERY_FROM_SAVED_TIMELINE_LINK = export const RELATED_INTEGRATION_COMBO_BOX_INPUT = '[data-test-subj="relatedIntegrationComboBox"] [data-test-subj="comboBoxSearchInput"]'; +export const REQUIRED_FIELD_COMBO_BOX_INPUT = + '[data-test-subj^="requiredFieldNameSelect"] [data-test-subj="comboBoxSearchInput"]'; + export const INDICATOR_MATCH_TYPE = '[data-test-subj="threatMatchRuleType"]'; export const INPUT = '[data-test-subj="input"]'; diff --git a/x-pack/test/security_solution_cypress/cypress/tasks/create_new_rule.ts b/x-pack/test/security_solution_cypress/cypress/tasks/create_new_rule.ts index 7ee1811760480..a71d990ec31a9 100644 --- a/x-pack/test/security_solution_cypress/cypress/tasks/create_new_rule.ts +++ b/x-pack/test/security_solution_cypress/cypress/tasks/create_new_rule.ts @@ -82,6 +82,7 @@ import { MITRE_TACTIC, QUERY_BAR, REFERENCE_URLS_INPUT, + REQUIRED_FIELD_COMBO_BOX_INPUT, RISK_MAPPING_OVERRIDE_OPTION, RISK_OVERRIDE, RULE_DESCRIPTION_INPUT, @@ -480,6 +481,18 @@ export const fillScheduleRuleAndContinue = (rule: RuleCreateProps) => { cy.get(SCHEDULE_CONTINUE_BUTTON).click({ force: true }); }; +export const fillRequiredFields = (): void => { + addRequiredField(); + addRequiredField(); +}; + +const addRequiredField = (): void => { + cy.contains('button', 'Add required field').should('be.enabled').click(); + + cy.get(REQUIRED_FIELD_COMBO_BOX_INPUT).last().should('be.enabled').click(); + cy.get(COMBO_BOX_OPTION).first().click(); +}; + /** * use default schedule options */ diff --git a/x-pack/test/security_solution_cypress/cypress/tasks/timeline.ts b/x-pack/test/security_solution_cypress/cypress/tasks/timeline.ts index 0b6fb3c31cb6a..75c78c24e4dc6 100644 --- a/x-pack/test/security_solution_cypress/cypress/tasks/timeline.ts +++ b/x-pack/test/security_solution_cypress/cypress/tasks/timeline.ts @@ -10,7 +10,10 @@ import type { Timeline, TimelineFilter } from '../objects/timeline'; import { ALL_CASES_CREATE_NEW_CASE_TABLE_BTN } from '../screens/all_cases'; import { FIELDS_BROWSER_CHECKBOX } from '../screens/fields_browser'; -import { EQL_QUERY_VALIDATION_SPINNER } from '../screens/create_new_rule'; +import { + EQL_QUERY_VALIDATION_LABEL, + EQL_QUERY_VALIDATION_SPINNER, +} from '../screens/create_new_rule'; import { ADD_FILTER, @@ -188,6 +191,7 @@ export const clearEqlInTimeline = () => { cy.get(TIMELINE_CORRELATION_INPUT).type('{selectAll} {del}'); cy.get(TIMELINE_CORRELATION_INPUT).clear(); cy.get(EQL_QUERY_VALIDATION_SPINNER).should('not.exist'); + cy.get(EQL_QUERY_VALIDATION_LABEL).should('not.exist'); }; export const addFilter = (filter: TimelineFilter): Cypress.Chainable> => { 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 58ffde0d7611f..6c78dd995673f 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 @@ -30,7 +30,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { const pageObjects = getPageObjects(['common', 'artifactEntriesList']); const testSubjects = getService('testSubjects'); const browser = getService('browser'); - const endpointArtifactsTestResources = getService('endpointArtifactTestResources'); + const endpointArtifactTestResources = getService('endpointArtifactTestResources'); const endpointTestResources = getService('endpointTestResources'); const retry = getService('retry'); const esClient = getService('es'); @@ -76,7 +76,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { // Check edited artifact is in the list with new values (wait for list to be updated) let updatedArtifact: ArtifactElasticsearchProperties | undefined; await retry.waitForWithTimeout('fleet artifact is updated', 120_000, async () => { - const artifacts = await endpointArtifactsTestResources.getArtifacts(); + const artifacts = await endpointArtifactTestResources.getArtifacts(); const manifestArtifact = artifacts.find((artifact) => { return ( diff --git a/x-pack/test/security_solution_endpoint/apps/integrations_feature_flag/artifact_entries_list.ts b/x-pack/test/security_solution_endpoint/apps/integrations_feature_flag/artifact_entries_list.ts new file mode 100644 index 0000000000000..46e333e10779d --- /dev/null +++ b/x-pack/test/security_solution_endpoint/apps/integrations_feature_flag/artifact_entries_list.ts @@ -0,0 +1,376 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { unzip } from 'zlib'; +import { promisify } from 'util'; +import expect from '@kbn/expect'; +import { IndexedHostsAndAlertsResponse } from '@kbn/security-solution-plugin/common/endpoint/index_data'; +import { + ENDPOINT_ARTIFACT_LIST_IDS, + EXCEPTION_LIST_URL, +} from '@kbn/securitysolution-list-constants'; +import { ArtifactElasticsearchProperties } from '@kbn/fleet-plugin/server/services'; +import { FtrProviderContext } from '../../ftr_provider_context'; +import { + ArtifactBodyType, + getArtifactsListTestsData, + ArtifactActionsType, + AgentPolicyResponseType, + getCreateMultipleData, + MultipleArtifactActionsType, +} from './mocks'; +import { PolicyTestResourceInfo } from '../../services/endpoint_policy'; +import { targetTags } from '../../target_tags'; + +export default ({ getPageObjects, getService }: FtrProviderContext) => { + const pageObjects = getPageObjects(['common', 'artifactEntriesList']); + const testSubjects = getService('testSubjects'); + const browser = getService('browser'); + const endpointArtifactsTestResources = getService('endpointArtifactTestResources'); + const endpointTestResources = getService('endpointTestResources'); + const retry = getService('retry'); + const esClient = getService('es'); + const supertest = getService('supertest'); + const find = getService('find'); + const toasts = getService('toasts'); + const policyTestResources = getService('policyTestResources'); + const unzipPromisify = promisify(unzip); + + const removeAllArtifacts = async () => { + for (const listId of ENDPOINT_ARTIFACT_LIST_IDS) { + await removeExceptionsList(listId); + } + }; + + const removeExceptionsList = async (listId: string) => { + await supertest + .delete(`${EXCEPTION_LIST_URL}?list_id=${listId}&namespace_type=agnostic`) + .set('kbn-xsrf', 'true'); + }; + + describe('For each artifact list under management', function () { + targetTags(this, ['@ess', '@serverless']); + + this.timeout(60_000 * 5); + let indexedData: IndexedHostsAndAlertsResponse; + let policyInfo: PolicyTestResourceInfo; + + before(async () => { + indexedData = await endpointTestResources.loadEndpointData(); + }); + after(async () => { + await endpointTestResources.unloadEndpointData(indexedData); + }); + + const checkFleetArtifacts = async ( + identifier: string, + expectedArtifact: ArtifactElasticsearchProperties, + expectedDecodedBodyArtifact: ArtifactBodyType, + policy?: PolicyTestResourceInfo + ) => { + // Check edited artifact is in the list with new values (wait for list to be updated) + let updatedArtifact: ArtifactElasticsearchProperties | undefined; + await retry.waitForWithTimeout('fleet artifact is updated', 120_000, async () => { + const artifacts = await endpointArtifactsTestResources.getArtifactsFromUnifiedManifestSO(); + + // This expects manifest artifact to come from unified so + const manifestArtifact = artifacts.find((artifact) => { + return ( + artifact.artifactIds.includes( + `${expectedArtifact.identifier}-${expectedArtifact.decoded_sha256}` + ) && artifact.policyId === policy?.packagePolicy.id + ); + }); + + if (!manifestArtifact) return false; + + // Get fleet artifact + const windowsArtifactResult = await esClient.get({ + index: '.fleet-artifacts-7', + id: `endpoint:${expectedArtifact.identifier}-${expectedArtifact.decoded_sha256}`, + }); + + const windowsArtifact = windowsArtifactResult._source as ArtifactElasticsearchProperties; + + // Get agent policy + const { + hits: { hits: policiesResults }, + } = await esClient.search({ + index: '.fleet-policies*', + query: { + bool: { + filter: [ + { + match: { + policy_id: policy?.agentPolicy.id, + }, + }, + ], + }, + }, + sort: [{ revision_idx: { order: 'desc' } }], + size: 1, + }); + + const agentPolicyResults = policiesResults[0] as AgentPolicyResponseType; + const policyArtifactManifest = agentPolicyResults._source.data.inputs[0] + ? agentPolicyResults._source.data.inputs[0].artifact_manifest + : undefined; + + let isUpdated: boolean = false; + if (policyArtifactManifest) { + // Compare artifacts from fleet artifacts and agent policy are the expecteds + isUpdated = + windowsArtifact.encoded_sha256 === expectedArtifact.encoded_sha256 && + policyArtifactManifest.artifacts[identifier].encoded_sha256 === + expectedArtifact.encoded_sha256; + } + + if (isUpdated) updatedArtifact = windowsArtifact; + return isUpdated; + }); + + updatedArtifact!.created = expectedArtifact.created; + const bodyFormBuffer = Buffer.from(updatedArtifact!.body, 'base64'); + const unzippedBody = await unzipPromisify(bodyFormBuffer); + + // Check decoded body first to detect possible body changes + expect(JSON.parse(unzippedBody.toString())).eql(expectedDecodedBodyArtifact); + expect(updatedArtifact).eql(expectedArtifact); + }; + + const performActions = async ( + actions: + | ArtifactActionsType['create']['formFields'] + | ArtifactActionsType['update']['formFields'], + suffix?: string + ) => { + for (const formAction of actions) { + if (formAction.type === 'customClick') { + await find.clickByCssSelector(formAction.selector, testSubjects.FIND_TIME); + } else if (formAction.type === 'click') { + await testSubjects.click(formAction.selector); + } else if (formAction.type === 'input') { + await testSubjects.setValue( + formAction.selector, + (formAction.value || '') + (suffix ? suffix : '') + ); + } else if (formAction.type === 'clear') { + await ( + await (await testSubjects.find(formAction.selector)).findByCssSelector('button') + ).click(); + } + } + }; + + const deleteArtifact = async (actions: ArtifactActionsType) => { + await pageObjects.artifactEntriesList.clickCardActionMenu(actions.pagePrefix); + await testSubjects.click(`${actions.pagePrefix}-card-cardDeleteAction`); + await testSubjects.click(`${actions.pagePrefix}-deleteModal-submitButton`); + await testSubjects.waitForDeleted(actions.delete.confirmSelector); + }; + + const createArtifact = async ( + actions: ArtifactActionsType | MultipleArtifactActionsType, + options?: { policyId?: string; suffix?: string; createButton?: string } + ) => { + // Opens add flyout + if (options?.createButton) { + await testSubjects.click(`${actions.pagePrefix}-${options.createButton}`); + } else { + await testSubjects.click(`${actions.pagePrefix}-emptyState-addButton`); + } + + await performActions(actions.create.formFields, options?.suffix); + + if (options?.policyId) { + await testSubjects.click(`${actions.pageObject}-form-effectedPolicies-perPolicy`); + await testSubjects.click(`policy-${options.policyId}-checkbox`); + } + + // Submit create artifact form + await testSubjects.click(`${actions.pagePrefix}-flyout-submitButton`); + }; + + const updateArtifact = async ( + actions: ArtifactActionsType, + options?: { policyId?: string; suffix?: string } + ) => { + // Opens edit flyout + await pageObjects.artifactEntriesList.clickCardActionMenu(actions.pagePrefix); + await testSubjects.click(`${actions.pagePrefix}-card-cardEditAction`); + + await performActions(actions.update.formFields); + + if (options?.policyId) { + await testSubjects.click(`${actions.pageObject}-form-effectedPolicies-perPolicy`); + await testSubjects.click(`policy-${options.policyId}-checkbox`); + } + + // Submit edit artifact form + await testSubjects.click(`${actions.pagePrefix}-flyout-submitButton`); + }; + + for (const testData of getArtifactsListTestsData()) { + describe(`When on the ${testData.title} entries list`, function () { + beforeEach(async () => { + policyInfo = await policyTestResources.createPolicy(); + await removeAllArtifacts(); + await browser.refresh(); + await pageObjects.artifactEntriesList.navigateToList(testData.urlPath); + }); + + afterEach(async () => { + await removeAllArtifacts(); + if (policyInfo) { + await policyInfo.cleanup(); + } + }); + + it(`should not show page title if there is no ${testData.title} entry`, async () => { + await testSubjects.missingOrFail('header-page-title'); + }); + + it(`should be able to add a new ${testData.title} entry`, async () => { + await createArtifact(testData, { policyId: policyInfo.packagePolicy.id }); + // Check new artifact is in the list + for (const checkResult of testData.create.checkResults) { + expect(await testSubjects.getVisibleText(checkResult.selector)).to.equal( + checkResult.value + ); + } + await toasts.dismiss(); + + // Title is shown after adding an item + expect(await testSubjects.getVisibleText('header-page-title')).to.equal(testData.title); + + // Checks if fleet artifact has been updated correctly + await checkFleetArtifacts( + testData.fleetArtifact.identifier, + testData.fleetArtifact.getExpectedUpdatedtArtifactWhenCreate(), + testData.fleetArtifact.getExpectedUpdatedArtifactBodyWhenCreate(), + policyInfo + ); + }); + + it(`should be able to update an existing ${testData.title} entry`, async () => { + await createArtifact(testData); + await updateArtifact(testData, { policyId: policyInfo.packagePolicy.id }); + + // Check edited artifact is in the list with new values (wait for list to be updated) + await retry.waitForWithTimeout('entry is updated in list', 20000, async () => { + const currentValue = await testSubjects.getVisibleText( + `${testData.pagePrefix}-card-criteriaConditions${ + testData.pagePrefix === 'EventFiltersListPage' ? '-condition' : '' + }` + ); + return currentValue === testData.update.waitForValue; + }); + + for (const checkResult of testData.update.checkResults) { + expect(await testSubjects.getVisibleText(checkResult.selector)).to.equal( + checkResult.value + ); + } + + await toasts.dismiss(); + + // Title still shown after editing an item + expect(await testSubjects.getVisibleText('header-page-title')).to.equal(testData.title); + + // Checks if fleet artifact has been updated correctly + await checkFleetArtifacts( + testData.fleetArtifact.identifier, + testData.fleetArtifact.getExpectedUpdatedArtifactWhenUpdate(), + testData.fleetArtifact.getExpectedUpdatedArtifactBodyWhenUpdate(), + policyInfo + ); + }); + + it(`should be able to delete the existing ${testData.title} entry`, async () => { + await createArtifact(testData); + await deleteArtifact(testData); + // We only expect one artifact to have been visible + await testSubjects.missingOrFail(testData.delete.card); + // Header has gone because there is no artifact + await testSubjects.missingOrFail('header-page-title'); + }); + }); + } + + describe('Should check artifacts are correctly generated when multiple entries', function () { + let firstPolicy: PolicyTestResourceInfo; + let secondPolicy: PolicyTestResourceInfo; + + const firstSuffix = 'first'; + const secondSuffix = 'second'; + const thirdSuffix = 'third'; + + beforeEach(async () => { + firstPolicy = await policyTestResources.createPolicy(); + secondPolicy = await policyTestResources.createPolicy(); + await removeAllArtifacts(); + await browser.refresh(); + await pageObjects.artifactEntriesList.navigateToList(testData.urlPath); + }); + + afterEach(async () => { + await removeAllArtifacts(); + if (firstPolicy) { + await firstPolicy.cleanup(); + } + if (secondPolicy) { + await secondPolicy.cleanup(); + } + }); + + const testData = getCreateMultipleData(); + it(`should get correct atifact when multiple entries are created`, async () => { + // Create first trusted app + await createArtifact(testData, { + policyId: firstPolicy.packagePolicy.id, + suffix: firstSuffix, + }); + await toasts.dismiss(); + + // Create second trusted app + await createArtifact(testData, { + policyId: secondPolicy.packagePolicy.id, + suffix: secondSuffix, + createButton: 'pageAddButton', + }); + await toasts.dismiss(); + + // Create third trusted app + await createArtifact(testData, { suffix: thirdSuffix, createButton: 'pageAddButton' }); + await toasts.dismiss(); + + // Checks if fleet artifact has been updated correctly + await checkFleetArtifacts( + testData.fleetArtifact.identifier, + testData.fleetArtifact.getExpectedUpdatedArtifactWhenCreateMultipleFirst(), + testData.fleetArtifact.getExpectedUpdatedArtifactBodyWhenCreateMultipleFirst( + thirdSuffix, + firstSuffix + ), + firstPolicy + ); + + // Checks if fleet artifact has been updated correctly + await checkFleetArtifacts( + testData.fleetArtifact.identifier, + testData.fleetArtifact.getExpectedUpdatedArtifactWhenCreateMultipleSecond(), + testData.fleetArtifact.getExpectedUpdatedArtifactBodyWhenCreateMultipleSecond( + thirdSuffix, + secondSuffix + ), + secondPolicy + ); + }); + }); + }); +}; diff --git a/x-pack/test/security_solution_endpoint/apps/integrations_feature_flag/endpoint_exceptions.ts b/x-pack/test/security_solution_endpoint/apps/integrations_feature_flag/endpoint_exceptions.ts new file mode 100644 index 0000000000000..ece54cecb47f1 --- /dev/null +++ b/x-pack/test/security_solution_endpoint/apps/integrations_feature_flag/endpoint_exceptions.ts @@ -0,0 +1,245 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import { unzip } from 'zlib'; +import { promisify } from 'util'; +import expect from '@kbn/expect'; +import { IndexedHostsAndAlertsResponse } from '@kbn/security-solution-plugin/common/endpoint/index_data'; +import { EXCEPTION_LIST_ITEM_URL } from '@kbn/securitysolution-list-constants'; +import { ArtifactElasticsearchProperties } from '@kbn/fleet-plugin/server/services'; +import { FoundExceptionListItemSchema } from '@kbn/securitysolution-io-ts-list-types'; +import { WebElementWrapper } from '@kbn/ftr-common-functional-ui-services'; +import { FtrProviderContext } from '../../ftr_provider_context'; +import { targetTags } from '../../target_tags'; + +export default ({ getPageObjects, getService }: FtrProviderContext) => { + const pageObjects = getPageObjects(['common', 'header']); + const queryBar = getService('queryBar'); + const testSubjects = getService('testSubjects'); + const endpointTestResources = getService('endpointTestResources'); + const endpointArtifactTestResources = getService('endpointArtifactTestResources'); + const retry = getService('retry'); + const esClient = getService('es'); + const supertest = getService('supertest'); + const find = getService('find'); + const unzipPromisify = promisify(unzip); + const comboBox = getService('comboBox'); + const toasts = getService('toasts'); + + describe('Endpoint Exceptions', function () { + targetTags(this, ['@ess', '@serverless']); + + this.timeout(10 * 60_000); + + const clearPrefilledEntries = async () => { + const entriesContainer = await testSubjects.find('exceptionEntriesContainer'); + + let deleteButtons: WebElementWrapper[]; + do { + deleteButtons = await testSubjects.findAllDescendant( + 'builderItemEntryDeleteButton', + entriesContainer + ); + + await deleteButtons[0].click(); + } while (deleteButtons.length > 1); + }; + + const openNewEndpointExceptionFlyout = async () => { + await testSubjects.click('timeline-context-menu-button'); + await testSubjects.click('add-endpoint-exception-menu-item'); + await testSubjects.existOrFail('addExceptionFlyout'); + + await retry.waitFor('entries should be loaded', () => + testSubjects.exists('exceptionItemEntryContainer') + ); + }; + + const setLastFieldsValue = async ({ + testSubj, + value, + }: { + testSubj: string; + value: string; + optionSelector?: string; + }) => { + const fields = await find.allByCssSelector(`[data-test-subj="${testSubj}"]`); + + const lastField = fields[fields.length - 1]; + await lastField.click(); + + await retry.try( + async () => { + await comboBox.setElement(lastField, value); + }, + async () => { + // If the above fails due to an option not existing, create the value custom instead + await comboBox.setFilterValue(lastField, value); + await pageObjects.common.pressEnterKey(); + } + ); + }; + + const setLastEntry = async ({ + field, + operator, + value, + }: { + field: string; + operator: 'matches' | 'is'; + value: string; + }) => { + await setLastFieldsValue({ testSubj: 'fieldAutocompleteComboBox', value: field }); + await setLastFieldsValue({ testSubj: 'operatorAutocompleteComboBox', value: operator }); + await setLastFieldsValue({ + testSubj: operator === 'matches' ? 'valuesAutocompleteWildcard' : 'valuesAutocompleteMatch', + value, + }); + }; + + const checkArtifact = (expectedArtifact: object) => { + return retry.tryForTime(120_000, async () => { + const artifacts = await endpointArtifactTestResources.getArtifactsFromUnifiedManifestSO(); + + const foundArtifactId = artifacts + .flatMap((artifact) => artifact.artifactIds) + .find((artifactId) => artifactId.startsWith('endpoint-exceptionlist-macos-v1')); + + expect(foundArtifactId).to.not.be(undefined); + + // Get fleet artifact + const artifactResult = await esClient.get({ + index: '.fleet-artifacts-7', + id: `endpoint:${foundArtifactId!}`, + }); + + const artifact = artifactResult._source as ArtifactElasticsearchProperties; + + const zippedBody = Buffer.from(artifact.body, 'base64'); + const artifactBody = await unzipPromisify(zippedBody); + + expect(JSON.parse(artifactBody.toString())).to.eql(expectedArtifact); + }); + }; + + let indexedData: IndexedHostsAndAlertsResponse; + before(async () => { + indexedData = await endpointTestResources.loadEndpointData(); + + const waitForAlertsToAppear = async () => { + await pageObjects.common.navigateToUrlWithBrowserHistory('security', `/alerts`); + await pageObjects.header.waitUntilLoadingHasFinished(); + await retry.waitForWithTimeout('alerts to appear', 10 * 60_000, async () => { + await queryBar.clickQuerySubmitButton(); + return testSubjects.exists('timeline-context-menu-button'); + }); + }; + + await waitForAlertsToAppear(); + }); + + after(async () => { + await endpointTestResources.unloadEndpointData(indexedData); + }); + + beforeEach(async () => { + const deleteEndpointExceptions = async () => { + const { body } = await supertest + .get(`${EXCEPTION_LIST_ITEM_URL}/_find?list_id=endpoint_list&namespace_type=agnostic`) + .set('kbn-xsrf', 'true'); + + for (const exceptionListItem of (body as FoundExceptionListItemSchema).data) { + await supertest + .delete(`${EXCEPTION_LIST_ITEM_URL}?id=${exceptionListItem.id}&namespace_type=agnostic`) + .set('kbn-xsrf', 'true'); + } + }; + + await deleteEndpointExceptions(); + }); + + it('should add `event.module=endpoint` to entry if only wildcard operator is present', async () => { + await pageObjects.common.navigateToUrlWithBrowserHistory('security', `/alerts`); + + await openNewEndpointExceptionFlyout(); + await clearPrefilledEntries(); + + await testSubjects.setValue('exceptionFlyoutNameInput', 'test exception'); + await setLastEntry({ field: 'file.path', operator: 'matches', value: '*/cheese/*' }); + await testSubjects.click('exceptionsAndButton'); + await setLastEntry({ field: 'process.executable', operator: 'matches', value: 'ex*' }); + + await testSubjects.click('addExceptionConfirmButton'); + await toasts.dismiss(); + + await checkArtifact({ + entries: [ + { + type: 'simple', + entries: [ + { + field: 'file.path', + operator: 'included', + type: 'wildcard_cased', + value: '*/cheese/*', + }, + { + field: 'process.executable', + operator: 'included', + type: 'wildcard_cased', + value: 'ex*', + }, + { + // this additional entry should be added + field: 'event.module', + operator: 'included', + type: 'exact_cased', + value: 'endpoint', + }, + ], + }, + ], + }); + }); + + it('should NOT add `event.module=endpoint` to entry if there is another operator', async () => { + await pageObjects.common.navigateToUrlWithBrowserHistory('security', `/alerts`); + + await openNewEndpointExceptionFlyout(); + await clearPrefilledEntries(); + + await testSubjects.setValue('exceptionFlyoutNameInput', 'test exception'); + await setLastEntry({ field: 'file.path', operator: 'matches', value: '*/cheese/*' }); + await testSubjects.click('exceptionsAndButton'); + await setLastEntry({ field: 'process.executable', operator: 'is', value: 'something' }); + + await testSubjects.click('addExceptionConfirmButton'); + await toasts.dismiss(); + + await checkArtifact({ + entries: [ + { + type: 'simple', + entries: [ + { + field: 'file.path', + operator: 'included', + type: 'wildcard_cased', + value: '*/cheese/*', + }, + { + field: 'process.executable', + operator: 'included', + type: 'exact_cased', + value: 'something', + }, + ], + }, + ], + }); + }); + }); +}; diff --git a/x-pack/test/security_solution_endpoint/apps/integrations_feature_flag/index.ts b/x-pack/test/security_solution_endpoint/apps/integrations_feature_flag/index.ts new file mode 100644 index 0000000000000..5464cf07f02e3 --- /dev/null +++ b/x-pack/test/security_solution_endpoint/apps/integrations_feature_flag/index.ts @@ -0,0 +1,48 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +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, + isRegistryEnabled, +} from '../../../security_solution_endpoint_api_int/registry'; + +export default function (providerContext: FtrProviderContext) { + 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'); + } + + const registryUrl = getRegistryUrlFromTestEnv() ?? getRegistryUrlFromIngest(); + log.info(`Package registry URL for tests: ${registryUrl}`); + + before(async () => { + log.info('calling Fleet setup'); + await ingestManager.setup(); + + 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('./artifact_entries_list')); + loadTestFile(require.resolve('./endpoint_exceptions')); + }); +} diff --git a/x-pack/test/security_solution_endpoint/apps/integrations_feature_flag/mocks.ts b/x-pack/test/security_solution_endpoint/apps/integrations_feature_flag/mocks.ts new file mode 100644 index 0000000000000..47523694b4349 --- /dev/null +++ b/x-pack/test/security_solution_endpoint/apps/integrations_feature_flag/mocks.ts @@ -0,0 +1,807 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FullAgentPolicy } from '@kbn/fleet-plugin/common/types'; +import { ArtifactElasticsearchProperties } from '@kbn/fleet-plugin/server/services/artifacts/types'; +import { InternalUnifiedManifestBaseSchema } from '@kbn/security-solution-plugin/server/endpoint/schemas/artifacts'; +import { TranslatedExceptionListItem } from '@kbn/security-solution-plugin/server/endpoint/schemas/artifacts/lists'; + +export interface AgentPolicyResponseType { + _index: string; + _id: string; + _score: number; + _source: { data: FullAgentPolicy }; +} + +export interface InternalUnifiedManifestSchemaResponseType { + _index: string; + _id: string; + _score: number; + _source: { + 'endpoint:unified-user-artifact-manifest': InternalUnifiedManifestBaseSchema; + }; +} + +export interface ArtifactBodyType { + entries: TranslatedExceptionListItem[]; +} + +export type ArtifactActionsType = ReturnType[0]; +export type MultipleArtifactActionsType = ReturnType; + +export const getArtifactsListTestsData = () => [ + { + title: 'Trusted applications', + pagePrefix: 'trustedAppsListPage', + create: { + formFields: [ + { + type: 'input', + selector: 'trustedApps-form-descriptionField', + value: 'This is the trusted application description', + }, + { + type: 'input', + selector: 'trustedApps-form-nameTextField', + value: 'Trusted application name', + }, + { + type: 'click', + selector: 'trustedApps-form-conditionsBuilder-group1-entry0-field', + }, + { + type: 'click', + selector: 'trustedApps-form-conditionsBuilder-group1-entry0-field-type-Hash', + }, + { + type: 'input', + selector: 'trustedApps-form-conditionsBuilder-group1-entry0-value', + value: 'A4370C0CF81686C0B696FA6261c9d3e0d810ae704ab8301839dffd5d5112f476', + }, + ], + checkResults: [ + { + selector: 'trustedAppsListPage-card-criteriaConditions', + value: + 'OSIS Windows\nAND process.hash.*IS a4370c0cf81686c0b696fa6261c9d3e0d810ae704ab8301839dffd5d5112f476', + }, + ], + }, + update: { + formFields: [ + { + type: 'input', + selector: 'trustedApps-form-descriptionField', + value: 'This is the trusted application description edited', + }, + { + type: 'input', + selector: 'trustedApps-form-nameTextField', + value: 'Trusted application name edited', + }, + { + type: 'click', + selector: 'trustedApps-form-conditionsBuilder-group1-entry0-field', + }, + { + type: 'click', + selector: 'trustedApps-form-conditionsBuilder-group1-entry0-field-type-Path', + }, + { + type: 'input', + selector: 'trustedApps-form-conditionsBuilder-group1-entry0-value', + value: 'c:\\randomFolder\\randomFile.exe, c:\\randomFolder\\randomFile2.exe', + }, + ], + checkResults: [ + { + selector: 'trustedAppsListPage-card-criteriaConditions', + value: + 'OSIS Windows\nAND process.executable.caselessIS c:\\randomFolder\\randomFile.exe, c:\\randomFolder\\randomFile2.exe', + }, + { + selector: 'trustedAppsListPage-card-header-title', + value: 'Trusted application name edited', + }, + { + selector: 'trustedAppsListPage-card-description', + value: 'This is the trusted application description edited', + }, + ], + waitForValue: + 'OSIS Windows\nAND process.executable.caselessIS c:\\randomFolder\\randomFile.exe, c:\\randomFolder\\randomFile2.exe', + }, + delete: { + confirmSelector: 'trustedAppsListPage-deleteModal-submitButton', + card: 'trustedAppsListPage-card', + }, + urlPath: 'trusted_apps', + pageObject: 'trustedApps', + fleetArtifact: { + identifier: 'endpoint-trustlist-windows-v1', + type: 'trustedApplications', + getExpectedUpdatedtArtifactWhenCreate: (): ArtifactElasticsearchProperties => ({ + type: 'trustlist', + identifier: 'endpoint-trustlist-windows-v1', + body: 'eJxVzNEKgyAUgOF3OdcxNMvMVxkxTp4jCa5EbWxE7z422MVuvx/+A3itOXABez2gvhKDhRLuKTI0f80HjgQWUt4cl3JZsCyXsmDba2hgS5yxbhkshNXFnZig+f34ia7eHJYvPjDuH8VODcIJ543URjsx61F71K2WbiTFgowUyIPocDZKSKNG8p566qVsfTdoOKdzOt89hz0Q', + package_name: 'endpoint', + created: '2000-01-01T00:00:00.000Z', + relative_url: + '/api/fleet/artifacts/endpoint-trustlist-windows-v1/016bec11c5b1d6f8609fd3525202aa12baf0132484abf368d5011100d5ec1ec4', + compression_algorithm: 'zlib', + decoded_size: 193, + decoded_sha256: '016bec11c5b1d6f8609fd3525202aa12baf0132484abf368d5011100d5ec1ec4', + encryption_algorithm: 'none', + encoded_sha256: '814aabc04d674ccdeb7c1acfe74120cb52ad1392d6924a7d813e08f8b6cd0f0f', + encoded_size: 153, + }), + getExpectedUpdatedArtifactBodyWhenCreate: (): ArtifactBodyType => ({ + entries: [ + { + type: 'simple', + entries: [ + { + field: 'process.hash.sha256', + operator: 'included', + type: 'exact_cased', + value: 'a4370c0cf81686c0b696fa6261c9d3e0d810ae704ab8301839dffd5d5112f476', + }, + ], + }, + ], + }), + getExpectedUpdatedArtifactWhenUpdate: (): ArtifactElasticsearchProperties => ({ + type: 'trustlist', + identifier: 'endpoint-trustlist-windows-v1', + body: 'eJx9jEEKwjAUBa8ibx1cuMwBvIQtEpMnBH6TkJ9KpeTuEkHBjcthhtnB1Gqkwl52tGchLDQuRQjz4+6REmBRavZUPXKjX5u7vcNcWF3LFRYxeVkDA8xnx835dvVOKVSFwcPJOoS301RdCnk5ZwmsX4rC8TeHf8VpJOhzn/sLJpZG8A==', + package_name: 'endpoint', + created: '2000-01-01T00:00:00.000Z', + relative_url: + '/api/fleet/artifacts/endpoint-trustlist-windows-v1/ac2bf74a73885f9a5a1700c328bf1a5a8f6cb72f2465a575335ea99dac0d4c10', + compression_algorithm: 'zlib', + decoded_size: 198, + decoded_sha256: 'ac2bf74a73885f9a5a1700c328bf1a5a8f6cb72f2465a575335ea99dac0d4c10', + encryption_algorithm: 'none', + encoded_sha256: '28d81b2787cea23fcb88d02b1c09940858963a62c60cdfd7a2b7564cfc251708', + encoded_size: 130, + }), + getExpectedUpdatedArtifactBodyWhenUpdate: (): ArtifactBodyType => ({ + entries: [ + { + type: 'simple', + entries: [ + { + field: 'process.executable', + operator: 'included', + type: 'exact_caseless', + value: 'c:\\randomFolder\\randomFile.exe, c:\\randomFolder\\randomFile2.exe', + }, + ], + }, + ], + }), + }, + }, + { + title: 'Event Filters', + pagePrefix: 'EventFiltersListPage', + create: { + formFields: [ + { + type: 'input', + selector: 'eventFilters-form-name-input', + value: 'Event filter name', + }, + { + type: 'input', + selector: 'eventFilters-form-description-input', + value: 'This is the event filter description', + }, + { + type: 'click', + selector: 'fieldAutocompleteComboBox', + }, + { + type: 'customClick', + selector: 'button[title="agent.ephemeral_id"]', + }, + { + type: 'click', + selector: 'valuesAutocompleteMatch', + }, + { + type: 'input', + selector: 'valuesAutocompleteMatch', + value: 'endpoint', + }, + ], + checkResults: [ + { + selector: 'EventFiltersListPage-card-criteriaConditions-condition', + value: 'AND agent.ephemeral_idIS endpoint', + }, + ], + }, + update: { + formFields: [ + { + type: 'input', + selector: 'eventFilters-form-name-input', + value: 'Event filter name edited', + }, + { + type: 'input', + selector: 'eventFilters-form-description-input', + value: 'This is the event filter description edited', + }, + { + type: 'click', + selector: 'fieldAutocompleteComboBox', + }, + { + type: 'input', + selector: 'fieldAutocompleteComboBox', + value: 'agent.id', + }, + { + type: 'customClick', + selector: 'button[title="agent.id"]', + }, + { + type: 'input', + selector: 'valuesAutocompleteMatch', + value: 'test super large value', + }, + { + type: 'click', + selector: 'eventFilters-form-description-input', + }, + ], + checkResults: [ + { + selector: 'EventFiltersListPage-card-criteriaConditions-condition', + value: 'AND agent.idIS test super large value', + }, + { + selector: 'EventFiltersListPage-card-header-title', + value: 'Event filter name edited', + }, + { + selector: 'EventFiltersListPage-card-description', + value: 'This is the event filter description edited', + }, + ], + waitForValue: 'AND agent.idIS test super large value', + }, + delete: { + confirmSelector: 'EventFiltersListPage-deleteModal-submitButton', + card: 'EventFiltersListPage-card', + }, + urlPath: 'event_filters', + pageObject: 'eventFilters', + fleetArtifact: { + identifier: 'endpoint-eventfilterlist-windows-v1', + type: 'eventfilterlist', + getExpectedUpdatedtArtifactWhenCreate: (): ArtifactElasticsearchProperties => ({ + type: 'eventfilterlist', + identifier: 'endpoint-eventfilterlist-windows-v1', + body: 'eJxVzFEKwjAQRdG9vO/iArKVUsqQPHVgmoRkWpSSvYvFH3/PhXuC2ZuyI8wn/F2JgK5bNWL6a3elJQTIg9lvrE9ubGKrJkwolU28NARojrYnfvW340uir1H6hYfYfmlOtWh2jGUs4wOrCC+X', + package_name: 'endpoint', + created: '2000-01-01T00:00:00.000Z', + relative_url: + '/api/fleet/artifacts/endpoint-eventfilterlist-windows-v1/b3373c93ffc795d954f22c625c084dc5874a156ec0cb3d4af1c3dab0b965fa30', + compression_algorithm: 'zlib', + decoded_size: 136, + decoded_sha256: 'b3373c93ffc795d954f22c625c084dc5874a156ec0cb3d4af1c3dab0b965fa30', + encryption_algorithm: 'none', + encoded_sha256: 'cc9bc4e3cc2c2767c3f56b17ebf4901dbe7e82f15720d48c745370e028c5e887', + encoded_size: 108, + }), + getExpectedUpdatedArtifactBodyWhenCreate: (): ArtifactBodyType => ({ + entries: [ + { + type: 'simple', + entries: [ + { + field: 'agent.ephemeral_id', + operator: 'included', + type: 'exact_cased', + value: 'endpoint', + }, + ], + }, + ], + }), + getExpectedUpdatedArtifactWhenUpdate: (): ArtifactElasticsearchProperties => ({ + type: 'eventfilterlist', + identifier: 'endpoint-eventfilterlist-windows-v1', + body: 'eJxVzEEKwyAURdGtyBuHLsCtlFA++hoEa+T7LQnBvZc0nXR6LtwDLKaJDf5+wPZKeLT0qpmY/tozMUd4yMJitxQxYa1UsVXhkUrIPfLU34SbBHsEaV98S+6nGpu51ivVZdGF7gpjHvP4ADqUMJs=', + package_name: 'endpoint', + created: '2000-01-01T00:00:00.000Z', + relative_url: + '/api/fleet/artifacts/endpoint-eventfilterlist-windows-v1/e4f00c88380d2c429eeb2741ad19383b94d76f79744b098b095befc24003e158', + compression_algorithm: 'zlib', + decoded_size: 140, + decoded_sha256: 'e4f00c88380d2c429eeb2741ad19383b94d76f79744b098b095befc24003e158', + encryption_algorithm: 'none', + encoded_sha256: 'e371e2a28b59bd942ca7ef9665dae7c9b27409ad6f2ca3bff6357a98deb23c12', + encoded_size: 110, + }), + getExpectedUpdatedArtifactBodyWhenUpdate: (): ArtifactBodyType => ({ + entries: [ + { + type: 'simple', + entries: [ + { + field: 'agent.id', + operator: 'included', + type: 'exact_cased', + value: 'test super large value', + }, + ], + }, + ], + }), + }, + }, + { + title: 'Blocklist', + pagePrefix: 'blocklistPage', + create: { + formFields: [ + { + type: 'input', + selector: 'blocklist-form-name-input', + value: 'Blocklist name', + }, + { + type: 'input', + selector: 'blocklist-form-description-input', + value: 'This is the blocklist description', + }, + { + type: 'click', + selector: 'blocklist-form-field-select', + }, + { + type: 'click', + selector: 'blocklist-form-file.hash.*', + }, + { + type: 'input', + selector: 'blocklist-form-values-input', + value: + 'A4370C0CF81686C0B696FA6261c9d3e0d810ae704ab8301839dffd5d5112f476,aedb279e378BED6C2DB3C9DC9e12ba635e0b391c,741462ab431a22233C787BAAB9B653C7', + }, + { + type: 'click', + selector: 'blocklist-form-name-input', + }, + ], + checkResults: [ + { + selector: 'blocklistPage-card-criteriaConditions', + value: + 'OSIS Windows\nAND file.hash.*IS ONE OF\n741462ab431a22233c787baab9b653c7\naedb279e378bed6c2db3c9dc9e12ba635e0b391c\na4370c0cf81686c0b696fa6261c9d3e0d810ae704ab8301839dffd5d5112f476', + }, + ], + }, + update: { + formFields: [ + { + type: 'input', + selector: 'blocklist-form-name-input', + value: 'Blocklist name edited', + }, + { + type: 'input', + selector: 'blocklist-form-description-input', + value: 'This is the blocklist description edited', + }, + { + type: 'click', + selector: 'blocklist-form-field-select', + }, + { + type: 'click', + selector: 'blocklist-form-file.path.caseless', + }, + { + type: 'clear', + selector: + 'blocklist-form-values-input-a4370c0cf81686c0b696fa6261c9d3e0d810ae704ab8301839dffd5d5112f476', + }, + { + type: 'clear', + selector: 'blocklist-form-values-input-741462ab431a22233c787baab9b653c7', + }, + { + type: 'clear', + selector: 'blocklist-form-values-input-aedb279e378bed6c2db3c9dc9e12ba635e0b391c', + }, + { + type: 'input', + selector: 'blocklist-form-values-input', + value: 'c:\\randomFolder\\randomFile.exe, c:\\randomFolder\\randomFile2.exe', + }, + { + type: 'click', + selector: 'blocklist-form-name-input', + }, + ], + checkResults: [ + { + selector: 'blocklistPage-card-criteriaConditions', + value: + 'OSIS Windows\nAND file.path.caselessIS ONE OF\nc:\\randomFolder\\randomFile.exe\nc:\\randomFolder\\randomFile2.exe', + }, + { + selector: 'blocklistPage-card-header-title', + value: 'Blocklist name edited', + }, + { + selector: 'blocklistPage-card-description', + value: 'This is the blocklist description edited', + }, + ], + waitForValue: + 'OSIS Windows\nAND file.path.caselessIS ONE OF\nc:\\randomFolder\\randomFile.exe\nc:\\randomFolder\\randomFile2.exe', + }, + delete: { + confirmSelector: 'blocklistDeletionConfirm', + card: 'blocklistCard', + }, + pageObject: 'blocklist', + urlPath: 'blocklist', + fleetArtifact: { + identifier: 'endpoint-blocklist-windows-v1', + type: 'blocklist', + getExpectedUpdatedtArtifactWhenCreate: (): ArtifactElasticsearchProperties => ({ + type: 'blocklist', + identifier: 'endpoint-blocklist-windows-v1', + relative_url: + '/api/fleet/artifacts/endpoint-blocklist-windows-v1/637f1e8795406904980ae2ab4a69cea967756571507f6bd7fc94cde0add20df2', + body: 'eJylzk1qw0AMQOG7aG3C/GpmfJVggkbSYIPjmNgpDcF3LxS66LLN+sHje4Eu+33SDfrzC/bnqtDDNl3XWaH71dqks0APbZr1NNI2nq4SoYPbqnfab3foYVp4fogKdD8n/STeL0ybyoWWJ3TwQfNDoT9DCjagoxq8Jeec95xyqkS1VIyeEwzHcHR/NW0j2TdQpFJdKupTrirITqrnIlzUukroo5rqi+V/41zEd3jBJ8OGW7aYkU3Fgo3QoeUiXo1ka0iTCVSzNzb7Iq1JlGitayHhN3s4vgDTjqDt', + encryption_algorithm: 'none', + package_name: 'endpoint', + encoded_size: 219, + encoded_sha256: 'e803c1ee6aec0885092bfd6c288839f42b31107dd6d0bb2c8e2d2b9f8fc8b293', + decoded_size: 501, + decoded_sha256: '637f1e8795406904980ae2ab4a69cea967756571507f6bd7fc94cde0add20df2', + compression_algorithm: 'zlib', + created: '2000-01-01T00:00:00.000Z', + }), + getExpectedUpdatedArtifactBodyWhenCreate: (): ArtifactBodyType => ({ + entries: [ + { + type: 'simple', + entries: [ + { + field: 'file.hash.md5', + operator: 'included', + type: 'exact_cased_any', + value: ['741462ab431a22233c787baab9b653c7'], + }, + ], + }, + { + type: 'simple', + entries: [ + { + field: 'file.hash.sha1', + operator: 'included', + type: 'exact_cased_any', + value: ['aedb279e378bed6c2db3c9dc9e12ba635e0b391c'], + }, + ], + }, + { + type: 'simple', + entries: [ + { + field: 'file.hash.sha256', + operator: 'included', + type: 'exact_cased_any', + value: ['a4370c0cf81686c0b696fa6261c9d3e0d810ae704ab8301839dffd5d5112f476'], + }, + ], + }, + ], + }), + getExpectedUpdatedArtifactWhenUpdate: (): ArtifactElasticsearchProperties => ({ + type: 'blocklist', + identifier: 'endpoint-blocklist-windows-v1', + relative_url: + '/api/fleet/artifacts/endpoint-blocklist-windows-v1/3ead6ce4e34cb4411083a44bfe813d9442d296981ee8d56e727e6cff14dea0f0', + body: 'eJx9jUEKwjAURK8isw4uXOYAXqKV8kmmGPhNQpJKS/HuEkHBjcxqmMebA4ytBFbY4UDbM2FRw5KVMD/bHKgeFnNQnrO0OwxSZpGWCixCdLp6epiPhZu4NjmpVNY6Sdxh8BBdCTvA2XEsEn1arkk9y7d1Pbf+fvrHXN7Q7dnzAojqRb8=', + encryption_algorithm: 'none', + package_name: 'endpoint', + encoded_size: 131, + encoded_sha256: 'f0e2dc2aa8d968b704baa11bf3100db91a85991d5de431f8c389b7417335a701', + decoded_size: 197, + decoded_sha256: '3ead6ce4e34cb4411083a44bfe813d9442d296981ee8d56e727e6cff14dea0f0', + compression_algorithm: 'zlib', + created: '2000-01-01T00:00:00.000Z', + }), + getExpectedUpdatedArtifactBodyWhenUpdate: (): ArtifactBodyType => ({ + entries: [ + { + type: 'simple', + entries: [ + { + field: 'file.path', + operator: 'included', + type: 'exact_caseless_any', + value: ['c:\\randomFolder\\randomFile.exe', ' c:\\randomFolder\\randomFile2.exe'], + }, + ], + }, + ], + }), + }, + }, + { + title: 'Host isolation exceptions', + pagePrefix: 'hostIsolationExceptionsListPage', + create: { + formFields: [ + { + type: 'input', + selector: 'hostIsolationExceptions-form-name-input', + value: 'Host Isolation exception name', + }, + { + type: 'input', + selector: 'hostIsolationExceptions-form-description-input', + value: 'This is the host isolation exception description', + }, + { + type: 'input', + selector: 'hostIsolationExceptions-form-ip-input', + value: '1.1.1.1', + }, + ], + checkResults: [ + { + selector: 'hostIsolationExceptionsListPage-card-criteriaConditions', + value: 'OSIS Windows, Linux, Mac\nAND destination.ipIS 1.1.1.1', + }, + ], + }, + update: { + formFields: [ + { + type: 'input', + selector: 'hostIsolationExceptions-form-name-input', + value: 'Host Isolation exception name edited', + }, + { + type: 'input', + selector: 'hostIsolationExceptions-form-description-input', + value: 'This is the host isolation exception description edited', + }, + { + type: 'input', + selector: 'hostIsolationExceptions-form-ip-input', + value: '2.2.2.2/24', + }, + ], + checkResults: [ + { + selector: 'hostIsolationExceptionsListPage-card-criteriaConditions', + value: 'OSIS Windows, Linux, Mac\nAND destination.ipIS 2.2.2.2/24', + }, + { + selector: 'hostIsolationExceptionsListPage-card-header-title', + value: 'Host Isolation exception name edited', + }, + { + selector: 'hostIsolationExceptionsListPage-card-description', + value: 'This is the host isolation exception description edited', + }, + ], + waitForValue: 'OSIS Windows, Linux, Mac\nAND destination.ipIS 2.2.2.2/24', + }, + delete: { + confirmSelector: 'hostIsolationExceptionsDeletionConfirm', + card: 'hostIsolationExceptionsCard', + }, + pageObject: 'hostIsolationExceptions', + urlPath: 'host_isolation_exceptions', + fleetArtifact: { + identifier: 'endpoint-hostisolationexceptionlist-windows-v1', + type: 'hostisolationexceptionlist', + getExpectedUpdatedtArtifactWhenCreate: (): ArtifactElasticsearchProperties => ({ + type: 'hostisolationexceptionlist', + identifier: 'endpoint-hostisolationexceptionlist-windows-v1', + relative_url: + '/api/fleet/artifacts/endpoint-hostisolationexceptionlist-windows-v1/2c3ee2b5e7f86f8c336a3df7e59a1151b11d7eec382442032e69712d6a6459e0', + body: 'eJxVjEEKgzAUBe/y1kFwm6uIyCd5hQ9pEpKvWCR3LxVclNnNwFxgtqbs8MsF+1TCo+u7JsL9tZcyRXhEdtMspiVPWuFQKptYafDQHNIeGeGeFU8JtgXptzwk7T87TzcY61jHF647LBE=', + encryption_algorithm: 'none', + package_name: 'endpoint', + encoded_size: 104, + encoded_sha256: 'f958ada742a0be63d136901317c6bfd04b2ab5f52cdd0e872461089b0009bb3e', + decoded_size: 131, + decoded_sha256: '2c3ee2b5e7f86f8c336a3df7e59a1151b11d7eec382442032e69712d6a6459e0', + compression_algorithm: 'zlib', + created: '2000-01-01T00:00:00.000Z', + }), + getExpectedUpdatedArtifactBodyWhenCreate: (): ArtifactBodyType => ({ + entries: [ + { + type: 'simple', + entries: [ + { + field: 'destination.ip', + operator: 'included', + type: 'exact_cased', + value: '1.1.1.1', + }, + ], + }, + ], + }), + getExpectedUpdatedArtifactWhenUpdate: (): ArtifactElasticsearchProperties => ({ + type: 'hostisolationexceptionlist', + identifier: 'endpoint-hostisolationexceptionlist-windows-v1', + relative_url: + '/api/fleet/artifacts/endpoint-hostisolationexceptionlist-windows-v1/4b62473b4cf057277b3297896771cc1061c3bea2c4f7ec1ef5c2546f33d5d9e8', + body: 'eJxVjEEKwyAUBe/y1pJC6MqrlBA++gofrIr+hJbg3UsCXZTZzcAcYLam7PCPA/aphEfXV02E+2tPZYrwiOymWUxLnrTCoVQ2sdLgoTmkLTLC/VZ8S7A1SL/kLmk77Txd3OY7xjKW8QUwWyyq', + encryption_algorithm: 'none', + package_name: 'endpoint', + encoded_size: 108, + encoded_sha256: '84df618343078f43a54299bcebef03010f3ec4ffdf7160448882fee9bafa1adb', + decoded_size: 134, + decoded_sha256: '4b62473b4cf057277b3297896771cc1061c3bea2c4f7ec1ef5c2546f33d5d9e8', + compression_algorithm: 'zlib', + created: '2000-01-01T00:00:00.000Z', + }), + getExpectedUpdatedArtifactBodyWhenUpdate: (): ArtifactBodyType => ({ + entries: [ + { + type: 'simple', + entries: [ + { + field: 'destination.ip', + operator: 'included', + type: 'exact_cased', + value: '2.2.2.2/24', + }, + ], + }, + ], + }), + }, + }, +]; + +export const getCreateMultipleData = () => ({ + title: 'Trusted applications', + pagePrefix: 'trustedAppsListPage', + create: { + formFields: [ + { + type: 'input', + selector: 'trustedApps-form-descriptionField', + value: 'This is the trusted application description', + }, + { + type: 'input', + selector: 'trustedApps-form-nameTextField', + value: 'Trusted application name', + }, + { + type: 'click', + selector: 'trustedApps-form-conditionsBuilder-group1-entry0-field', + }, + { + type: 'click', + selector: 'trustedApps-form-conditionsBuilder-group1-entry0-field-type-Path', + }, + { + type: 'input', + selector: 'trustedApps-form-conditionsBuilder-group1-entry0-value', + value: 'c:\\randomFolder\\randomFile.exe', + }, + ], + }, + + urlPath: 'trusted_apps', + pageObject: 'trustedApps', + fleetArtifact: { + identifier: 'endpoint-trustlist-windows-v1', + type: 'trustedApplications', + getExpectedUpdatedArtifactWhenCreateMultipleFirst: (): ArtifactElasticsearchProperties => ({ + type: 'trustlist', + identifier: 'endpoint-trustlist-windows-v1', + body: 'eJzNjlEKwjAQBe+y38ED5ABewhaJySsubJuwu5VK6d0lgoI38PMxj2F2wuLKMIqXnfzZQJGM5yag8MMmhhSK1LRmmJ2wIa+ebu9jbdDkVSkSL1nWgkLho8OWsl9zMgjMKNAjydpBjsOgaSl1Plcp0O9iQff7nbXQMR7h79ImVvOeNh4vUR5zdA==', + package_name: 'endpoint', + created: '2000-01-01T00:00:00.000Z', + relative_url: + '/api/fleet/artifacts/endpoint-trustlist-windows-v1/329fc9176a24d64f4376d2c25d5db5b31cf86b288dac83c8a004dfe5bbfdc7d0', + compression_algorithm: 'zlib', + decoded_size: 323, + decoded_sha256: '329fc9176a24d64f4376d2c25d5db5b31cf86b288dac83c8a004dfe5bbfdc7d0', + encryption_algorithm: 'none', + encoded_sha256: '4d9eecb830948eabd721563fd2473900207d043126e66eac2ef78f9e05a80adb', + encoded_size: 136, + }), + getExpectedUpdatedArtifactBodyWhenCreateMultipleFirst: ( + firstSuffix: string, + secondSuffix: string + ): ArtifactBodyType => ({ + entries: [ + { + type: 'simple', + entries: [ + { + field: 'process.executable', + operator: 'included', + type: 'exact_caseless', + value: `c:\\randomFolder\\randomFile.exe${firstSuffix}`, + }, + ], + }, + { + entries: [ + { + field: 'process.executable', + operator: 'included', + type: 'exact_caseless', + value: `c:\\randomFolder\\randomFile.exe${secondSuffix}`, + }, + ], + type: 'simple', + }, + ], + }), + getExpectedUpdatedArtifactWhenCreateMultipleSecond: (): ArtifactElasticsearchProperties => ({ + type: 'trustlist', + identifier: 'endpoint-trustlist-windows-v1', + body: 'eJzNjlEKwjAQRO8y38ED5ABewhaJyYiBbRJ2U6mU3l1aUPAGfg5veLwVLF0zDf6yor8a4WF5akK4H3bPlASPpjXS7MSFce7hdhxro4ZeFR65RJkTE9xHxyXEfo3BKDSDwzPIvIPoh0FDSXU6V0nU78rC3d8fWRO2cXN/l2aMtRxt4/YGxIFzyA==', + package_name: 'endpoint', + created: '2000-01-01T00:00:00.000Z', + relative_url: + '/api/fleet/artifacts/endpoint-trustlist-windows-v1/3be2ce848f9b49d6531e6dc80f43579e00adbc640d3f785c14c8f9fa2652500a', + compression_algorithm: 'zlib', + decoded_size: 324, + decoded_sha256: '3be2ce848f9b49d6531e6dc80f43579e00adbc640d3f785c14c8f9fa2652500a', + encryption_algorithm: 'none', + encoded_sha256: '68304c35bbe863d0fbb15cf7e5ae5c84bad17aa7a3bc26828f9f0b20e0df6ed8', + encoded_size: 136, + }), + getExpectedUpdatedArtifactBodyWhenCreateMultipleSecond: ( + firstSuffix: string, + secondSuffix: string + ): ArtifactBodyType => ({ + entries: [ + { + type: 'simple', + entries: [ + { + field: 'process.executable', + operator: 'included', + type: 'exact_caseless', + value: `c:\\randomFolder\\randomFile.exe${firstSuffix}`, + }, + ], + }, + { + entries: [ + { + field: 'process.executable', + operator: 'included', + type: 'exact_caseless', + value: `c:\\randomFolder\\randomFile.exe${secondSuffix}`, + }, + ], + type: 'simple', + }, + ], + }), + }, +}); diff --git a/x-pack/test/security_solution_endpoint/integrations_feature_flag.config.ts b/x-pack/test/security_solution_endpoint/integrations_feature_flag.config.ts new file mode 100644 index 0000000000000..275f984307bff --- /dev/null +++ b/x-pack/test/security_solution_endpoint/integrations_feature_flag.config.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 { resolve } from 'path'; +import { FtrConfigProviderContext } from '@kbn/test'; +import { generateConfig } from './config.base'; +import { services } from './services'; + +export default async function (ftrConfigProviderContext: FtrConfigProviderContext) { + const { readConfigFile } = ftrConfigProviderContext; + + const xpackFunctionalConfig = await readConfigFile( + require.resolve('../functional/config.base.js') + ); + + return generateConfig({ + ftrConfigProviderContext, + baseConfig: xpackFunctionalConfig, + testFiles: [resolve(__dirname, './apps/integrations_feature_flag')], + junitReportName: + 'X-Pack Endpoint Integrations With Feature Flags turned on 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', + `--xpack.securitySolution.enableExperimental=${JSON.stringify(['unifiedManifestEnabled'])}`, + ], + services, + }); +} diff --git a/x-pack/test/security_solution_endpoint/serverless.integrations_feature_flag.config.ts b/x-pack/test/security_solution_endpoint/serverless.integrations_feature_flag.config.ts new file mode 100644 index 0000000000000..7ac35bbe3a101 --- /dev/null +++ b/x-pack/test/security_solution_endpoint/serverless.integrations_feature_flag.config.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 { 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_feature_flag')], + junitReportName: + 'X-Pack Endpoint Integrations With Feature Flags turned on Functional Tests on ESS', + 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', + `--xpack.securitySolution.enableExperimental=${JSON.stringify(['unifiedManifestEnabled'])}`, + ], + services: svlServices, + }); +} diff --git a/x-pack/test/security_solution_endpoint/services/endpoint_artifacts.ts b/x-pack/test/security_solution_endpoint/services/endpoint_artifacts.ts index a8fcbf3f982fa..0a914226c9280 100644 --- a/x-pack/test/security_solution_endpoint/services/endpoint_artifacts.ts +++ b/x-pack/test/security_solution_endpoint/services/endpoint_artifacts.ts @@ -6,9 +6,9 @@ */ import type { - ExceptionListItemSchema, - CreateExceptionListSchema, CreateExceptionListItemSchema, + CreateExceptionListSchema, + ExceptionListItemSchema, } from '@kbn/securitysolution-io-ts-list-types'; import { EXCEPTION_LIST_ITEM_URL, EXCEPTION_LIST_URL } from '@kbn/securitysolution-list-constants'; import { Response } from 'superagent'; @@ -19,8 +19,10 @@ import { EVENT_FILTER_LIST_DEFINITION } from '@kbn/security-solution-plugin/publ import { HOST_ISOLATION_EXCEPTIONS_LIST_DEFINITION } from '@kbn/security-solution-plugin/public/management/pages/host_isolation_exceptions/constants'; import { BLOCKLISTS_LIST_DEFINITION } from '@kbn/security-solution-plugin/public/management/pages/blocklist/constants'; import { ManifestConstants } from '@kbn/security-solution-plugin/server/endpoint/lib/artifacts'; + import { FtrService } from '../../functional/ftr_provider_context'; import { InternalManifestSchemaResponseType } from '../apps/integrations/mocks'; +import { InternalUnifiedManifestSchemaResponseType } from '../apps/integrations_feature_flag/mocks'; export interface ArtifactTestData { artifact: ExceptionListItemSchema; @@ -132,8 +134,25 @@ export class EndpointArtifactsTestResources extends FtrService { }); const manifestResult = manifestResults[0] as InternalManifestSchemaResponseType; - const artifacts = manifestResult._source['endpoint:user-artifact-manifest'].artifacts; + return manifestResult._source['endpoint:user-artifact-manifest'].artifacts; + } + + async getArtifactsFromUnifiedManifestSO(): Promise< + Array< + InternalUnifiedManifestSchemaResponseType['_source']['endpoint:unified-user-artifact-manifest'] + > + > { + const { + hits: { hits: manifestResults }, + } = await this.esClient.search({ + index: '.kibana*', + query: { + bool: { filter: [{ term: { type: ManifestConstants.UNIFIED_SAVED_OBJECT_TYPE } }] }, + }, + }); - return artifacts; + return manifestResults.map( + (result) => result._source!['endpoint:unified-user-artifact-manifest'] + ); } } diff --git a/x-pack/test/spaces_api_integration/common/lib/create_users_and_roles.ts b/x-pack/test/spaces_api_integration/common/lib/create_users_and_roles.ts index 15ee9785aa690..58ef5ba9f9481 100644 --- a/x-pack/test/spaces_api_integration/common/lib/create_users_and_roles.ts +++ b/x-pack/test/spaces_api_integration/common/lib/create_users_and_roles.ts @@ -5,11 +5,11 @@ * 2.0. */ -import { SuperTest } from 'supertest'; +import { Agent as SuperTestAgent } from 'supertest'; import type { Client } from '@elastic/elasticsearch'; import { AUTHENTICATION } from './authentication'; -export const createUsersAndRoles = async (es: Client, supertest: SuperTest) => { +export const createUsersAndRoles = async (es: Client, supertest: SuperTestAgent) => { await supertest .put('/api/security/role/kibana_legacy_user') .send({ diff --git a/x-pack/test/spaces_api_integration/common/suites/disable_legacy_url_aliases.ts b/x-pack/test/spaces_api_integration/common/suites/disable_legacy_url_aliases.ts index 002ed6c3e6515..5889a10479f31 100644 --- a/x-pack/test/spaces_api_integration/common/suites/disable_legacy_url_aliases.ts +++ b/x-pack/test/spaces_api_integration/common/suites/disable_legacy_url_aliases.ts @@ -6,7 +6,7 @@ */ import expect from '@kbn/expect'; -import type { SuperTest } from 'supertest'; +import type { Agent as SuperTestAgent } from 'supertest'; import type { Client } from '@elastic/elasticsearch'; import type { LegacyUrlAlias } from '@kbn/core-saved-objects-base-server-internal'; import { MAIN_SAVED_OBJECT_INDEX } from '@kbn/core-saved-objects-server'; @@ -48,7 +48,7 @@ const getTestTitle = ({ targetSpace, targetType, sourceId }: DisableLegacyUrlAli export function disableLegacyUrlAliasesTestSuiteFactory( es: Client, esArchiver: any, - supertest: SuperTest + supertest: SuperTestAgent ) { const expectResponseBody = (testCase: DisableLegacyUrlAliasesTestCase, statusCode: 204 | 403): ExpectResponseBody => @@ -117,7 +117,7 @@ export function disableLegacyUrlAliasesTestSuiteFactory( const requestBody = test.request; await supertest .post(`${getUrlPrefix(spaceId)}/api/spaces/_disable_legacy_url_aliases`) - .auth(user?.username, user?.password) + .auth(user?.username!, user?.password!) .send(requestBody) .expect(test.responseStatusCode) .then(test.responseBody); diff --git a/x-pack/test/spaces_api_integration/common/suites/get_shareable_references.ts b/x-pack/test/spaces_api_integration/common/suites/get_shareable_references.ts index bedc8a52409b6..c1630bc288169 100644 --- a/x-pack/test/spaces_api_integration/common/suites/get_shareable_references.ts +++ b/x-pack/test/spaces_api_integration/common/suites/get_shareable_references.ts @@ -7,7 +7,7 @@ import expect from '@kbn/expect'; import { deepFreeze } from '@kbn/std'; -import { SuperTest } from 'supertest'; +import { Agent as SuperTestAgent } from 'supertest'; import { SavedObjectsCollectMultiNamespaceReferencesResponse, SavedObjectReferenceWithContext, @@ -192,7 +192,7 @@ const getRedactedSpaces = (authorizedSpace: string | undefined, spaces: string[] return redactedSpaces.sort((a, b) => (a === '?' ? 1 : b === '?' ? -1 : 0)); // unknown spaces are always at the end of the array }; -export function getShareableReferencesTestSuiteFactory(esArchiver: any, supertest: SuperTest) { +export function getShareableReferencesTestSuiteFactory(esArchiver: any, supertest: SuperTestAgent) { const expectForbidden = expectResponses.forbiddenTypes('share_to_space'); const expectResponseBody = ( @@ -274,7 +274,7 @@ export function getShareableReferencesTestSuiteFactory(esArchiver: any, supertes const requestBody = test.request; await supertest .post(`${getUrlPrefix(spaceId)}/api/spaces/_get_shareable_references`) - .auth(user?.username, user?.password) + .auth(user?.username!, user?.password!) .send(requestBody) .expect(test.responseStatusCode) .then(test.responseBody); diff --git a/x-pack/test/spaces_api_integration/common/suites/update_objects_spaces.ts b/x-pack/test/spaces_api_integration/common/suites/update_objects_spaces.ts index 14eb97c38c6ee..777581d9aa5a0 100644 --- a/x-pack/test/spaces_api_integration/common/suites/update_objects_spaces.ts +++ b/x-pack/test/spaces_api_integration/common/suites/update_objects_spaces.ts @@ -9,7 +9,7 @@ import expect from '@kbn/expect'; import type { Client } from '@elastic/elasticsearch'; import type { SearchTotalHits } from '@elastic/elasticsearch/lib/api/types'; import { without, uniq } from 'lodash'; -import { SuperTest } from 'supertest'; +import { Agent as SuperTestAgent } from 'supertest'; import { SavedObjectsErrorHelpers, SavedObjectsUpdateObjectsSpacesResponse, @@ -61,7 +61,7 @@ const getTestTitle = ({ objects, spacesToAdd, spacesToRemove }: UpdateObjectsSpa export function updateObjectsSpacesTestSuiteFactory( es: Client, esArchiver: any, - supertest: SuperTest + supertest: SuperTestAgent ) { const expectForbidden = expectResponses.forbiddenTypes('share_to_space'); const expectResponseBody = @@ -162,7 +162,7 @@ export function updateObjectsSpacesTestSuiteFactory( const requestBody = test.request; await supertest .post(`${getUrlPrefix(spaceId)}/api/spaces/_update_objects_spaces`) - .auth(user?.username, user?.password) + .auth(user?.username!, user?.password!) .send(requestBody) .expect(test.responseStatusCode) .then(test.responseBody); diff --git a/x-pack/test_serverless/api_integration/services/slo_api.ts b/x-pack/test_serverless/api_integration/services/slo_api.ts index 5a5c9eb5c5ff7..7312905589cb7 100644 --- a/x-pack/test_serverless/api_integration/services/slo_api.ts +++ b/x-pack/test_serverless/api_integration/services/slo_api.ts @@ -5,6 +5,11 @@ * 2.0. */ +import { + fetchHistoricalSummaryParamsSchema, + FetchHistoricalSummaryResponse, +} from '@kbn/slo-schema'; +import * as t from 'io-ts'; import { FtrProviderContext } from '../ftr_provider_context'; type DurationUnit = 'm' | 'h' | 'd' | 'w' | 'M'; @@ -58,6 +63,10 @@ interface SloParams { groupBy: string; } +type FetchHistoricalSummaryParams = t.OutputOf< + typeof fetchHistoricalSummaryParamsSchema.props.body +>; + export function SloApiProvider({ getService }: FtrProviderContext) { const es = getService('es'); const supertest = getService('supertest'); @@ -84,6 +93,18 @@ export function SloApiProvider({ getService }: FtrProviderContext) { return response; }, + async fetchHistoricalSummary( + params: FetchHistoricalSummaryParams + ): Promise { + const { body } = await supertest + .post(`/internal/observability/slos/_historical_summary`) + .set('kbn-xsrf', 'foo') + .set('x-elastic-internal-origin', 'foo') + .send(params); + + return body; + }, + async waitForSloToBeDeleted(sloId: string) { if (!sloId) { throw new Error(`sloId is undefined`); diff --git a/x-pack/test_serverless/api_integration/services/svl_cases/api.ts b/x-pack/test_serverless/api_integration/services/svl_cases/api.ts index 8f23eba1ea981..7089655551fbe 100644 --- a/x-pack/test_serverless/api_integration/services/svl_cases/api.ts +++ b/x-pack/test_serverless/api_integration/services/svl_cases/api.ts @@ -141,7 +141,7 @@ export function SvlCasesApiServiceProvider({ getService }: FtrProviderContext) { params: CasePostRequest, expectedHttpCode: number = 200, auth: { user: User; space: string | null } | null = { user: superUser, space: null }, - headers: Record = {} + headers: Record = {} ): Promise { const apiCall = supertest.post(`${CASES_URL}`); diff --git a/x-pack/test_serverless/api_integration/services/transform/api.ts b/x-pack/test_serverless/api_integration/services/transform/api.ts index 39c2d01c6adb1..c865dcec6e8a0 100644 --- a/x-pack/test_serverless/api_integration/services/transform/api.ts +++ b/x-pack/test_serverless/api_integration/services/transform/api.ts @@ -217,7 +217,7 @@ export function TransformAPIProvider({ getService }: FtrProviderContext) { ); const { body, status } = await esSupertest .put(`/_transform/${transformId}${deferValidation ? '?defer_validation=true' : ''}`) - .set(headers) + .set(headers as Record) .send(transformConfig); this.assertResponseStatusCode(200, status, body); } else { 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 bd8c64bed6731..88f3f1a76d3bb 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 @@ -6,7 +6,7 @@ */ import moment from 'moment'; -import type { SuperTest, Test } from 'supertest'; +import type { Agent as SuperTestAgent } from 'supertest'; interface CreateEsQueryRuleParams { size: number; @@ -32,7 +32,7 @@ export async function createIndexConnector({ name, indexName, }: { - supertest: SuperTest; + supertest: SuperTestAgent; name: string; indexName: string; }) { @@ -56,7 +56,7 @@ export async function createSlackConnector({ supertest, name, }: { - supertest: SuperTest; + supertest: SuperTestAgent; name: string; }) { const { body } = await supertest @@ -87,7 +87,7 @@ export async function createEsQueryRule({ notifyWhen, enabled = true, }: { - supertest: SuperTest; + supertest: SuperTestAgent; ruleTypeId: string; name: string; params: CreateEsQueryRuleParams; @@ -134,7 +134,7 @@ export async function createAnomalyRule({ ruleTypeId = 'apm.anomaly', params, }: { - supertest: SuperTest; + supertest: SuperTestAgent; name?: string; consumer?: string; actions?: any[]; @@ -184,7 +184,7 @@ export async function createLatencyThresholdRule({ ruleTypeId = 'apm.transaction_duration', params, }: { - supertest: SuperTest; + supertest: SuperTestAgent; name?: string; consumer?: string; actions?: any[]; @@ -233,7 +233,7 @@ export async function createInventoryRule({ ruleTypeId = 'metrics.alert.inventory.threshold', params, }: { - supertest: SuperTest; + supertest: SuperTestAgent; name?: string; consumer?: string; actions?: any[]; @@ -287,7 +287,7 @@ export async function disableRule({ supertest, ruleId, }: { - supertest: SuperTest; + supertest: SuperTestAgent; ruleId: string; }) { const { body } = await supertest @@ -303,7 +303,7 @@ export async function updateEsQueryRule({ ruleId, updates, }: { - supertest: SuperTest; + supertest: SuperTestAgent; ruleId: string; updates: any; }) { @@ -341,7 +341,7 @@ export async function runRule({ supertest, ruleId, }: { - supertest: SuperTest; + supertest: SuperTestAgent; ruleId: string; }) { const response = await supertest @@ -356,7 +356,7 @@ export async function muteRule({ supertest, ruleId, }: { - supertest: SuperTest; + supertest: SuperTestAgent; ruleId: string; }) { const { body } = await supertest @@ -371,7 +371,7 @@ export async function enableRule({ supertest, ruleId, }: { - supertest: SuperTest; + supertest: SuperTestAgent; ruleId: string; }) { const { body } = await supertest @@ -387,7 +387,7 @@ export async function muteAlert({ ruleId, alertId, }: { - supertest: SuperTest; + supertest: SuperTestAgent; ruleId: string; alertId: string; }) { @@ -403,7 +403,7 @@ export async function unmuteRule({ supertest, ruleId, }: { - supertest: SuperTest; + supertest: SuperTestAgent; ruleId: string; }) { const { body } = await supertest @@ -418,7 +418,7 @@ export async function snoozeRule({ supertest, ruleId, }: { - supertest: SuperTest; + supertest: SuperTestAgent; ruleId: string; }) { const { body } = await supertest @@ -443,7 +443,7 @@ export async function findRule({ supertest, ruleId, }: { - supertest: SuperTest; + supertest: SuperTestAgent; ruleId: string; }) { if (!ruleId) { 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 00b746697cd23..55bfa422c5f4b 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 @@ -6,7 +6,7 @@ */ import pRetry from 'p-retry'; -import type { SuperTest, Test } from 'supertest'; +import type { Agent as SuperTestAgent } from 'supertest'; import type { Client } from '@elastic/elasticsearch'; import type { AggregationsAggregate, @@ -372,7 +372,7 @@ export async function waitForNumRuleRuns({ esClient, testStart, }: { - supertest: SuperTest; + supertest: SuperTestAgent; numOfRuns: number; ruleId: string; esClient: Client; diff --git a/x-pack/test_serverless/api_integration/test_suites/common/index_management/index.ts b/x-pack/test_serverless/api_integration/test_suites/common/index_management/index.ts index c7e8c7b171bc9..608530a51e72a 100644 --- a/x-pack/test_serverless/api_integration/test_suites/common/index_management/index.ts +++ b/x-pack/test_serverless/api_integration/test_suites/common/index_management/index.ts @@ -13,6 +13,7 @@ export default function ({ loadTestFile }: FtrProviderContext) { loadTestFile(require.resolve('./index_templates')); loadTestFile(require.resolve('./indices')); + loadTestFile(require.resolve('./inference_endpoints')); loadTestFile(require.resolve('./enrich_policies')); loadTestFile(require.resolve('./create_enrich_policies')); loadTestFile(require.resolve('./index_component_templates')); diff --git a/x-pack/test_serverless/api_integration/test_suites/common/index_management/inference_endpoints.ts b/x-pack/test_serverless/api_integration/test_suites/common/index_management/inference_endpoints.ts new file mode 100644 index 0000000000000..cacf294b4c81a --- /dev/null +++ b/x-pack/test_serverless/api_integration/test_suites/common/index_management/inference_endpoints.ts @@ -0,0 +1,64 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import expect from '@kbn/expect'; +import { FtrProviderContext } from '../../../ftr_provider_context'; + +const API_BASE_PATH = '/api/index_management'; + +export default function ({ getService }: FtrProviderContext) { + const supertest = getService('supertest'); + const log = getService('log'); + const ml = getService('ml'); + const inferenceId = 'my-elser-model'; + const taskType = 'sparse_embedding'; + const service = 'elser'; + + describe('Inference endpoints', function () { + // test adds new trained model '.elser_model_2_linux-x86_64', but does not clean it. Follow up tests are affected + this.tags(['failsOnMKI']); + before(async () => { + log.debug(`Creating inference endpoint`); + try { + await ml.api.createInferenceEndpoint(inferenceId, taskType, { + service, + service_settings: { + num_allocations: 1, + num_threads: 1, + }, + }); + } catch (err) { + log.debug('[Setup error] Error creating inference endpoint'); + throw err; + } + }); + + after(async () => { + // Cleanup inference endpoints created for testing purposes + try { + log.debug(`Deleting inference endpoint`); + await ml.api.deleteInferenceEndpoint(inferenceId, taskType); + } catch (err) { + log.debug('[Cleanup error] Error deleting inference endpoint'); + throw err; + } + }); + + describe('get inference endpoints', () => { + it('returns the existing inference endpoints', async () => { + const { body: inferenceEndpoints } = await supertest + .get(`${API_BASE_PATH}/inference/all`) + .set('kbn-xsrf', 'xxx') + .set('x-elastic-internal-origin', 'xxx') + .expect(200); + + expect(inferenceEndpoints).to.be.ok(); + expect(inferenceEndpoints[0].model_id).to.eql(inferenceId); + }); + }); + }); +} diff --git a/x-pack/test_serverless/api_integration/test_suites/common/platform_security/feature_check.ts b/x-pack/test_serverless/api_integration/test_suites/common/platform_security/feature_check.ts new file mode 100644 index 0000000000000..e42cb88eec0f8 --- /dev/null +++ b/x-pack/test_serverless/api_integration/test_suites/common/platform_security/feature_check.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 { FtrProviderContext } from '../../../ftr_provider_context'; + +export default function ({ getService }: FtrProviderContext) { + const svlCommonApi = getService('svlCommonApi'); + const supertest = getService('supertest'); + + describe('security/features', function () { + it('route access disabled', async () => { + const { body, status } = await supertest + .get('/internal/security/_check_security_features') + .set(svlCommonApi.getInternalRequestHeader()); + svlCommonApi.assertApiNotFound(body, status); + }); + }); +} diff --git a/x-pack/test_serverless/api_integration/test_suites/common/platform_security/index.ts b/x-pack/test_serverless/api_integration/test_suites/common/platform_security/index.ts index 86d4ad05cfc35..fab6e47e87969 100644 --- a/x-pack/test_serverless/api_integration/test_suites/common/platform_security/index.ts +++ b/x-pack/test_serverless/api_integration/test_suites/common/platform_security/index.ts @@ -25,5 +25,6 @@ export default function ({ loadTestFile }: FtrProviderContext) { loadTestFile(require.resolve('./request_as_viewer')); loadTestFile(require.resolve('./user_profiles')); loadTestFile(require.resolve('./views')); + loadTestFile(require.resolve('./feature_check')); }); } diff --git a/x-pack/test_serverless/api_integration/test_suites/common/platform_security/role_mappings.ts b/x-pack/test_serverless/api_integration/test_suites/common/platform_security/role_mappings.ts index 4d1f25cfd772f..bfddf5b4a3267 100644 --- a/x-pack/test_serverless/api_integration/test_suites/common/platform_security/role_mappings.ts +++ b/x-pack/test_serverless/api_integration/test_suites/common/platform_security/role_mappings.ts @@ -42,13 +42,6 @@ export default function ({ getService }: FtrProviderContext) { .set(svlCommonApi.getInternalRequestHeader()); svlCommonApi.assertApiNotFound(body, status); }); - - it('role mapping feature check', async () => { - const { body, status } = await supertest - .get('/internal/security/_check_role_mapping_features') - .set(svlCommonApi.getInternalRequestHeader()); - svlCommonApi.assertApiNotFound(body, status); - }); }); }); }); diff --git a/x-pack/test_serverless/api_integration/test_suites/observability/apm_api_integration/common/apm_api_supertest.ts b/x-pack/test_serverless/api_integration/test_suites/observability/apm_api_integration/common/apm_api_supertest.ts index ac324b3fda087..62db8c2eddda4 100644 --- a/x-pack/test_serverless/api_integration/test_suites/observability/apm_api_integration/common/apm_api_supertest.ts +++ b/x-pack/test_serverless/api_integration/test_suites/observability/apm_api_integration/common/apm_api_supertest.ts @@ -16,7 +16,7 @@ import type { APIEndpoint } from '@kbn/apm-plugin/server'; import { formatRequest } from '@kbn/server-route-repository'; import { InheritedFtrProviderContext } from '../../../../services'; -export function createApmApiClient(st: supertest.SuperTest) { +export function createApmApiClient(st: supertest.Agent) { return async ( options: { type?: 'form-data'; diff --git a/x-pack/test_serverless/api_integration/test_suites/observability/dataset_quality_api_integration/common/dataset_quality_api_supertest.ts b/x-pack/test_serverless/api_integration/test_suites/observability/dataset_quality_api_integration/common/dataset_quality_api_supertest.ts index 2cdb6ec4fd765..f1d746b49ff06 100644 --- a/x-pack/test_serverless/api_integration/test_suites/observability/dataset_quality_api_integration/common/dataset_quality_api_supertest.ts +++ b/x-pack/test_serverless/api_integration/test_suites/observability/dataset_quality_api_integration/common/dataset_quality_api_supertest.ts @@ -13,7 +13,7 @@ import type { APIEndpoint } from '@kbn/dataset-quality-plugin/server/routes'; import { formatRequest } from '@kbn/server-route-repository'; import { InheritedFtrProviderContext } from '../../../../services'; -export function createDatasetQualityApiClient(st: supertest.SuperTest) { +export function createDatasetQualityApiClient(st: supertest.Agent) { return async ( options: { type?: 'form-data'; diff --git a/x-pack/test_serverless/api_integration/test_suites/observability/slos/fetch_historical_summary.ts b/x-pack/test_serverless/api_integration/test_suites/observability/slos/fetch_historical_summary.ts new file mode 100644 index 0000000000000..32992e5a3b07b --- /dev/null +++ b/x-pack/test_serverless/api_integration/test_suites/observability/slos/fetch_historical_summary.ts @@ -0,0 +1,132 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license 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 { + SLO_DESTINATION_INDEX_NAME, + SLO_DESTINATION_INDEX_PATTERN, +} from '@kbn/slo-plugin/common/constants'; + +import { ALL_VALUE } from '@kbn/slo-schema'; +import moment from 'moment'; +import { FtrProviderContext } from '../../../ftr_provider_context'; + +export default function ({ getService }: FtrProviderContext) { + const esClient = getService('es'); + const esDeleteAllIndices = getService('esDeleteAllIndices'); + const sloApi = getService('sloApi'); + + const SLO_ID = 'slo-fake-1'; + // Failing: See https://github.com/elastic/kibana/issues/183748 + describe.skip('fetch historical summary', () => { + before(async () => { + const now = moment().startOf('minute'); + const curr = now.clone().subtract(30, 'days'); + const end = now.clone().add(5, 'minutes'); + + const batchOperations = []; + while (curr.isSameOrBefore(end)) { + batchOperations.push([ + { index: { _index: SLO_DESTINATION_INDEX_NAME } }, + { + '@timestamp': curr.toISOString(), + slo: { + id: SLO_ID, + revision: 1, + instanceId: ALL_VALUE, + numerator: 90, + denominator: 100, + isGoodSlice: 1, + groupings: {}, + }, + }, + ]); + curr.add(1, 'minute'); + } + + await esClient.bulk({ + index: SLO_DESTINATION_INDEX_NAME, + operations: batchOperations.flat(), + refresh: 'wait_for', + }); + + await esClient.indices.refresh({ index: SLO_DESTINATION_INDEX_NAME }); + }); + + after(async () => { + await esDeleteAllIndices(SLO_DESTINATION_INDEX_PATTERN); + }); + + it('computes the historical summary for a rolling occurrences SLO', async () => { + const response = await sloApi.fetchHistoricalSummary({ + list: [ + { + sloId: SLO_ID, + instanceId: ALL_VALUE, + timeWindow: { + duration: '7d', + type: 'rolling', + }, + budgetingMethod: 'occurrences', + objective: { + target: 0.9, + }, + groupBy: ALL_VALUE, + revision: 1, + }, + ], + }); + expect(response[0].sloId).to.eql(SLO_ID); + expect(response[0].instanceId).to.eql(ALL_VALUE); + expect(response[0].data).to.have.length(168); // 7 days * 24 hours/day * 1 bucket/hour + const last = response[0].data.pop(); + expect(last?.errorBudget).to.eql({ + consumed: 1, + initial: 0.1, + isEstimated: false, + remaining: 0, + }); + expect(last?.sliValue).to.eql(0.9); + expect(last?.status).to.eql('HEALTHY'); + }); + + it('computes the historical summary for a rolling timeslices SLO', async () => { + const response = await sloApi.fetchHistoricalSummary({ + list: [ + { + sloId: SLO_ID, + instanceId: ALL_VALUE, + timeWindow: { + duration: '7d', + type: 'rolling', + }, + budgetingMethod: 'timeslices', + objective: { + target: 0.9, + timesliceTarget: 0.8, + timesliceWindow: '1m', + }, + groupBy: ALL_VALUE, + revision: 1, + }, + ], + }); + expect(response[0].sloId).to.eql(SLO_ID); + expect(response[0].instanceId).to.eql(ALL_VALUE); + expect(response[0].data).to.have.length(168); // 7 days * 24 hours/day * 1 bucket/hour + const last = response[0].data.pop(); + expect(last?.errorBudget).to.eql({ + consumed: 0, + initial: 0.1, + isEstimated: false, + remaining: 1, + }); + expect(last?.sliValue).to.eql(1); + expect(last?.status).to.eql('HEALTHY'); + }); + }); +} diff --git a/x-pack/test_serverless/api_integration/test_suites/observability/slos/index.ts b/x-pack/test_serverless/api_integration/test_suites/observability/slos/index.ts index 77d2b169fc7aa..8df59e6f3b624 100644 --- a/x-pack/test_serverless/api_integration/test_suites/observability/slos/index.ts +++ b/x-pack/test_serverless/api_integration/test_suites/observability/slos/index.ts @@ -10,5 +10,6 @@ export default function ({ loadTestFile }: FtrProviderContext) { describe('SLOs', function () { loadTestFile(require.resolve('./create_slo')); loadTestFile(require.resolve('./delete_slo')); + loadTestFile(require.resolve('./fetch_historical_summary')); }); } diff --git a/x-pack/test_serverless/api_integration/test_suites/observability/synthetics/synthetics_enablement.ts b/x-pack/test_serverless/api_integration/test_suites/observability/synthetics/synthetics_enablement.ts index fae09f97cf2a2..9925c00fe5748 100644 --- a/x-pack/test_serverless/api_integration/test_suites/observability/synthetics/synthetics_enablement.ts +++ b/x-pack/test_serverless/api_integration/test_suites/observability/synthetics/synthetics_enablement.ts @@ -65,7 +65,7 @@ export default function ({ getService }: FtrProviderContext) { async function enablementPut(role: RoleName = 'admin', expectedStatus: number = 200) { return supertestWithoutAuth .put(SYNTHETICS_API_URLS.SYNTHETICS_ENABLEMENT) - .set(internalRequestHeader) + .set(internalRequestHeader as unknown as Record) .set(await svlUserManager.getApiCredentialsForRole(role)) .expect(expectedStatus); } @@ -73,7 +73,7 @@ export default function ({ getService }: FtrProviderContext) { async function enablementDelete(role: RoleName = 'admin', expectedStatus: number = 200) { return supertestWithoutAuth .delete(SYNTHETICS_API_URLS.SYNTHETICS_ENABLEMENT) - .set(internalRequestHeader) + .set(internalRequestHeader as unknown as Record) .set(await svlUserManager.getApiCredentialsForRole(role)) .expect(expectedStatus); } diff --git a/x-pack/test_serverless/functional/test_suites/observability/observability_logs_explorer/columns_selection.ts b/x-pack/test_serverless/functional/test_suites/observability/observability_logs_explorer/columns_selection.ts index beb1adc25e70c..d32f3aff208b0 100644 --- a/x-pack/test_serverless/functional/test_suites/observability/observability_logs_explorer/columns_selection.ts +++ b/x-pack/test_serverless/functional/test_suites/observability/observability_logs_explorer/columns_selection.ts @@ -132,9 +132,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { expect(cellValue.includes('error.message')).to.be(false); expect(cellValue.includes('event.original')).to.be(false); - const cellAttribute = await cellElement.findByTestSubject( - 'logsExplorerCellDescriptionList' - ); + const cellAttribute = await cellElement.findByTestSubject('discoverCellDescriptionList'); expect(cellAttribute).not.to.be.empty(); }); }); diff --git a/x-pack/test_serverless/functional/test_suites/search/playground_overview.ts b/x-pack/test_serverless/functional/test_suites/search/playground_overview.ts index 17d9d81c1014c..f726287de0fb7 100644 --- a/x-pack/test_serverless/functional/test_suites/search/playground_overview.ts +++ b/x-pack/test_serverless/functional/test_suites/search/playground_overview.ts @@ -6,6 +6,7 @@ */ import { FtrProviderContext } from '../../ftr_provider_context'; +import { testHasEmbeddedConsole } from './embedded_console'; export default function ({ getPageObjects }: FtrProviderContext) { const pageObjects = getPageObjects(['svlCommonPage', 'svlCommonNavigation', 'svlPlaygroundUI']); @@ -23,5 +24,9 @@ export default function ({ getPageObjects }: FtrProviderContext) { await pageObjects.svlPlaygroundUI.PlaygrounStartChatPage.expectPlaygroundStartChatPageComponentsToExist(); await pageObjects.svlPlaygroundUI.PlaygrounStartChatPage.expectPlaygroundHeaderComponentsToExist(); }); + + it('has embedded console', async () => { + await testHasEmbeddedConsole(pageObjects); + }); }); } diff --git a/x-pack/test_serverless/functional/test_suites/security/ml/trained_models_list.ts b/x-pack/test_serverless/functional/test_suites/security/ml/trained_models_list.ts index 745f2b8d4a65f..8e6928b9817a2 100644 --- a/x-pack/test_serverless/functional/test_suites/security/ml/trained_models_list.ts +++ b/x-pack/test_serverless/functional/test_suites/security/ml/trained_models_list.ts @@ -11,7 +11,10 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const svlMl = getService('svlMl'); const PageObjects = getPageObjects(['svlCommonPage']); + // failsOnMKI, see https://github.com/elastic/kibana/issues/180481 describe('Trained models list', function () { + this.tags(['failsOnMKI']); + before(async () => { await PageObjects.svlCommonPage.login(); await ml.api.syncSavedObjects(); diff --git a/x-pack/test_serverless/shared/lib/object_remover.ts b/x-pack/test_serverless/shared/lib/object_remover.ts index ad029ca579cbd..ef43c70d0ee49 100644 --- a/x-pack/test_serverless/shared/lib/object_remover.ts +++ b/x-pack/test_serverless/shared/lib/object_remover.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { SuperTest, Test } from 'supertest'; +import { Agent as SuperTestAgent } from 'supertest'; import { getUrlPathPrefixForSpace } from './space_path_prefix'; @@ -18,10 +18,10 @@ interface ObjectToRemove { } export class ObjectRemover { - private readonly supertest: SuperTest; + private readonly supertest: SuperTestAgent; private objectsToRemove: ObjectToRemove[] = []; - constructor(supertest: SuperTest) { + constructor(supertest: SuperTestAgent) { this.supertest = supertest; } @@ -60,7 +60,7 @@ export class ObjectRemover { } interface DeleteObjectParams { - supertest: SuperTest; + supertest: SuperTestAgent; url: string; plugin: string; } diff --git a/x-pack/test_serverless/shared/services/bsearch_secure.ts b/x-pack/test_serverless/shared/services/bsearch_secure.ts index 2493c1d76e09c..14a373ab99686 100644 --- a/x-pack/test_serverless/shared/services/bsearch_secure.ts +++ b/x-pack/test_serverless/shared/services/bsearch_secure.ts @@ -25,7 +25,7 @@ const parseBfetchResponse = (resp: request.Response): Array> }; interface SendOptions { - supertestWithoutAuth: SuperTest.SuperTest; + supertestWithoutAuth: SuperTest.Agent; apiKeyHeader: { Authorization: string }; referer?: string; kibanaVersion?: string; diff --git a/yarn.lock b/yarn.lock index e35fbacacef73..63f50a8f16e93 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4583,6 +4583,10 @@ version "0.0.0" uid "" +"@kbn/entities-schema@link:x-pack/packages/kbn-entities-schema": + version "0.0.0" + uid "" + "@kbn/error-boundary-example-plugin@link:examples/error_boundary": version "0.0.0" uid "" @@ -9555,10 +9559,10 @@ dependencies: "@types/node" "*" -"@types/cookiejar@*": - version "2.1.2" - resolved "https://registry.yarnpkg.com/@types/cookiejar/-/cookiejar-2.1.2.tgz#66ad9331f63fe8a3d3d9d8c6e3906dd10f6446e8" - integrity sha512-t73xJJrvdTjXrn4jLS9VSGRbz0nUY3cl2DMGDU48lKl+HR9dbbjW2A9r3g40VA++mQpy6uuHg33gy7du2BKpog== +"@types/cookiejar@^2.1.5": + version "2.1.5" + resolved "https://registry.yarnpkg.com/@types/cookiejar/-/cookiejar-2.1.5.tgz#14a3e83fa641beb169a2dd8422d91c3c345a9a78" + integrity sha512-he+DHOWReW0nghN24E1WUqM0efK4kI9oTqDm6XmK8ZPe2djZ90BSNdGnIyCLzCPw7/pogPlGbzI2wHGGmi4O/Q== "@types/cytoscape@^3.14.0": version "3.14.0" @@ -10163,6 +10167,11 @@ resolved "https://registry.yarnpkg.com/@types/mdurl/-/mdurl-1.0.2.tgz#e2ce9d83a613bacf284c7be7d491945e39e1f8e9" integrity sha512-eC4U9MlIcu2q0KQmXszyn5Akca/0jrQmwDRgpAMJai7qBWq4amIQhZyNau4VYGtCeALvW1/NtjzJJ567aZxfKA== +"@types/methods@^1.1.4": + version "1.1.4" + resolved "https://registry.yarnpkg.com/@types/methods/-/methods-1.1.4.tgz#d3b7ac30ac47c91054ea951ce9eed07b1051e547" + integrity sha512-ymXWVrDiCxTBE3+RIrrP533E70eA+9qu7zdWoHuOmGujkYtzf4HQF96b8nwHLqhuf4ykX61IGRIB38CC6/sImQ== + "@types/micromatch@^4.0.2": version "4.0.2" resolved "https://registry.yarnpkg.com/@types/micromatch/-/micromatch-4.0.2.tgz#ce29c8b166a73bf980a5727b1e4a4d099965151d" @@ -10268,7 +10277,7 @@ dependencies: "@types/node" "*" -"@types/node@*", "@types/node@20.10.5", "@types/node@>= 8", "@types/node@>=12.12.47", "@types/node@>=13.7.0", "@types/node@>=18.0.0", "@types/node@^14.0.10 || ^16.0.0", "@types/node@^14.14.20 || ^16.0.0", "@types/node@^18.0.0", "@types/node@^18.11.18", "@types/node@^18.17.5": +"@types/node@*", "@types/node@20.10.5", "@types/node@>= 8", "@types/node@>=12.12.47", "@types/node@>=13.7.0", "@types/node@>=18.0.0", "@types/node@^14.0.10 || ^16.0.0", "@types/node@^14.14.20 || ^16.0.0", "@types/node@^18.0.0", "@types/node@^18.11.18": version "20.10.5" resolved "https://registry.yarnpkg.com/@types/node/-/node-20.10.5.tgz#47ad460b514096b7ed63a1dae26fad0914ed3ab2" integrity sha512-nNPsNE65wjMxEKI93yOP+NPGGBJz/PoN3kZsVLee0XMiJolxSekEVD8wRwBUBqkwc7UWop0edW50yrCQW4CyRw== @@ -10701,20 +10710,22 @@ resolved "https://registry.yarnpkg.com/@types/stylis/-/stylis-4.2.0.tgz#199a3f473f0c3a6f6e4e1b17cdbc967f274bdc6b" integrity sha512-n4sx2bqL0mW1tvDf/loQ+aMX7GQD3lc3fkCMC55VFNDu/vBOabO+LTIeXKM14xK0ppk5TUGcWRjiSpIlUpghKw== -"@types/superagent@*": - version "3.8.4" - resolved "https://registry.yarnpkg.com/@types/superagent/-/superagent-3.8.4.tgz#24a5973c7d1a9c024b4bbda742a79267c33fb86a" - integrity sha512-Dnh0Iw6NO55z1beXvlsvUrfk4cd9eL2nuTmUk+rAhSVCk10PGGFbqCCTwbau9D0d2W3DITiXl4z8VCqppGkMPQ== +"@types/superagent@^8.1.0": + version "8.1.7" + resolved "https://registry.yarnpkg.com/@types/superagent/-/superagent-8.1.7.tgz#1153819ed4db34427409a1cc58f3e2f13eeec862" + integrity sha512-NmIsd0Yj4DDhftfWvvAku482PZum4DBW7U51OvS8gvOkDDY0WT1jsVyDV3hK+vplrsYw8oDwi9QxOM7U68iwww== dependencies: - "@types/cookiejar" "*" + "@types/cookiejar" "^2.1.5" + "@types/methods" "^1.1.4" "@types/node" "*" -"@types/supertest@^2.0.12": - version "2.0.12" - resolved "https://registry.yarnpkg.com/@types/supertest/-/supertest-2.0.12.tgz#ddb4a0568597c9aadff8dbec5b2e8fddbe8692fc" - integrity sha512-X3HPWTwXRerBZS7Mo1k6vMVR1Z6zmJcDVn5O/31whe0tnjE4te6ZJSJGq1RiqHPjzPdMTfjCFogDJmwng9xHaQ== +"@types/supertest@^6.0.2": + version "6.0.2" + resolved "https://registry.yarnpkg.com/@types/supertest/-/supertest-6.0.2.tgz#2af1c466456aaf82c7c6106c6b5cbd73a5e86588" + integrity sha512-137ypx2lk/wTQbW6An6safu9hXmajAifU/s7szAHLN/FeIm5w7yR0Wkl9fdJMRSHwOn4HLAI0DaB2TOORuhPDg== dependencies: - "@types/superagent" "*" + "@types/methods" "^1.1.4" + "@types/superagent" "^8.1.0" "@types/tapable@^1", "@types/tapable@^1.0.5", "@types/tapable@^1.0.6": version "1.0.6" @@ -12246,12 +12257,12 @@ axe-core@^4.9.0: resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.9.0.tgz#b18971494551ab39d4ff5f7d4c6411bd20cc7c2a" integrity sha512-H5orY+M2Fr56DWmMFpMrq5Ge93qjNdPVqzBv5gWK3aD1OvjBEJlEzxf09z93dGVQeI0LiW+aCMIx1QtShC/zUw== -axios@1.6.3, axios@^1.0.0, axios@^1.3.4, axios@^1.6.0, axios@^1.6.7: - version "1.6.3" - resolved "https://registry.npmjs.org/axios/-/axios-1.6.3.tgz#7f50f23b3aa246eff43c54834272346c396613f4" - integrity sha512-fWyNdeawGam70jXSVlKl+SUNVcL6j6W79CuSIPfi6HnDUmSCH6gyUys/HrqHeA/wU0Az41rRgean494d0Jb+ww== +axios@^1.0.0, axios@^1.3.4, axios@^1.6.0, axios@^1.6.7, axios@^1.6.8: + version "1.6.8" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.6.8.tgz#66d294951f5d988a00e87a0ffb955316a619ea66" + integrity sha512-v/ZHtJDU39mDpyBoFVkETcd/uNdxrWRrg3bKpOKzXFA6Bvqopts6ALSMU3y6ijYxbw2B+wPrIv46egTzJXCLGQ== dependencies: - follow-redirects "^1.15.0" + follow-redirects "^1.15.6" form-data "^4.0.0" proxy-from-env "^1.1.0" @@ -14692,14 +14703,13 @@ cypress-recurse@^1.35.2: dependencies: humanize-duration "^3.27.3" -cypress@13.6.2: - version "13.6.2" - resolved "https://registry.yarnpkg.com/cypress/-/cypress-13.6.2.tgz#c70df09db0a45063298b3cecba2fa21109768e08" - integrity sha512-TW3bGdPU4BrfvMQYv1z3oMqj71YI4AlgJgnrycicmPZAXtvywVFZW9DAToshO65D97rCWfG/kqMFsYB6Kp91gQ== +cypress@13.6.3: + version "13.6.3" + resolved "https://registry.yarnpkg.com/cypress/-/cypress-13.6.3.tgz#54f03ca07ee56b2bc18211e7bd32abd2533982ba" + integrity sha512-d/pZvgwjAyZsoyJ3FOsJT5lDsqnxQ/clMqnNc++rkHjbkkiF2h9s0JsZSyyH4QXhVFW3zPFg82jD25roFLOdZA== dependencies: "@cypress/request" "^3.0.0" "@cypress/xvfb" "^1.2.4" - "@types/node" "^18.17.5" "@types/sinonjs__fake-timers" "8.1.1" "@types/sizzle" "^2.3.2" arch "^2.2.0" @@ -17589,10 +17599,10 @@ focus-lock@^0.11.6: dependencies: tslib "^2.0.3" -follow-redirects@1.15.2, follow-redirects@^1.0.0, follow-redirects@^1.15.0: - version "1.15.2" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13" - integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA== +follow-redirects@^1.0.0, follow-redirects@^1.15.6: + version "1.15.6" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.6.tgz#7f815c0cda4249c74ff09e95ef97c23b5fd0399b" + integrity sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA== font-awesome@4.7.0: version "4.7.0" @@ -17726,15 +17736,14 @@ formdata-polyfill@^4.0.10: dependencies: fetch-blob "^3.1.2" -formidable@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/formidable/-/formidable-2.1.2.tgz#fa973a2bec150e4ce7cac15589d7a25fc30ebd89" - integrity sha512-CM3GuJ57US06mlpQ47YcunuUZ9jpm8Vx+P2CGt2j7HpgkKZO/DJYQ0Bobim8G6PFQmK5lOqOOdUXboU+h73A4g== +formidable@^3.5.1: + version "3.5.1" + resolved "https://registry.yarnpkg.com/formidable/-/formidable-3.5.1.tgz#9360a23a656f261207868b1484624c4c8d06ee1a" + integrity sha512-WJWKelbRHN41m5dumb0/k8TeAx7Id/y3a+Z7QfhxP/htI9Js5zYaEDtG8uMgG0vM0lOlqnmjE99/kfpOYi/0Og== dependencies: dezalgo "^1.0.4" hexoid "^1.0.0" once "^1.4.0" - qs "^6.11.0" formik@^2.4.5: version "2.4.5" @@ -27655,7 +27664,7 @@ semver@7.5.4: dependencies: lru-cache "^6.0.0" -semver@7.6.0, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.3.8, semver@^7.5.0, semver@^7.5.2, semver@^7.5.3, semver@^7.5.4: +semver@7.6.0, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.5.0, semver@^7.5.2, semver@^7.5.3, semver@^7.5.4: version "7.6.0" resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.0.tgz#1a46a4db4bffcccd97b743b5005c8325f23d4e2d" integrity sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg== @@ -28745,7 +28754,7 @@ string-replace-loader@^2.2.0: loader-utils "^1.2.3" schema-utils "^1.0.0" -"string-width-cjs@npm:string-width@^4.2.0": +"string-width-cjs@npm:string-width@^4.2.0", "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -28763,15 +28772,6 @@ string-width@^1.0.1: is-fullwidth-code-point "^1.0.0" strip-ansi "^3.0.0" -"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - string-width@^5.0.1, string-width@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" @@ -28881,7 +28881,7 @@ stringify-object@^3.2.1: is-obj "^1.0.1" is-regexp "^1.0.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1": +"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -28895,13 +28895,6 @@ strip-ansi@^3.0.0, strip-ansi@^3.0.1: dependencies: ansi-regex "^2.0.0" -strip-ansi@^6.0.0, strip-ansi@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - strip-ansi@^7.0.1, strip-ansi@^7.1.0: version "7.1.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" @@ -29098,21 +29091,20 @@ stylus-lookup@^5.0.1: dependencies: commander "^10.0.1" -superagent@^8.0.5, superagent@^8.1.2: - version "8.1.2" - resolved "https://registry.yarnpkg.com/superagent/-/superagent-8.1.2.tgz#03cb7da3ec8b32472c9d20f6c2a57c7f3765f30b" - integrity sha512-6WTxW1EB6yCxV5VFOIPQruWGHqc3yI7hEmZK6h+pyk69Lk/Ut7rLUY6W/ONF2MjBuGjvmMiIpsrVJ2vjrHlslA== +superagent@^9.0.1, superagent@^9.0.2: + version "9.0.2" + resolved "https://registry.yarnpkg.com/superagent/-/superagent-9.0.2.tgz#a18799473fc57557289d6b63960610e358bdebc1" + integrity sha512-xuW7dzkUpcJq7QnhOsnNUgtYp3xRwpt2F7abdRYIpCsAt0hhUqia0EdxyXZQQpNmGtsCzYHryaKSV3q3GJnq7w== dependencies: component-emitter "^1.3.0" cookiejar "^2.1.4" debug "^4.3.4" fast-safe-stringify "^2.1.1" form-data "^4.0.0" - formidable "^2.1.2" + formidable "^3.5.1" methods "^1.1.2" mime "2.6.0" qs "^6.11.0" - semver "^7.3.8" supercluster@^8.0.1: version "8.0.1" @@ -29128,13 +29120,13 @@ superjson@^1.10.0: dependencies: copy-anything "^3.0.2" -supertest@^6.3.3: - version "6.3.3" - resolved "https://registry.yarnpkg.com/supertest/-/supertest-6.3.3.tgz#42f4da199fee656106fd422c094cf6c9578141db" - integrity sha512-EMCG6G8gDu5qEqRQ3JjjPs6+FYT1a7Hv5ApHvtSghmOFJYtsU5S+pSb6Y2EUeCEY3CmEL3mmQ8YWlPOzQomabA== +supertest@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/supertest/-/supertest-7.0.0.tgz#cac53b3d6872a0b317980b2b0cfa820f09cd7634" + integrity sha512-qlsr7fIC0lSddmA3tzojvzubYxvlGtzumcdHgPwbFWMISQwL22MhM2Y3LNt+6w9Yyx7559VW5ab70dgphm8qQA== dependencies: methods "^1.1.2" - superagent "^8.0.5" + superagent "^9.0.1" supports-color@8.1.1, supports-color@^8.0.0, supports-color@^8.1.1: version "8.1.1" @@ -31775,7 +31767,7 @@ workerpool@6.2.1: resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.2.1.tgz#46fc150c17d826b86a008e5a4508656777e9c343" integrity sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw== -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -31801,15 +31793,6 @@ wrap-ansi@^6.2.0: string-width "^4.1.0" strip-ansi "^6.0.0" -wrap-ansi@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - wrap-ansi@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214"