diff --git a/.buildkite/ftr_platform_stateful_configs.yml b/.buildkite/ftr_platform_stateful_configs.yml index 09b2feced215b..f9d21fbb4934d 100644 --- a/.buildkite/ftr_platform_stateful_configs.yml +++ b/.buildkite/ftr_platform_stateful_configs.yml @@ -66,6 +66,7 @@ enabled: - test/functional/apps/dashboard/group4/config.ts - test/functional/apps/dashboard/group5/config.ts - test/functional/apps/dashboard/group6/config.ts + - test/functional/apps/dashboard/esql_controls/config.ts - test/functional/apps/discover/ccs_compatibility/config.ts - test/functional/apps/discover/embeddable/config.ts - test/functional/apps/discover/esql/config.ts @@ -285,7 +286,6 @@ enabled: - x-pack/test/functional_cloud/saml.config.ts - x-pack/test/functional_solution_sidenav/config.ts - x-pack/test/functional_search/config.ts - - x-pack/test/kubernetes_security/basic/config.ts - x-pack/test/licensing_plugin/config.public.ts - x-pack/test/licensing_plugin/config.ts - x-pack/test/monitoring_api_integration/config.ts diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 08146425bd3a4..f0d77e3770272 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -254,6 +254,7 @@ src/core/packages/http/browser @elastic/kibana-core src/core/packages/http/browser-internal @elastic/kibana-core src/core/packages/http/common @elastic/kibana-core src/core/packages/http/context-server-internal @elastic/kibana-core +src/core/packages/http/rate-limiter-internal @elastic/kibana-core src/core/packages/http/request-handler-context-server @elastic/kibana-core src/core/packages/http/request-handler-context-server-internal @elastic/kibana-core src/core/packages/http/resources-server @elastic/kibana-core @@ -463,6 +464,7 @@ src/platform/packages/shared/kbn-es-types @elastic/kibana-core @elastic/obs-know src/platform/packages/shared/kbn-esql-ast @elastic/kibana-esql src/platform/packages/shared/kbn-esql-utils @elastic/kibana-esql src/platform/packages/shared/kbn-esql-validation-autocomplete @elastic/kibana-esql +src/platform/packages/shared/kbn-esql-variables-types @elastic/kibana-esql src/platform/packages/shared/kbn-event-annotation-common @elastic/kibana-visualizations src/platform/packages/shared/kbn-event-annotation-components @elastic/kibana-visualizations src/platform/packages/shared/kbn-field-types @elastic/kibana-data-discovery @@ -894,7 +896,7 @@ x-pack/platform/plugins/shared/logs_shared @elastic/obs-ux-logs-team x-pack/platform/plugins/shared/maps @elastic/kibana-presentation x-pack/platform/plugins/shared/ml @elastic/ml-ui x-pack/platform/plugins/shared/notifications @elastic/appex-sharedux -x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant @elastic/obs-ai-assistant +x-pack/platform/plugins/shared/observability_ai_assistant @elastic/obs-ai-assistant x-pack/platform/plugins/shared/osquery @elastic/security-defend-workflows x-pack/platform/plugins/shared/rule_registry @elastic/response-ops @elastic/obs-ux-management-team x-pack/platform/plugins/shared/saved_objects_tagging @elastic/appex-sharedux @@ -953,7 +955,7 @@ x-pack/solutions/search/packages/kbn-ipynb @elastic/search-kibana x-pack/solutions/search/packages/kbn-search-api-keys-components @elastic/search-kibana x-pack/solutions/search/packages/kbn-search-api-keys-server @elastic/search-kibana x-pack/solutions/search/packages/kbn-search-index-documents @elastic/search-kibana -x-pack/solutions/search/packages/search/shared_ui @elastic/search-kibana +x-pack/solutions/search/packages/shared_ui @elastic/search-kibana x-pack/solutions/search/plugins/enterprise_search @elastic/search-kibana x-pack/solutions/search/plugins/search_assistant @elastic/search-kibana x-pack/solutions/search/plugins/search_connectors @elastic/search-kibana @@ -997,7 +999,6 @@ x-pack/solutions/security/plugins/cloud_defend @elastic/kibana-cloud-security-po x-pack/solutions/security/plugins/cloud_security_posture @elastic/kibana-cloud-security-posture x-pack/solutions/security/plugins/ecs_data_quality_dashboard @elastic/security-threat-hunting-explore x-pack/solutions/security/plugins/elastic_assistant @elastic/security-generative-ai -x-pack/solutions/security/plugins/kubernetes_security @elastic/kibana-cloud-security-posture x-pack/solutions/security/plugins/lists @elastic/security-detection-engine x-pack/solutions/security/plugins/security_solution @elastic/security-solution x-pack/solutions/security/plugins/security_solution_ess @elastic/security-solution @@ -1168,7 +1169,6 @@ src/platform/plugins/shared/discover/public/context_awareness/profile_providers/ /test/functional/fixtures/kbn_archiver/visualize.json @elastic/kibana-visualizations /test/functional/fixtures/kbn_archiver/managed_content.json @elastic/kibana-visualizations # Assigned per only use: https://github.com/elastic/kibana/blob/main/x-pack/test/functional/apps/managed_content/managed_content.ts#L38 /test/api_integration/fixtures/kbn_archiver/event_annotations/event_annotations.json @elastic/kibana-visualizations -/test/functional/page_objects/unified_search_page.ts @elastic/kibana-visualizations # Assigned per https://github.com/elastic/kibana/pull/200132#discussion_r1847188168 /test/functional/apps/getting_started/*.ts @elastic/kibana-visualizations # Assigned per https://github.com/elastic/kibana/pull/199767#discussion_r1840485031 /x-pack/test/upgrade/apps/graph @elastic/kibana-visualizations /x-pack/test/functional/page_objects/log_wrapper.ts @elastic/kibana-visualizations # Assigned per https://github.com/elastic/kibana/pull/36437 @@ -1460,6 +1460,7 @@ packages/kbn-monaco/src/esql @elastic/kibana-esql ### END Observability Plugins # Presentation +/test/functional/page_objects/unified_search_page.ts @elastic/kibana-presentation /test/functional/fixtures/kbn_archiver/dashboard_error_cases.json @elastic/kibana-presentation # Assigned per https://github.com/elastic/kibana/pull/201648#discussion_r1859020986 /x-pack/test/functional/es_archives/getting_started/shakespeare @elastic/kibana-presentation # Assigned per https://github.com/elastic/kibana/pull/201648#discussion_r1860319853 /x-pack/test/upgrade/screenshots @elastic/kibana-presentation @@ -2008,7 +2009,6 @@ x-pack/platform/plugins/private/cloud_integrations/cloud_full_story/server/confi # search /x-pack/test/functional/es_archives/data/search_sessions @elastic/search-kibana /x-pack/test/common/services/search_secure.ts @elastic/search-kibana -/test/functional/page_objects/unified_search_page.ts @elastic/search-kibana /test/functional/fixtures/kbn_archiver/ccs @elastic/search-kibana /test/functional/fixtures/kbn_archiver/annotation_listing_page_search.json @elastic/search-kibana /test/functional/fixtures/es_archiver/search/downsampled @elastic/search-kibana @@ -2546,6 +2546,7 @@ x-pack/test_serverless/api_integration/test_suites/security/cloud_security_postu ## CSP e2e tests x-pack/test/security_solution_cypress/cypress/e2e/cloud_security_posture/misconfiguration_contextual_flyout.cy.ts @elastic/kibana-cloud-security-posture x-pack/test/security_solution_cypress/cypress/e2e/cloud_security_posture/vulnerabilities_contextual_flyout.cy.ts @elastic/kibana-cloud-security-posture +x-pack/test/security_solution_cypress/cypress/e2e/asset_inventory @elastic/kibana-cloud-security-posture # Security Solution onboarding tour /x-pack/solutions/security/plugins/security_solution/public/common/components/guided_onboarding @elastic/security-threat-hunting-explore diff --git a/.github/paths-labeller.yml b/.github/paths-labeller.yml index 54936cdadc844..97c1b5f25c4a8 100644 --- a/.github/paths-labeller.yml +++ b/.github/paths-labeller.yml @@ -24,7 +24,7 @@ - 'x-pack/solutions/observability/plugins/synthetics/**/*.*' - 'x-pack/solutions/observability/plugins/exploratory_view/**/*.*' - 'Team:Obs AI Assistant': - - 'x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/**/*.*' + - 'x-pack/platform/plugins/shared/observability_ai_assistant/**/*.*' - 'x-pack/plugins/observability_solution/observability_ai_assistant_*/**/*.*' - 'x-pack/test/observability_ai_assistant_api_integration/**/*.*' - 'x-pack/test/observability_ai_assistant_functional/**/*.*' diff --git a/api_docs/actions.mdx b/api_docs/actions.mdx index a688f64015f8f..54e925a1d0b29 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: 2025-01-24 +date: 2025-01-27 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 90801f52f047a..e79e1c587e1c3 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: 2025-01-24 +date: 2025-01-27 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 1f8090f7294a1..3730b59bee0d3 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: 2025-01-24 +date: 2025-01-27 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 ed3527b565ad1..758bedbb3b126 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: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'aiops'] --- import aiopsObj from './aiops.devdocs.json'; diff --git a/api_docs/alerting.devdocs.json b/api_docs/alerting.devdocs.json index ee843ec440fdc..e8d79da744e06 100644 --- a/api_docs/alerting.devdocs.json +++ b/api_docs/alerting.devdocs.json @@ -4361,7 +4361,7 @@ "section": "def-common.FilterStateStore", "text": "FilterStateStore" }, - "; }> | undefined; } & { meta: Record; }>[]; }> | undefined; timeframe?: Readonly<{} & { days: (2 | 1 | 7 | 6 | 5 | 4 | 3)[]; hours: Readonly<{} & { start: string; end: string; }>; timezone: string; }> | undefined; } & {}> | undefined; uuid?: string | undefined; useAlertDataForTemplate?: boolean | undefined; } & { params: Record; id: string; group: string; }> | Readonly<{ actionTypeId?: string | undefined; uuid?: string | undefined; } & { params: Record; id: string; }>)[]; field: \"actions\"; operation: \"add\" | \"set\"; }> | Readonly<{} & { value: Readonly<{} & { interval: string; }>; field: \"schedule\"; operation: \"set\"; }> | Readonly<{} & { value: string | null; field: \"throttle\"; operation: \"set\"; }> | Readonly<{} & { value: \"onActionGroupChange\" | \"onActiveAlert\" | \"onThrottleInterval\"; field: \"notifyWhen\"; operation: \"set\"; }> | Readonly<{} & { value: Readonly<{ id?: string | undefined; } & { duration: number; rRule: Readonly<{ count?: number | undefined; interval?: number | undefined; freq?: 0 | 2 | 1 | 3 | undefined; until?: string | undefined; byweekday?: (\"MO\" | \"TU\" | \"WE\" | \"TH\" | \"FR\" | \"SA\" | \"SU\")[] | undefined; bymonthday?: number[] | undefined; bymonth?: number[] | undefined; } & { dtstart: string; tzid: string; }>; }>; field: \"snoozeSchedule\"; operation: \"set\"; }> | Readonly<{ value?: string[] | undefined; } & { field: \"snoozeSchedule\"; operation: \"delete\"; }> | Readonly<{} & { field: \"apiKey\"; operation: \"set\"; }>" + "; }> | undefined; } & { meta: Record; }>[]; }> | undefined; timeframe?: Readonly<{} & { days: (2 | 1 | 7 | 6 | 5 | 4 | 3)[]; hours: Readonly<{} & { start: string; end: string; }>; timezone: string; }> | undefined; } & {}> | undefined; uuid?: string | undefined; useAlertDataForTemplate?: boolean | undefined; } & { params: Record; id: string; group: string; }> | Readonly<{ actionTypeId?: string | undefined; uuid?: string | undefined; } & { params: Record; id: string; }>)[]; field: \"actions\"; operation: \"add\" | \"set\"; }> | Readonly<{} & { value: Readonly<{} & { interval: string; }>; field: \"schedule\"; operation: \"set\"; }> | Readonly<{} & { value: string | null; field: \"throttle\"; operation: \"set\"; }> | Readonly<{} & { value: \"onActionGroupChange\" | \"onActiveAlert\" | \"onThrottleInterval\"; field: \"notifyWhen\"; operation: \"set\"; }> | Readonly<{} & { value: Readonly<{ id?: string | undefined; } & { duration: number; rRule: Readonly<{ count?: number | undefined; interval?: number | undefined; freq?: 0 | 2 | 1 | 3 | undefined; until?: string | undefined; byweekday?: string[] | undefined; bymonthday?: number[] | undefined; bymonth?: number[] | undefined; } & { dtstart: string; tzid: string; }>; }>; field: \"snoozeSchedule\"; operation: \"set\"; }> | Readonly<{ value?: string[] | undefined; } & { field: \"snoozeSchedule\"; operation: \"delete\"; }> | Readonly<{} & { field: \"apiKey\"; operation: \"set\"; }>" ], "path": "x-pack/platform/plugins/shared/alerting/server/application/rule/methods/bulk_edit/types/bulk_edit_rules_options.ts", "deprecated": false, diff --git a/api_docs/alerting.mdx b/api_docs/alerting.mdx index be10f9acc17a2..646ee34c18325 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: 2025-01-24 +date: 2025-01-27 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 d0bcd0ee2954d..7fe736982bfcc 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: 2025-01-24 +date: 2025-01-27 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 c09440297c713..673ee02614691 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: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'apmDataAccess'] --- import apmDataAccessObj from './apm_data_access.devdocs.json'; diff --git a/api_docs/banners.mdx b/api_docs/banners.mdx index 29cd44ca2fc91..3c990dcd07b95 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: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'banners'] --- import bannersObj from './banners.devdocs.json'; diff --git a/api_docs/canvas.mdx b/api_docs/canvas.mdx index de280170f8808..4198fdf754284 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: 2025-01-24 +date: 2025-01-27 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 7e18890caf4c6..1f74ef8ba60c8 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: 2025-01-24 +date: 2025-01-27 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 c96e0a20193f7..57b425de50587 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: 2025-01-24 +date: 2025-01-27 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 c6195ff7cc4fb..7a521f75f1c10 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: 2025-01-24 +date: 2025-01-27 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 25ed68d0c2f6d..b0c2b96a0687d 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: 2025-01-24 +date: 2025-01-27 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 1a81d8224569e..dd9e9fff4c903 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: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloudDefend'] --- import cloudDefendObj from './cloud_defend.devdocs.json'; diff --git a/api_docs/cloud_security_posture.mdx b/api_docs/cloud_security_posture.mdx index bc020c5fa85dc..7b40306db936c 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: 2025-01-24 +date: 2025-01-27 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 63ecb84350502..706ccf3d01835 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: 2025-01-24 +date: 2025-01-27 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 9fa8ef9086a46..eb6057a8b14cb 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: 2025-01-24 +date: 2025-01-27 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 3d9b5b63d2b40..6d46af3c89b8f 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: 2025-01-24 +date: 2025-01-27 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 cb18512695a26..16aa89342644c 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: 2025-01-24 +date: 2025-01-27 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 e2cd9224472eb..51f933561dd52 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: 2025-01-24 +date: 2025-01-27 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 926ca3ad45f1d..626034b15707b 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: 2025-01-24 +date: 2025-01-27 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 614bacfe4ea67..883dbb83383e5 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: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'data'] --- import dataObj from './data.devdocs.json'; diff --git a/api_docs/data_quality.mdx b/api_docs/data_quality.mdx index 919e7364ee36a..51534b6b5b91e 100644 --- a/api_docs/data_quality.mdx +++ b/api_docs/data_quality.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataQuality title: "dataQuality" image: https://source.unsplash.com/400x175/?github description: API docs for the dataQuality plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataQuality'] --- import dataQualityObj from './data_quality.devdocs.json'; diff --git a/api_docs/data_query.mdx b/api_docs/data_query.mdx index 05a369b41e110..6ae7fa06a5865 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: 2025-01-24 +date: 2025-01-27 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 83cfc72e79ffe..172187181d5ec 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: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'data.search'] --- import dataSearchObj from './data_search.devdocs.json'; diff --git a/api_docs/data_usage.mdx b/api_docs/data_usage.mdx index 5820492f4e459..384f8e9bf8be7 100644 --- a/api_docs/data_usage.mdx +++ b/api_docs/data_usage.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataUsage title: "dataUsage" image: https://source.unsplash.com/400x175/?github description: API docs for the dataUsage plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataUsage'] --- import dataUsageObj from './data_usage.devdocs.json'; diff --git a/api_docs/data_view_editor.mdx b/api_docs/data_view_editor.mdx index 5bf1b01d68585..a8f62fe9f7c32 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: 2025-01-24 +date: 2025-01-27 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 86f1f93e73d94..c508cbf927da1 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: 2025-01-24 +date: 2025-01-27 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 34a5eae2b7e79..b5b924939c0f2 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: 2025-01-24 +date: 2025-01-27 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 43d705df245f7..842864e5b44b0 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: 2025-01-24 +date: 2025-01-27 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 332309320d48d..f32b6b56068d3 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: 2025-01-24 +date: 2025-01-27 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 4c45ac59d18a5..0d795da566aaa 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: 2025-01-24 +date: 2025-01-27 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 611b50a4fe841..73d29edffc9be 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: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- diff --git a/api_docs/deprecations_by_plugin.mdx b/api_docs/deprecations_by_plugin.mdx index 903d25102621f..40e0709a2b033 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: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- @@ -1140,8 +1140,8 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | Deprecated API | Reference location(s) | Remove By | | ---------------|-----------|-----------| | | [request_handler_context.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/saved_objects_tagging/server/request_handler_context.ts#:~:text=authz) | - | -| | [get_table_column_definition.tsx](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/saved_objects_tagging/public/ui_api/get_table_column_definition.tsx#:~:text=SavedObject), [get_table_column_definition.tsx](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/saved_objects_tagging/public/ui_api/get_table_column_definition.tsx#:~:text=SavedObject), [get_table_column_definition.tsx](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/saved_objects_tagging/public/ui_api/get_table_column_definition.tsx#:~:text=SavedObject), [types.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/saved_objects_tagging/common/types.ts#:~:text=SavedObject), [types.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/saved_objects_tagging/common/types.ts#:~:text=SavedObject), [utils.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/saved_objects_tagging/public/utils.ts#:~:text=SavedObject), [utils.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/saved_objects_tagging/public/utils.ts#:~:text=SavedObject), [utils.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/saved_objects_tagging/public/utils.test.ts#:~:text=SavedObject), [utils.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/saved_objects_tagging/public/utils.test.ts#:~:text=SavedObject), [utils.test.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/saved_objects_tagging/public/utils.test.ts#:~:text=SavedObject)+ 3 more | - | -| | [get_table_column_definition.tsx](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/saved_objects_tagging/public/ui_api/get_table_column_definition.tsx#:~:text=SavedObjectReference), [get_table_column_definition.tsx](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/saved_objects_tagging/public/ui_api/get_table_column_definition.tsx#:~:text=SavedObjectReference), [references.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/saved_objects_tagging/common/references.ts#:~:text=SavedObjectReference), [references.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/saved_objects_tagging/common/references.ts#:~:text=SavedObjectReference), [references.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/saved_objects_tagging/common/references.ts#:~:text=SavedObjectReference), [references.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/saved_objects_tagging/common/references.ts#:~:text=SavedObjectReference), [references.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/saved_objects_tagging/common/references.ts#:~:text=SavedObjectReference), [references.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/saved_objects_tagging/common/references.ts#:~:text=SavedObjectReference), [references.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/saved_objects_tagging/common/references.ts#:~:text=SavedObjectReference), [utils.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/saved_objects_tagging/public/utils.ts#:~:text=SavedObjectReference)+ 12 more | - | +| | [get_table_column_definition.tsx](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/saved_objects_tagging/public/ui_api/get_table_column_definition.tsx#:~:text=SavedObject), [get_table_column_definition.tsx](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/saved_objects_tagging/public/ui_api/get_table_column_definition.tsx#:~:text=SavedObject), [get_table_column_definition.tsx](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/saved_objects_tagging/public/ui_api/get_table_column_definition.tsx#:~:text=SavedObject), [types.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/saved_objects_tagging/common/types.ts#:~:text=SavedObject), [types.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/saved_objects_tagging/common/types.ts#:~:text=SavedObject), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/saved_objects_tagging/common/test_utils/index.ts#:~:text=SavedObject), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/saved_objects_tagging/common/test_utils/index.ts#:~:text=SavedObject), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/saved_objects_tagging/common/test_utils/index.ts#:~:text=SavedObject) | - | +| | [get_table_column_definition.tsx](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/saved_objects_tagging/public/ui_api/get_table_column_definition.tsx#:~:text=SavedObjectReference), [get_table_column_definition.tsx](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/saved_objects_tagging/public/ui_api/get_table_column_definition.tsx#:~:text=SavedObjectReference), [tag_list.tsx](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/saved_objects_tagging/public/components/connected/tag_list.tsx#:~:text=SavedObjectReference), [tag_list.tsx](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/saved_objects_tagging/public/components/connected/tag_list.tsx#:~:text=SavedObjectReference), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/saved_objects_tagging/common/test_utils/index.ts#:~:text=SavedObjectReference), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/saved_objects_tagging/common/test_utils/index.ts#:~:text=SavedObjectReference) | - | | | [tag.ts](https://github.com/elastic/kibana/tree/main/x-pack/platform/plugins/shared/saved_objects_tagging/server/saved_objects/tag.ts#:~:text=convertToMultiNamespaceTypeVersion) | - | diff --git a/api_docs/deprecations_by_team.mdx b/api_docs/deprecations_by_team.mdx index a3ebe7dcf5317..8f1b3d93aad43 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: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- diff --git a/api_docs/dev_tools.mdx b/api_docs/dev_tools.mdx index 6b5c6e4afe0ff..ab16c43c4416e 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: 2025-01-24 +date: 2025-01-27 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 3694c27c7e8f3..da8d007f3c40c 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: 2025-01-24 +date: 2025-01-27 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 c5054cea91e7a..def9b40abd23e 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: 2025-01-24 +date: 2025-01-27 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 b7f915b1ccb2c..6ac936464fe34 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: 2025-01-24 +date: 2025-01-27 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 b78455533f0a7..e6530b6d8121f 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: 2025-01-24 +date: 2025-01-27 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 34ed786ec2ac8..863dbdf5fc1e1 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: 2025-01-24 +date: 2025-01-27 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 7d0029c3737d5..1744566cac016 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: 2025-01-24 +date: 2025-01-27 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 14e4e579f568f..acce0b0af1ad8 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: 2025-01-24 +date: 2025-01-27 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 879371b0d15d0..1afd4dfa15baf 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: 2025-01-24 +date: 2025-01-27 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 89d55e4f071eb..52a57b064fee2 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: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'enterpriseSearch'] --- import enterpriseSearchObj from './enterprise_search.devdocs.json'; diff --git a/api_docs/entities_data_access.mdx b/api_docs/entities_data_access.mdx index 211b47e64ea28..8f25e67393de3 100644 --- a/api_docs/entities_data_access.mdx +++ b/api_docs/entities_data_access.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/entitiesDataAccess title: "entitiesDataAccess" image: https://source.unsplash.com/400x175/?github description: API docs for the entitiesDataAccess plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'entitiesDataAccess'] --- import entitiesDataAccessObj from './entities_data_access.devdocs.json'; diff --git a/api_docs/entity_manager.mdx b/api_docs/entity_manager.mdx index 3e7ed814b73f0..b9f29a2a3260e 100644 --- a/api_docs/entity_manager.mdx +++ b/api_docs/entity_manager.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/entityManager title: "entityManager" image: https://source.unsplash.com/400x175/?github description: API docs for the entityManager plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'entityManager'] --- import entityManagerObj from './entity_manager.devdocs.json'; diff --git a/api_docs/es_ui_shared.mdx b/api_docs/es_ui_shared.mdx index b2f370d2d020d..829845d6cdaf3 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: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'esUiShared'] --- import esUiSharedObj from './es_ui_shared.devdocs.json'; diff --git a/api_docs/esql.mdx b/api_docs/esql.mdx index f195c72ad184c..686822d084fe9 100644 --- a/api_docs/esql.mdx +++ b/api_docs/esql.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/esql title: "esql" image: https://source.unsplash.com/400x175/?github description: API docs for the esql plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'esql'] --- import esqlObj from './esql.devdocs.json'; diff --git a/api_docs/esql_data_grid.mdx b/api_docs/esql_data_grid.mdx index d922b298d527d..28393012dbbfb 100644 --- a/api_docs/esql_data_grid.mdx +++ b/api_docs/esql_data_grid.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/esqlDataGrid title: "esqlDataGrid" image: https://source.unsplash.com/400x175/?github description: API docs for the esqlDataGrid plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'esqlDataGrid'] --- import esqlDataGridObj from './esql_data_grid.devdocs.json'; diff --git a/api_docs/event_annotation.mdx b/api_docs/event_annotation.mdx index 594424e5a42bd..8d28c1cc36d2c 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: 2025-01-24 +date: 2025-01-27 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 42231d02c1988..31f696b5bd714 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: 2025-01-24 +date: 2025-01-27 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 6ceded62a9695..aacbf974c7d17 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: 2025-01-24 +date: 2025-01-27 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 de2e7d630a7c5..f0718f159b4ad 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: 2025-01-24 +date: 2025-01-27 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 253725eb2c119..a63610e52a08f 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: 2025-01-24 +date: 2025-01-27 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 a39642cf397e6..2c636da20e52c 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: 2025-01-24 +date: 2025-01-27 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 10fd590ea1f59..ff6347937e45a 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: 2025-01-24 +date: 2025-01-27 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 1df16d1b2bdfa..8f0ee9fb8894f 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: 2025-01-24 +date: 2025-01-27 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 4886429dc44ea..c47aa20a93c00 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: 2025-01-24 +date: 2025-01-27 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 e73c7054ba8f8..560f3cacf64c6 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: 2025-01-24 +date: 2025-01-27 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 6f05ee1650569..64c38b9995f45 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: 2025-01-24 +date: 2025-01-27 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 a0e667ec72514..15a63a90a9d2f 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: 2025-01-24 +date: 2025-01-27 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 e860d5ce9da57..233fd4d32afde 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: 2025-01-24 +date: 2025-01-27 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 b4ab49a17852a..2bbb2433a0938 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: 2025-01-24 +date: 2025-01-27 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 930dafa6c1023..a247f7b900c57 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: 2025-01-24 +date: 2025-01-27 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 d91b0cbd94971..47a29bc70c6d3 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: 2025-01-24 +date: 2025-01-27 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 122c65ee127e1..9952e071866ca 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: 2025-01-24 +date: 2025-01-27 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 4854c8ee9cd63..8eabd3c4c9826 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: 2025-01-24 +date: 2025-01-27 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 f6a9ba6656981..475089b48c5bf 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: 2025-01-24 +date: 2025-01-27 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 d43b8c1317274..4bb583ca70451 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: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'fieldFormats'] --- import fieldFormatsObj from './field_formats.devdocs.json'; diff --git a/api_docs/fields_metadata.mdx b/api_docs/fields_metadata.mdx index 3bc5284cdf168..6d49782ff7724 100644 --- a/api_docs/fields_metadata.mdx +++ b/api_docs/fields_metadata.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/fieldsMetadata title: "fieldsMetadata" image: https://source.unsplash.com/400x175/?github description: API docs for the fieldsMetadata plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'fieldsMetadata'] --- import fieldsMetadataObj from './fields_metadata.devdocs.json'; diff --git a/api_docs/file_upload.mdx b/api_docs/file_upload.mdx index ea3cdb270d82f..4339c7b23203c 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: 2025-01-24 +date: 2025-01-27 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 e2ba3d6bcf7b4..57abceb6937d1 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: 2025-01-24 +date: 2025-01-27 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 1c19672a291b2..3973869dee249 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: 2025-01-24 +date: 2025-01-27 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 0f5c79189e55d..cca44709f50e8 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: 2025-01-24 +date: 2025-01-27 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 2ad41ca973a79..f68612d7c4665 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: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'globalSearch'] --- import globalSearchObj from './global_search.devdocs.json'; diff --git a/api_docs/guided_onboarding.devdocs.json b/api_docs/guided_onboarding.devdocs.json index e0a75c92a9046..5deaa6df2c60f 100644 --- a/api_docs/guided_onboarding.devdocs.json +++ b/api_docs/guided_onboarding.devdocs.json @@ -1257,14 +1257,6 @@ "section": "def-common.GuideConfig", "text": "GuideConfig" }, - "; appSearch: ", - { - "pluginId": "@kbn/guided-onboarding", - "scope": "common", - "docId": "kibKbnGuidedOnboardingPluginApi", - "section": "def-common.GuideConfig", - "text": "GuideConfig" - }, "; websiteSearch: ", { "pluginId": "@kbn/guided-onboarding", diff --git a/api_docs/guided_onboarding.mdx b/api_docs/guided_onboarding.mdx index b3b9f6e7d51ef..22b51f84db678 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: 2025-01-24 +date: 2025-01-27 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 417b969db09cc..8621e5453f24e 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: 2025-01-24 +date: 2025-01-27 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 a275145867471..bb0ca992599d2 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: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'imageEmbeddable'] --- import imageEmbeddableObj from './image_embeddable.devdocs.json'; diff --git a/api_docs/index_management.mdx b/api_docs/index_management.mdx index a12db83e8401a..59afd8cc4191c 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: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'indexManagement'] --- import indexManagementObj from './index_management.devdocs.json'; diff --git a/api_docs/inference.mdx b/api_docs/inference.mdx index 3ae3b7b6571d6..5c59ca5288997 100644 --- a/api_docs/inference.mdx +++ b/api_docs/inference.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/inference title: "inference" image: https://source.unsplash.com/400x175/?github description: API docs for the inference plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'inference'] --- import inferenceObj from './inference.devdocs.json'; diff --git a/api_docs/inference_endpoint.mdx b/api_docs/inference_endpoint.mdx index 485adb364ac5e..8455780deec34 100644 --- a/api_docs/inference_endpoint.mdx +++ b/api_docs/inference_endpoint.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/inferenceEndpoint title: "inferenceEndpoint" image: https://source.unsplash.com/400x175/?github description: API docs for the inferenceEndpoint plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'inferenceEndpoint'] --- import inferenceEndpointObj from './inference_endpoint.devdocs.json'; diff --git a/api_docs/infra.mdx b/api_docs/infra.mdx index 21ff6775aafd6..3bef7a0f89af2 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: 2025-01-24 +date: 2025-01-27 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 825186a76be93..81b15d10ede14 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: 2025-01-24 +date: 2025-01-27 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 40fd73b52925d..d9bffd8d8699d 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: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'inspector'] --- import inspectorObj from './inspector.devdocs.json'; diff --git a/api_docs/integration_assistant.mdx b/api_docs/integration_assistant.mdx index 5a24fdedadaa1..984bcc80837f1 100644 --- a/api_docs/integration_assistant.mdx +++ b/api_docs/integration_assistant.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/integrationAssistant title: "integrationAssistant" image: https://source.unsplash.com/400x175/?github description: API docs for the integrationAssistant plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'integrationAssistant'] --- import integrationAssistantObj from './integration_assistant.devdocs.json'; diff --git a/api_docs/interactive_setup.mdx b/api_docs/interactive_setup.mdx index 48c1b432ef054..fd72b6671263e 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: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'interactiveSetup'] --- import interactiveSetupObj from './interactive_setup.devdocs.json'; diff --git a/api_docs/inventory.mdx b/api_docs/inventory.mdx index 4327e00ebea14..6365b785df100 100644 --- a/api_docs/inventory.mdx +++ b/api_docs/inventory.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/inventory title: "inventory" image: https://source.unsplash.com/400x175/?github description: API docs for the inventory plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'inventory'] --- import inventoryObj from './inventory.devdocs.json'; diff --git a/api_docs/investigate.mdx b/api_docs/investigate.mdx index 8637ee21e2cfc..8a49818b643e0 100644 --- a/api_docs/investigate.mdx +++ b/api_docs/investigate.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/investigate title: "investigate" image: https://source.unsplash.com/400x175/?github description: API docs for the investigate plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'investigate'] --- import investigateObj from './investigate.devdocs.json'; diff --git a/api_docs/investigate_app.mdx b/api_docs/investigate_app.mdx index d6c3c208024e2..f2ca52f560c57 100644 --- a/api_docs/investigate_app.mdx +++ b/api_docs/investigate_app.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/investigateApp title: "investigateApp" image: https://source.unsplash.com/400x175/?github description: API docs for the investigateApp plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'investigateApp'] --- import investigateAppObj from './investigate_app.devdocs.json'; diff --git a/api_docs/kbn_actions_types.mdx b/api_docs/kbn_actions_types.mdx index d5cb9b4f47fdc..41d34876bc533 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: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/actions-types'] --- import kbnActionsTypesObj from './kbn_actions_types.devdocs.json'; diff --git a/api_docs/kbn_ai_assistant.mdx b/api_docs/kbn_ai_assistant.mdx index 23d7c35de6ca7..3f33ba091ca72 100644 --- a/api_docs/kbn_ai_assistant.mdx +++ b/api_docs/kbn_ai_assistant.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ai-assistant title: "@kbn/ai-assistant" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ai-assistant plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ai-assistant'] --- import kbnAiAssistantObj from './kbn_ai_assistant.devdocs.json'; diff --git a/api_docs/kbn_ai_assistant_common.mdx b/api_docs/kbn_ai_assistant_common.mdx index 34a48041b4b70..1dfa6591fbee6 100644 --- a/api_docs/kbn_ai_assistant_common.mdx +++ b/api_docs/kbn_ai_assistant_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ai-assistant-common title: "@kbn/ai-assistant-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ai-assistant-common plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ai-assistant-common'] --- import kbnAiAssistantCommonObj from './kbn_ai_assistant_common.devdocs.json'; diff --git a/api_docs/kbn_ai_assistant_icon.mdx b/api_docs/kbn_ai_assistant_icon.mdx index c358adcae328d..99fe8a5d18171 100644 --- a/api_docs/kbn_ai_assistant_icon.mdx +++ b/api_docs/kbn_ai_assistant_icon.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ai-assistant-icon title: "@kbn/ai-assistant-icon" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ai-assistant-icon plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ai-assistant-icon'] --- import kbnAiAssistantIconObj from './kbn_ai_assistant_icon.devdocs.json'; diff --git a/api_docs/kbn_aiops_components.mdx b/api_docs/kbn_aiops_components.mdx index 583542a146d17..184e68ca31ae8 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: 2025-01-24 +date: 2025-01-27 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 7c0d0e00852a4..4ecce080bb492 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: 2025-01-24 +date: 2025-01-27 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 73ddf389ff452..bbe9a3dc15976 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: 2025-01-24 +date: 2025-01-27 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 ea4124bb3eff2..92de4fffd56a2 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: 2025-01-24 +date: 2025-01-27 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_comparators.mdx b/api_docs/kbn_alerting_comparators.mdx index b9b1c8e0216ba..a8d641ba4dd9e 100644 --- a/api_docs/kbn_alerting_comparators.mdx +++ b/api_docs/kbn_alerting_comparators.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-alerting-comparators title: "@kbn/alerting-comparators" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/alerting-comparators plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/alerting-comparators'] --- import kbnAlertingComparatorsObj from './kbn_alerting_comparators.devdocs.json'; diff --git a/api_docs/kbn_alerting_state_types.mdx b/api_docs/kbn_alerting_state_types.mdx index 5394c46f2ff88..977f412b1cd73 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: 2025-01-24 +date: 2025-01-27 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 d17219d10dc77..8064d5ba2ad87 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: 2025-01-24 +date: 2025-01-27 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 54fba58886fd7..1f0b5621ceb9a 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: 2025-01-24 +date: 2025-01-27 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_grouping.mdx b/api_docs/kbn_alerts_grouping.mdx index 978a0e16daf32..abe5ed6e3e3a8 100644 --- a/api_docs/kbn_alerts_grouping.mdx +++ b/api_docs/kbn_alerts_grouping.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-alerts-grouping title: "@kbn/alerts-grouping" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/alerts-grouping plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/alerts-grouping'] --- import kbnAlertsGroupingObj from './kbn_alerts_grouping.devdocs.json'; diff --git a/api_docs/kbn_alerts_ui_shared.mdx b/api_docs/kbn_alerts_ui_shared.mdx index 9a0558f36eed3..58cada75c5aa7 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: 2025-01-24 +date: 2025-01-27 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 1c36847e62aa7..64c96365e37a6 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: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics'] --- import kbnAnalyticsObj from './kbn_analytics.devdocs.json'; diff --git a/api_docs/kbn_analytics_collection_utils.mdx b/api_docs/kbn_analytics_collection_utils.mdx index c18a4137cdb67..dbd6ff26bc245 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: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-collection-utils'] --- import kbnAnalyticsCollectionUtilsObj from './kbn_analytics_collection_utils.devdocs.json'; diff --git a/api_docs/kbn_apm_config_loader.mdx b/api_docs/kbn_apm_config_loader.mdx index aff16acb7df44..149849c241d6e 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: 2025-01-24 +date: 2025-01-27 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 2cccbf54d1ef1..0bdb49b789d6b 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: 2025-01-24 +date: 2025-01-27 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 df153e520cf7d..6b59b991ee8ce 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: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/apm-synthtrace'] --- import kbnApmSynthtraceObj from './kbn_apm_synthtrace.devdocs.json'; diff --git a/api_docs/kbn_apm_synthtrace_client.mdx b/api_docs/kbn_apm_synthtrace_client.mdx index feffe4f0183a0..4c5a2b170f4c6 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: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/apm-synthtrace-client'] --- import kbnApmSynthtraceClientObj from './kbn_apm_synthtrace_client.devdocs.json'; diff --git a/api_docs/kbn_apm_types.mdx b/api_docs/kbn_apm_types.mdx index 3cc7a7d9567e7..a7b416ea72c97 100644 --- a/api_docs/kbn_apm_types.mdx +++ b/api_docs/kbn_apm_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-apm-types title: "@kbn/apm-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/apm-types plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/apm-types'] --- import kbnApmTypesObj from './kbn_apm_types.devdocs.json'; diff --git a/api_docs/kbn_apm_utils.mdx b/api_docs/kbn_apm_utils.mdx index 8dc49aa441d21..7c0c1beb5f4d8 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: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/apm-utils'] --- import kbnApmUtilsObj from './kbn_apm_utils.devdocs.json'; diff --git a/api_docs/kbn_avc_banner.mdx b/api_docs/kbn_avc_banner.mdx index be4326b309a88..55050c4556d26 100644 --- a/api_docs/kbn_avc_banner.mdx +++ b/api_docs/kbn_avc_banner.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-avc-banner title: "@kbn/avc-banner" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/avc-banner plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/avc-banner'] --- import kbnAvcBannerObj from './kbn_avc_banner.devdocs.json'; diff --git a/api_docs/kbn_axe_config.mdx b/api_docs/kbn_axe_config.mdx index 3757ed2e13438..c766ed931b53e 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: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/axe-config'] --- import kbnAxeConfigObj from './kbn_axe_config.devdocs.json'; diff --git a/api_docs/kbn_calculate_auto.mdx b/api_docs/kbn_calculate_auto.mdx index 39b69bf877a8e..0f7c25226e023 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: 2025-01-24 +date: 2025-01-27 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 1a757dc163113..5059583a5aeb6 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: 2025-01-24 +date: 2025-01-27 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 1c23a096c12c6..e70f358783652 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: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/cases-components'] --- import kbnCasesComponentsObj from './kbn_cases_components.devdocs.json'; diff --git a/api_docs/kbn_cbor.mdx b/api_docs/kbn_cbor.mdx index e6bc2e1055f7e..f8c03b01fded9 100644 --- a/api_docs/kbn_cbor.mdx +++ b/api_docs/kbn_cbor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-cbor title: "@kbn/cbor" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/cbor plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/cbor'] --- import kbnCborObj from './kbn_cbor.devdocs.json'; diff --git a/api_docs/kbn_cell_actions.mdx b/api_docs/kbn_cell_actions.mdx index ef485aad1209a..a53767c0cdd1f 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: 2025-01-24 +date: 2025-01-27 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 d7b4e86497c5c..bbecb9b40f5dd 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: 2025-01-24 +date: 2025-01-27 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 9ea7d7a0e8c27..6dda341fa4304 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: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/chart-icons'] --- import kbnChartIconsObj from './kbn_chart_icons.devdocs.json'; diff --git a/api_docs/kbn_charts_theme.mdx b/api_docs/kbn_charts_theme.mdx index 56257a85deae8..ccbc081aa32d7 100644 --- a/api_docs/kbn_charts_theme.mdx +++ b/api_docs/kbn_charts_theme.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-charts-theme title: "@kbn/charts-theme" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/charts-theme plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/charts-theme'] --- import kbnChartsThemeObj from './kbn_charts_theme.devdocs.json'; diff --git a/api_docs/kbn_ci_stats_core.mdx b/api_docs/kbn_ci_stats_core.mdx index e9eb6b6ca4009..379952e457e2f 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: 2025-01-24 +date: 2025-01-27 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 393977599de0d..4b2803eb5a286 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: 2025-01-24 +date: 2025-01-27 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 fe521b5363b02..905126cb8531d 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: 2025-01-24 +date: 2025-01-27 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 fe308c2f25d7f..2d2d00e692757 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: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/cli-dev-mode'] --- import kbnCliDevModeObj from './kbn_cli_dev_mode.devdocs.json'; diff --git a/api_docs/kbn_cloud_security_posture.mdx b/api_docs/kbn_cloud_security_posture.mdx index 9ad9090dab1c6..c0ae870641ade 100644 --- a/api_docs/kbn_cloud_security_posture.mdx +++ b/api_docs/kbn_cloud_security_posture.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-cloud-security-posture title: "@kbn/cloud-security-posture" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/cloud-security-posture plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/cloud-security-posture'] --- import kbnCloudSecurityPostureObj from './kbn_cloud_security_posture.devdocs.json'; diff --git a/api_docs/kbn_cloud_security_posture_common.mdx b/api_docs/kbn_cloud_security_posture_common.mdx index c2638cc8b4241..1c5b94e02fa4c 100644 --- a/api_docs/kbn_cloud_security_posture_common.mdx +++ b/api_docs/kbn_cloud_security_posture_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-cloud-security-posture-common title: "@kbn/cloud-security-posture-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/cloud-security-posture-common plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/cloud-security-posture-common'] --- import kbnCloudSecurityPostureCommonObj from './kbn_cloud_security_posture_common.devdocs.json'; diff --git a/api_docs/kbn_cloud_security_posture_graph.mdx b/api_docs/kbn_cloud_security_posture_graph.mdx index 7eaeecea318da..5eb6c5212d836 100644 --- a/api_docs/kbn_cloud_security_posture_graph.mdx +++ b/api_docs/kbn_cloud_security_posture_graph.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-cloud-security-posture-graph title: "@kbn/cloud-security-posture-graph" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/cloud-security-posture-graph plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/cloud-security-posture-graph'] --- import kbnCloudSecurityPostureGraphObj from './kbn_cloud_security_posture_graph.devdocs.json'; diff --git a/api_docs/kbn_code_editor.mdx b/api_docs/kbn_code_editor.mdx index aa0c2e59b05ed..74d6af8ab79fe 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: 2025-01-24 +date: 2025-01-27 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 317e7d6c47a1e..1e4e21d95eca2 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: 2025-01-24 +date: 2025-01-27 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 80b3d0e1ac76c..a6592bd8df7ba 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: 2025-01-24 +date: 2025-01-27 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 8ec6854bfb187..ef7ea6f963e7f 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: 2025-01-24 +date: 2025-01-27 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 b8942cb101850..deaccb138a108 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: 2025-01-24 +date: 2025-01-27 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 a9f4bed123d5c..b0b3b14b9f412 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: 2025-01-24 +date: 2025-01-27 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 c408d9be7b08a..1df1701f47411 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: 2025-01-24 +date: 2025-01-27 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 65443c59d835f..b23329e00916f 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: 2025-01-24 +date: 2025-01-27 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_content_insights_public.mdx b/api_docs/kbn_content_management_content_insights_public.mdx index 283d9f81698d1..2fa27fca46a72 100644 --- a/api_docs/kbn_content_management_content_insights_public.mdx +++ b/api_docs/kbn_content_management_content_insights_public.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-content-management-content-insights-public title: "@kbn/content-management-content-insights-public" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/content-management-content-insights-public plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/content-management-content-insights-public'] --- import kbnContentManagementContentInsightsPublicObj from './kbn_content_management_content_insights_public.devdocs.json'; diff --git a/api_docs/kbn_content_management_content_insights_server.mdx b/api_docs/kbn_content_management_content_insights_server.mdx index 8a5e6396f95ef..92ea0c2e25398 100644 --- a/api_docs/kbn_content_management_content_insights_server.mdx +++ b/api_docs/kbn_content_management_content_insights_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-content-management-content-insights-server title: "@kbn/content-management-content-insights-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/content-management-content-insights-server plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/content-management-content-insights-server'] --- import kbnContentManagementContentInsightsServerObj from './kbn_content_management_content_insights_server.devdocs.json'; diff --git a/api_docs/kbn_content_management_favorites_common.mdx b/api_docs/kbn_content_management_favorites_common.mdx index 4c7e3eb09c91b..43dcd2fb8461d 100644 --- a/api_docs/kbn_content_management_favorites_common.mdx +++ b/api_docs/kbn_content_management_favorites_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-content-management-favorites-common title: "@kbn/content-management-favorites-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/content-management-favorites-common plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/content-management-favorites-common'] --- import kbnContentManagementFavoritesCommonObj from './kbn_content_management_favorites_common.devdocs.json'; diff --git a/api_docs/kbn_content_management_favorites_public.mdx b/api_docs/kbn_content_management_favorites_public.mdx index ec464288922af..29ebaace1c4ca 100644 --- a/api_docs/kbn_content_management_favorites_public.mdx +++ b/api_docs/kbn_content_management_favorites_public.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-content-management-favorites-public title: "@kbn/content-management-favorites-public" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/content-management-favorites-public plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/content-management-favorites-public'] --- import kbnContentManagementFavoritesPublicObj from './kbn_content_management_favorites_public.devdocs.json'; diff --git a/api_docs/kbn_content_management_favorites_server.mdx b/api_docs/kbn_content_management_favorites_server.mdx index c6327a742df1a..4b8df75ff5346 100644 --- a/api_docs/kbn_content_management_favorites_server.mdx +++ b/api_docs/kbn_content_management_favorites_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-content-management-favorites-server title: "@kbn/content-management-favorites-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/content-management-favorites-server plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/content-management-favorites-server'] --- import kbnContentManagementFavoritesServerObj from './kbn_content_management_favorites_server.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 f1b12bf2dd600..003a349794b73 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: 2025-01-24 +date: 2025-01-27 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 9a643ac9db710..473796d1ea14f 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: 2025-01-24 +date: 2025-01-27 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 046cbdeddead8..ef8359c50f51f 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: 2025-01-24 +date: 2025-01-27 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 22f2f4cf9e7d9..3582ced22869e 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: 2025-01-24 +date: 2025-01-27 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_user_profiles.mdx b/api_docs/kbn_content_management_user_profiles.mdx index 9e6e8f7d549bf..9fc1589225d07 100644 --- a/api_docs/kbn_content_management_user_profiles.mdx +++ b/api_docs/kbn_content_management_user_profiles.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-content-management-user-profiles title: "@kbn/content-management-user-profiles" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/content-management-user-profiles plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/content-management-user-profiles'] --- import kbnContentManagementUserProfilesObj from './kbn_content_management_user_profiles.devdocs.json'; diff --git a/api_docs/kbn_content_management_utils.mdx b/api_docs/kbn_content_management_utils.mdx index c2ebfbe16eb2e..2e1d2ea9d316b 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: 2025-01-24 +date: 2025-01-27 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 f0ce02d7ccc96..6936484e63a90 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: 2025-01-24 +date: 2025-01-27 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 4934ea2d05141..fea39b3726493 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: 2025-01-24 +date: 2025-01-27 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 451a27c2f48ca..391d939410213 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: 2025-01-24 +date: 2025-01-27 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 e9433f87a0bdc..42add518bd870 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: 2025-01-24 +date: 2025-01-27 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 f9c3d5cc78e67..c7f39bcc25a0b 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: 2025-01-24 +date: 2025-01-27 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 4db4d1bbe16aa..6563615b6f020 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: 2025-01-24 +date: 2025-01-27 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 ec951a26e94bf..01815cf11ddc7 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: 2025-01-24 +date: 2025-01-27 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 518ed303f4df1..facd758b0ac08 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: 2025-01-24 +date: 2025-01-27 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 4907a52e20770..e84c4762cf12d 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: 2025-01-24 +date: 2025-01-27 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 4b04117029f59..6ca8748f9ab1e 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: 2025-01-24 +date: 2025-01-27 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 d62ceaf912159..0361d89da529e 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: 2025-01-24 +date: 2025-01-27 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 fa86de7c0d69e..b5ab3f2def898 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: 2025-01-24 +date: 2025-01-27 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 8a69088a2be7a..d6bd87197d52a 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: 2025-01-24 +date: 2025-01-27 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 bd455cee3c0ce..fb20587288724 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: 2025-01-24 +date: 2025-01-27 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 978d4cb9f51c4..68bd2d97a3827 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: 2025-01-24 +date: 2025-01-27 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 752009bfd16a7..9036c67ec4f74 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: 2025-01-24 +date: 2025-01-27 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 3c4adc71b948a..2df3b9be7bf82 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: 2025-01-24 +date: 2025-01-27 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 00a2bf5247992..3587ca77de3d3 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: 2025-01-24 +date: 2025-01-27 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 17bda334ca7c5..2fb83a9907579 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: 2025-01-24 +date: 2025-01-27 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 b330a870fbe88..d940235e55526 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: 2025-01-24 +date: 2025-01-27 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 e7ffee0a546d6..1b60ecdf07071 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: 2025-01-24 +date: 2025-01-27 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 67149b6c7cebd..e168697536eb9 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: 2025-01-24 +date: 2025-01-27 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 78e6129b84262..3a569ce7f2176 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: 2025-01-24 +date: 2025-01-27 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 ad7062677a0af..3500fc42edde8 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: 2025-01-24 +date: 2025-01-27 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 e287d9feede50..9d7cb80193db5 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: 2025-01-24 +date: 2025-01-27 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 12d8260894318..495ae74557b9f 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: 2025-01-24 +date: 2025-01-27 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 381eca0b35877..64b3546427700 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: 2025-01-24 +date: 2025-01-27 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 1b70b9d77202f..401f3e434dadf 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: 2025-01-24 +date: 2025-01-27 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 c07cbe7acb2b3..3c707b10b3e05 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: 2025-01-24 +date: 2025-01-27 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 e6ab19d422bae..8876931da3a22 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: 2025-01-24 +date: 2025-01-27 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 67dc50ca857cd..4c1306386881e 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: 2025-01-24 +date: 2025-01-27 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 4ef0f95ea00d3..d43ccbea4c128 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: 2025-01-24 +date: 2025-01-27 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 cd0d13e633912..2b2d7ce0e9127 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: 2025-01-24 +date: 2025-01-27 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 63bffa6d7d8d6..ae1c2d8fbc457 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: 2025-01-24 +date: 2025-01-27 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 357f1f1bcfc7e..a9b23e9994b22 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: 2025-01-24 +date: 2025-01-27 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 879213dc93ddd..b5abb8672934a 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: 2025-01-24 +date: 2025-01-27 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 99a4cbd01d90b..03822dc3a4efc 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: 2025-01-24 +date: 2025-01-27 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 e28997038a638..246b87fff1ee3 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: 2025-01-24 +date: 2025-01-27 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 3db9b155fe558..9857a63f5ff77 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: 2025-01-24 +date: 2025-01-27 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 89b544400c71e..9fb7903b3b1b6 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: 2025-01-24 +date: 2025-01-27 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 dcc68e9b06c43..6fa9eeb2d8ed7 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: 2025-01-24 +date: 2025-01-27 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 8e12a36855386..e64079a718e9b 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: 2025-01-24 +date: 2025-01-27 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 01be0bae5a10f..6bacb011c9076 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: 2025-01-24 +date: 2025-01-27 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 8fdd74232aa38..724d840ba4ebf 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: 2025-01-24 +date: 2025-01-27 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 5904bd544d360..b2509245e999f 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: 2025-01-24 +date: 2025-01-27 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 17faffb4e951a..711dbc32d1825 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: 2025-01-24 +date: 2025-01-27 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 b07a3c2a6e616..36f80df4d333b 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: 2025-01-24 +date: 2025-01-27 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 aabe4880cfe13..be38e272f6410 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: 2025-01-24 +date: 2025-01-27 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 6f0457af1ca08..f29642a725a19 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: 2025-01-24 +date: 2025-01-27 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 566c3506ab05f..a93e65029845b 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: 2025-01-24 +date: 2025-01-27 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 f791dd09175ee..f332b2aa8993a 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: 2025-01-24 +date: 2025-01-27 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 cca9138b62d69..472cfc9fd77ec 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: 2025-01-24 +date: 2025-01-27 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 7e8d5eb0920dd..9394a6eecf052 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: 2025-01-24 +date: 2025-01-27 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 062532368a303..5d825be23cb92 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: 2025-01-24 +date: 2025-01-27 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 b6e5214742897..59c035957702e 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: 2025-01-24 +date: 2025-01-27 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 66493c16675aa..d93025d8ccd57 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: 2025-01-24 +date: 2025-01-27 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 9a51e5a4c520d..84b955923a805 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: 2025-01-24 +date: 2025-01-27 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 e36bba3ee0ed7..07fa18aebc9ca 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: 2025-01-24 +date: 2025-01-27 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_feature_flags_browser.mdx b/api_docs/kbn_core_feature_flags_browser.mdx index f8097990e49c8..bbb762fadaa27 100644 --- a/api_docs/kbn_core_feature_flags_browser.mdx +++ b/api_docs/kbn_core_feature_flags_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-feature-flags-browser title: "@kbn/core-feature-flags-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-feature-flags-browser plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-feature-flags-browser'] --- import kbnCoreFeatureFlagsBrowserObj from './kbn_core_feature_flags_browser.devdocs.json'; diff --git a/api_docs/kbn_core_feature_flags_browser_internal.mdx b/api_docs/kbn_core_feature_flags_browser_internal.mdx index 189104b353153..3d4365790e898 100644 --- a/api_docs/kbn_core_feature_flags_browser_internal.mdx +++ b/api_docs/kbn_core_feature_flags_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-feature-flags-browser-internal title: "@kbn/core-feature-flags-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-feature-flags-browser-internal plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-feature-flags-browser-internal'] --- import kbnCoreFeatureFlagsBrowserInternalObj from './kbn_core_feature_flags_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_feature_flags_browser_mocks.mdx b/api_docs/kbn_core_feature_flags_browser_mocks.mdx index ce9ffb4f963e3..16d9b8f174c36 100644 --- a/api_docs/kbn_core_feature_flags_browser_mocks.mdx +++ b/api_docs/kbn_core_feature_flags_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-feature-flags-browser-mocks title: "@kbn/core-feature-flags-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-feature-flags-browser-mocks plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-feature-flags-browser-mocks'] --- import kbnCoreFeatureFlagsBrowserMocksObj from './kbn_core_feature_flags_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_feature_flags_server.mdx b/api_docs/kbn_core_feature_flags_server.mdx index cbb9055ed41fb..21de77612d760 100644 --- a/api_docs/kbn_core_feature_flags_server.mdx +++ b/api_docs/kbn_core_feature_flags_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-feature-flags-server title: "@kbn/core-feature-flags-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-feature-flags-server plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-feature-flags-server'] --- import kbnCoreFeatureFlagsServerObj from './kbn_core_feature_flags_server.devdocs.json'; diff --git a/api_docs/kbn_core_feature_flags_server_internal.mdx b/api_docs/kbn_core_feature_flags_server_internal.mdx index cc80f4dc89b76..64ca4a18fe647 100644 --- a/api_docs/kbn_core_feature_flags_server_internal.mdx +++ b/api_docs/kbn_core_feature_flags_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-feature-flags-server-internal title: "@kbn/core-feature-flags-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-feature-flags-server-internal plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-feature-flags-server-internal'] --- import kbnCoreFeatureFlagsServerInternalObj from './kbn_core_feature_flags_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_feature_flags_server_mocks.mdx b/api_docs/kbn_core_feature_flags_server_mocks.mdx index 7757b868abf41..9bc83560a012b 100644 --- a/api_docs/kbn_core_feature_flags_server_mocks.mdx +++ b/api_docs/kbn_core_feature_flags_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-feature-flags-server-mocks title: "@kbn/core-feature-flags-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-feature-flags-server-mocks plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-feature-flags-server-mocks'] --- import kbnCoreFeatureFlagsServerMocksObj from './kbn_core_feature_flags_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_http_browser.mdx b/api_docs/kbn_core_http_browser.mdx index 315c7527a9fc4..6e3afff9d6cd9 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: 2025-01-24 +date: 2025-01-27 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 9e6ca8670f91f..048635d7be7d5 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: 2025-01-24 +date: 2025-01-27 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 7f54ef3442528..0d5774dd79373 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: 2025-01-24 +date: 2025-01-27 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 019006fcd69bb..b9749b1c62dcb 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: 2025-01-24 +date: 2025-01-27 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 bd5d336b8a43e..7e52f72c12930 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: 2025-01-24 +date: 2025-01-27 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 980a8b19f1b57..07efc3a0d4cd4 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: 2025-01-24 +date: 2025-01-27 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 c0aa64c88e3ea..a95bbeec5b46a 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: 2025-01-24 +date: 2025-01-27 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 eeb632f32bd64..d5141ceed0c61 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: 2025-01-24 +date: 2025-01-27 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 e08cc5daa865b..5e532595893ec 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: 2025-01-24 +date: 2025-01-27 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 e60d74acf70c3..f80971af64a75 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: 2025-01-24 +date: 2025-01-27 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 8acd9b572bcfd..89ae99ee275ed 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: 2025-01-24 +date: 2025-01-27 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.mdx b/api_docs/kbn_core_http_server.mdx index a862175c26d54..6673ee999aa07 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: 2025-01-24 +date: 2025-01-27 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 c2b5a1d041071..1d16acedab3f4 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: 2025-01-24 +date: 2025-01-27 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 1ad954d9db045..e45a34df120ce 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: 2025-01-24 +date: 2025-01-27 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_http_server_utils.mdx b/api_docs/kbn_core_http_server_utils.mdx index ac42e27483a2c..50aa53da5f9c6 100644 --- a/api_docs/kbn_core_http_server_utils.mdx +++ b/api_docs/kbn_core_http_server_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-server-utils title: "@kbn/core-http-server-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-server-utils plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-server-utils'] --- import kbnCoreHttpServerUtilsObj from './kbn_core_http_server_utils.devdocs.json'; diff --git a/api_docs/kbn_core_i18n_browser.mdx b/api_docs/kbn_core_i18n_browser.mdx index 8d8ec318602b4..546d86c605140 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: 2025-01-24 +date: 2025-01-27 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 121cdff1255dd..c0a43dc93dc08 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: 2025-01-24 +date: 2025-01-27 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 c07834302cb5e..8b4bebb7b07d9 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: 2025-01-24 +date: 2025-01-27 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 2c3072e76f171..3757f43804f4b 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: 2025-01-24 +date: 2025-01-27 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 baba82b19d605..f96a336025844 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: 2025-01-24 +date: 2025-01-27 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 c91f070206b95..3901b95f7899e 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: 2025-01-24 +date: 2025-01-27 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 a90900fd04932..9de019b453c5c 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: 2025-01-24 +date: 2025-01-27 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 398e53e26b130..40a38da6fa87c 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: 2025-01-24 +date: 2025-01-27 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 45b9c751fde63..be5a9e0b40b76 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: 2025-01-24 +date: 2025-01-27 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 cab25a00d6c9c..0024665afb412 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: 2025-01-24 +date: 2025-01-27 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 1c416db18b712..d53efe7c652ec 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: 2025-01-24 +date: 2025-01-27 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 921cd7ca26f48..51f11cc9c7acb 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: 2025-01-24 +date: 2025-01-27 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 fe7070c66500c..2764e7cd06431 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: 2025-01-24 +date: 2025-01-27 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 b27994f515ab2..409d175e1f45f 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: 2025-01-24 +date: 2025-01-27 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 434237362b1fc..2a8b5c48e9d54 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: 2025-01-24 +date: 2025-01-27 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 9809d46ef5cd1..cd0216d7456d2 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: 2025-01-24 +date: 2025-01-27 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 8f553a7a124a1..58393f47ba00c 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: 2025-01-24 +date: 2025-01-27 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 194855b1d4c46..b797233c363c0 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: 2025-01-24 +date: 2025-01-27 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 9e21308b37c87..02235641018c3 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: 2025-01-24 +date: 2025-01-27 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 2205dc18ce469..3fa29f6d93cc4 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: 2025-01-24 +date: 2025-01-27 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 6f310e4dcda1c..c226de0701da4 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: 2025-01-24 +date: 2025-01-27 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 47c04f2f22721..0d1cee0ec99f1 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: 2025-01-24 +date: 2025-01-27 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 41a171c72d873..58d8737c780d7 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: 2025-01-24 +date: 2025-01-27 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 642cfc8c026b5..501fb2d29b629 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: 2025-01-24 +date: 2025-01-27 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 ea5527f605203..d2ccf22cfba19 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: 2025-01-24 +date: 2025-01-27 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 a1439fb72c97c..0b1a4339bc7cd 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: 2025-01-24 +date: 2025-01-27 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 e843a6b78e437..892c21d0c1b7b 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: 2025-01-24 +date: 2025-01-27 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 fba1657afcd9f..5fb4867f25f6b 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: 2025-01-24 +date: 2025-01-27 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 a0b31f3b20417..0bfa86deb8798 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: 2025-01-24 +date: 2025-01-27 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 de7225f370131..958d6ff6ab86b 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: 2025-01-24 +date: 2025-01-27 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 7a5451ba3ae71..a7903e77f560c 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: 2025-01-24 +date: 2025-01-27 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 e456ab832a325..3cef4a9a1d533 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: 2025-01-24 +date: 2025-01-27 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 ab867aee712c3..6acecfbf14373 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: 2025-01-24 +date: 2025-01-27 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 87d4742ef8b5a..dfa8ae2220ce0 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: 2025-01-24 +date: 2025-01-27 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 f4cfa5da7cc06..8bc9f65277a75 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: 2025-01-24 +date: 2025-01-27 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 58f5f5fe94a65..4293e8e1b06f9 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: 2025-01-24 +date: 2025-01-27 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 81ab255f2ef59..fa143372a4488 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: 2025-01-24 +date: 2025-01-27 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 05227e9ffc4b5..5fb7c03a9b1ef 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: 2025-01-24 +date: 2025-01-27 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 e9b116160a3a1..ee8b14241677f 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: 2025-01-24 +date: 2025-01-27 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 4d11f3e61d2c3..6de0acf95c678 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: 2025-01-24 +date: 2025-01-27 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.mdx b/api_docs/kbn_core_rendering_browser.mdx index 9b89380b9cf69..54c02ba1d581a 100644 --- a/api_docs/kbn_core_rendering_browser.mdx +++ b/api_docs/kbn_core_rendering_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-rendering-browser title: "@kbn/core-rendering-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-rendering-browser plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-rendering-browser'] --- import kbnCoreRenderingBrowserObj from './kbn_core_rendering_browser.devdocs.json'; diff --git a/api_docs/kbn_core_rendering_browser_mocks.mdx b/api_docs/kbn_core_rendering_browser_mocks.mdx index 8975bdbcc88b0..3988cd8fc5714 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: 2025-01-24 +date: 2025-01-27 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 e58229b9c019e..3f777f4366e62 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: 2025-01-24 +date: 2025-01-27 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 8c2d92b923f1c..ea88aa6430d4f 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: 2025-01-24 +date: 2025-01-27 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 0bebefbe3717e..18c54496a88ac 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: 2025-01-24 +date: 2025-01-27 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 458d4b689a58a..02604f7b03871 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: 2025-01-24 +date: 2025-01-27 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 41e163696aac2..f074324518792 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: 2025-01-24 +date: 2025-01-27 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 26c142dd292a0..47156cc7cd21d 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: 2025-01-24 +date: 2025-01-27 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 7e0fa7e45a13c..e486ad705ecf0 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: 2025-01-24 +date: 2025-01-27 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 06216d34a2619..cf7c92f37142e 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: 2025-01-24 +date: 2025-01-27 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 0b0b3deda127e..fa0f958c15975 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: 2025-01-24 +date: 2025-01-27 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 051aa4e128ced..e753fe4c8b09c 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: 2025-01-24 +date: 2025-01-27 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 ede295f538ddc..11916faadb5e0 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: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-browser-mocks'] --- import kbnCoreSavedObjectsBrowserMocksObj from './kbn_core_saved_objects_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_common.devdocs.json b/api_docs/kbn_core_saved_objects_common.devdocs.json index 54c4551b2c051..a959855d27c5c 100644 --- a/api_docs/kbn_core_saved_objects_common.devdocs.json +++ b/api_docs/kbn_core_saved_objects_common.devdocs.json @@ -1239,14 +1239,6 @@ "plugin": "savedObjectsTagging", "path": "x-pack/platform/plugins/shared/saved_objects_tagging/common/types.ts" }, - { - "plugin": "savedObjectsTagging", - "path": "x-pack/platform/plugins/shared/saved_objects_tagging/public/utils.ts" - }, - { - "plugin": "savedObjectsTagging", - "path": "x-pack/platform/plugins/shared/saved_objects_tagging/public/utils.ts" - }, { "plugin": "upgradeAssistant", "path": "x-pack/platform/plugins/private/upgrade_assistant/common/types.ts" @@ -1255,18 +1247,6 @@ "plugin": "upgradeAssistant", "path": "x-pack/platform/plugins/private/upgrade_assistant/common/types.ts" }, - { - "plugin": "savedObjectsTagging", - "path": "x-pack/platform/plugins/shared/saved_objects_tagging/public/utils.test.ts" - }, - { - "plugin": "savedObjectsTagging", - "path": "x-pack/platform/plugins/shared/saved_objects_tagging/public/utils.test.ts" - }, - { - "plugin": "savedObjectsTagging", - "path": "x-pack/platform/plugins/shared/saved_objects_tagging/public/utils.test.ts" - }, { "plugin": "savedObjectsTagging", "path": "x-pack/platform/plugins/shared/saved_objects_tagging/common/test_utils/index.ts" @@ -2226,50 +2206,6 @@ "plugin": "visualizations", "path": "src/platform/plugins/shared/visualizations/public/utils/saved_visualization_references/timeseries_references.ts" }, - { - "plugin": "savedObjectsTagging", - "path": "x-pack/platform/plugins/shared/saved_objects_tagging/common/references.ts" - }, - { - "plugin": "savedObjectsTagging", - "path": "x-pack/platform/plugins/shared/saved_objects_tagging/common/references.ts" - }, - { - "plugin": "savedObjectsTagging", - "path": "x-pack/platform/plugins/shared/saved_objects_tagging/common/references.ts" - }, - { - "plugin": "savedObjectsTagging", - "path": "x-pack/platform/plugins/shared/saved_objects_tagging/common/references.ts" - }, - { - "plugin": "savedObjectsTagging", - "path": "x-pack/platform/plugins/shared/saved_objects_tagging/common/references.ts" - }, - { - "plugin": "savedObjectsTagging", - "path": "x-pack/platform/plugins/shared/saved_objects_tagging/common/references.ts" - }, - { - "plugin": "savedObjectsTagging", - "path": "x-pack/platform/plugins/shared/saved_objects_tagging/common/references.ts" - }, - { - "plugin": "savedObjectsTagging", - "path": "x-pack/platform/plugins/shared/saved_objects_tagging/public/utils.ts" - }, - { - "plugin": "savedObjectsTagging", - "path": "x-pack/platform/plugins/shared/saved_objects_tagging/public/utils.ts" - }, - { - "plugin": "savedObjectsTagging", - "path": "x-pack/platform/plugins/shared/saved_objects_tagging/public/utils.ts" - }, - { - "plugin": "savedObjectsTagging", - "path": "x-pack/platform/plugins/shared/saved_objects_tagging/public/utils.ts" - }, { "plugin": "savedObjectsTagging", "path": "x-pack/platform/plugins/shared/saved_objects_tagging/public/components/connected/tag_list.tsx" @@ -2442,26 +2378,6 @@ "plugin": "uiActionsEnhanced", "path": "src/platform/plugins/shared/ui_actions_enhanced/server/dynamic_action_enhancement.ts" }, - { - "plugin": "savedObjectsTagging", - "path": "x-pack/platform/plugins/shared/saved_objects_tagging/common/references.test.ts" - }, - { - "plugin": "savedObjectsTagging", - "path": "x-pack/platform/plugins/shared/saved_objects_tagging/common/references.test.ts" - }, - { - "plugin": "savedObjectsTagging", - "path": "x-pack/platform/plugins/shared/saved_objects_tagging/public/utils.test.ts" - }, - { - "plugin": "savedObjectsTagging", - "path": "x-pack/platform/plugins/shared/saved_objects_tagging/public/utils.test.ts" - }, - { - "plugin": "savedObjectsTagging", - "path": "x-pack/platform/plugins/shared/saved_objects_tagging/public/utils.test.ts" - }, { "plugin": "savedObjectsTagging", "path": "x-pack/platform/plugins/shared/saved_objects_tagging/common/test_utils/index.ts" diff --git a/api_docs/kbn_core_saved_objects_common.mdx b/api_docs/kbn_core_saved_objects_common.mdx index 03136dbc5dbdd..4abaf4eb64433 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: 2025-01-24 +date: 2025-01-27 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 8d5a011c01128..d03f3dd51a287 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: 2025-01-24 +date: 2025-01-27 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 7321150ca5eaf..7152dc179d79e 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: 2025-01-24 +date: 2025-01-27 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 2868881692bfb..ef7a2b4a6b7cc 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: 2025-01-24 +date: 2025-01-27 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 4d5df3dae875f..e15531edeea79 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: 2025-01-24 +date: 2025-01-27 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 8504ede2b2a7a..521ade838b0be 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: 2025-01-24 +date: 2025-01-27 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 35a9476560a2e..a3b098b6d9e5f 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: 2025-01-24 +date: 2025-01-27 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 89ee8273cc26c..9072e8cdd8888 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: 2025-01-24 +date: 2025-01-27 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 3d583c729c3f2..3d5ffb4137bef 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: 2025-01-24 +date: 2025-01-27 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 d42571040fb90..1335a43b164c8 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: 2025-01-24 +date: 2025-01-27 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 43b7aed2b9f85..1c0f56251215b 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: 2025-01-24 +date: 2025-01-27 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 5d32b2f0e2d61..80ea4902e9482 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: 2025-01-24 +date: 2025-01-27 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 4b6a5ea096296..6934fd321294a 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: 2025-01-24 +date: 2025-01-27 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 d9ca7bd1421bd..67187e1f93c2a 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: 2025-01-24 +date: 2025-01-27 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 72241f6d1964f..1a238cdf95071 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: 2025-01-24 +date: 2025-01-27 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 c053c9c51b83b..e2d12179cef27 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: 2025-01-24 +date: 2025-01-27 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 a4fc8c6728e7b..70ce11633d19a 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: 2025-01-24 +date: 2025-01-27 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_server.mdx b/api_docs/kbn_core_status_server.mdx index 79043f81cc702..f6e3a8a1e5d47 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: 2025-01-24 +date: 2025-01-27 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 1f59fcc3746a1..e9abedecfbfce 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: 2025-01-24 +date: 2025-01-27 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 6d088d4d6ca8e..5612f7063f29e 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: 2025-01-24 +date: 2025-01-27 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 c07721ede8724..b721be2c47457 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: 2025-01-24 +date: 2025-01-27 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 5fdf358574c8a..8f2b053829d5c 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: 2025-01-24 +date: 2025-01-27 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 e94c5ce87ae8d..49877b58f8a12 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: 2025-01-24 +date: 2025-01-27 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 9553426cbca5a..722172e13d7a0 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: 2025-01-24 +date: 2025-01-27 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 076d617975e50..a6ade60067db6 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: 2025-01-24 +date: 2025-01-27 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 4914d6ed9f17c..a12138626e14a 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: 2025-01-24 +date: 2025-01-27 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 2d0fc7919fe57..6377fb9e406a1 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: 2025-01-24 +date: 2025-01-27 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_internal.mdx b/api_docs/kbn_core_theme_browser_internal.mdx index b9c6ba4332fec..8b570e04110af 100644 --- a/api_docs/kbn_core_theme_browser_internal.mdx +++ b/api_docs/kbn_core_theme_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-theme-browser-internal title: "@kbn/core-theme-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-theme-browser-internal plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-theme-browser-internal'] --- import kbnCoreThemeBrowserInternalObj from './kbn_core_theme_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_theme_browser_mocks.mdx b/api_docs/kbn_core_theme_browser_mocks.mdx index f98c95ad6819d..ab7420f2242e1 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: 2025-01-24 +date: 2025-01-27 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 f1f83399bf0e3..a2da2ac206fcc 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: 2025-01-24 +date: 2025-01-27 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 d2dd7a532f9e0..e9f29f317b4c6 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: 2025-01-24 +date: 2025-01-27 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 5467dc739aedb..78408dc85033d 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: 2025-01-24 +date: 2025-01-27 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 b437a6a25aac3..2ddfc7f5302e8 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: 2025-01-24 +date: 2025-01-27 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 925537672b9fd..ba781c1516c1f 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: 2025-01-24 +date: 2025-01-27 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 e088e43352064..f026864ed3fca 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: 2025-01-24 +date: 2025-01-27 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 98e491af45e7a..09d0c5c5a6059 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: 2025-01-24 +date: 2025-01-27 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 2db6d44e34cd0..626b3963be65d 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: 2025-01-24 +date: 2025-01-27 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 c835a055958f9..46dbec8b6b901 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: 2025-01-24 +date: 2025-01-27 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 7bfa1d9974c43..f687b0ddf41a8 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: 2025-01-24 +date: 2025-01-27 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 a27d9dcf4cbce..02bde8dd0efd2 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: 2025-01-24 +date: 2025-01-27 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 31c17294b0ff3..ec6a7980966f0 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: 2025-01-24 +date: 2025-01-27 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 6b68828af9c5e..f65752102c3ec 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: 2025-01-24 +date: 2025-01-27 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 291907b75c368..b4ede5adc58e0 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: 2025-01-24 +date: 2025-01-27 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 27f779d37b036..ae1981e91d2a3 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: 2025-01-24 +date: 2025-01-27 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 22decc29b10b5..799c2d7bf2e87 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: 2025-01-24 +date: 2025-01-27 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 c41cb9f08b704..9a5eb83b34543 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: 2025-01-24 +date: 2025-01-27 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 903512a061e09..0f5d78fcce003 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: 2025-01-24 +date: 2025-01-27 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 666f7f49586a9..dd18ada7282e1 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: 2025-01-24 +date: 2025-01-27 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 4e95c0432024a..2a3df38cbfe87 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: 2025-01-24 +date: 2025-01-27 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 2fd8e43cde112..d403243db3cef 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: 2025-01-24 +date: 2025-01-27 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 830c38acca61d..d958eeaf96324 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: 2025-01-24 +date: 2025-01-27 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 1586dbc6afe7c..3174c9efe4d0a 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: 2025-01-24 +date: 2025-01-27 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 e9a43df7d1772..58798be6e0010 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: 2025-01-24 +date: 2025-01-27 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 17644330564ee..bea63daf24509 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: 2025-01-24 +date: 2025-01-27 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 3deeb7106f1c7..0ad2208dec251 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: 2025-01-24 +date: 2025-01-27 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 759986858defb..b4342f0ee5bee 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: 2025-01-24 +date: 2025-01-27 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 308dfef15972d..e69714dc10d90 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: 2025-01-24 +date: 2025-01-27 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 9e9f8201ca2a5..86c391e94f78c 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: 2025-01-24 +date: 2025-01-27 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 e1d6069725f68..8d27c0a407422 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: 2025-01-24 +date: 2025-01-27 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 ec494d62f1391..ef626200ddff5 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: 2025-01-24 +date: 2025-01-27 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 d3a3d39da0224..77cad116e5eea 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: 2025-01-24 +date: 2025-01-27 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 fc54fde64779f..6bfa805948002 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: 2025-01-24 +date: 2025-01-27 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 898198374d9bd..b145bcf14d165 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: 2025-01-24 +date: 2025-01-27 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 1796660231e02..0ce483f0a0969 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: 2025-01-24 +date: 2025-01-27 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 ef2ad9065ca03..6b47b8b67278d 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: 2025-01-24 +date: 2025-01-27 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 a843436472480..d4de916aa5742 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: 2025-01-24 +date: 2025-01-27 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 bdecf2296ea24..42976fc935231 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: 2025-01-24 +date: 2025-01-27 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 cf1464557012d..50ddc5b31e95c 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: 2025-01-24 +date: 2025-01-27 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 daee45c78c9b8..0639db5877ff7 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: 2025-01-24 +date: 2025-01-27 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 7d6dc78ba5fe2..4d53b9577cf00 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: 2025-01-24 +date: 2025-01-27 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 ee1744ca3ef25..e8502246bae6a 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: 2025-01-24 +date: 2025-01-27 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 97d5bc2d3bbef..47e95746d27bc 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: 2025-01-24 +date: 2025-01-27 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 414d152613747..789074542d6e3 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: 2025-01-24 +date: 2025-01-27 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 373a362123de1..d9202f3779048 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: 2025-01-24 +date: 2025-01-27 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 13c4f3f995569..7267fb62fb008 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: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/dev-utils'] --- import kbnDevUtilsObj from './kbn_dev_utils.devdocs.json'; diff --git a/api_docs/kbn_discover_contextual_components.mdx b/api_docs/kbn_discover_contextual_components.mdx index 9e31705932205..691844391f565 100644 --- a/api_docs/kbn_discover_contextual_components.mdx +++ b/api_docs/kbn_discover_contextual_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-discover-contextual-components title: "@kbn/discover-contextual-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/discover-contextual-components plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/discover-contextual-components'] --- import kbnDiscoverContextualComponentsObj from './kbn_discover_contextual_components.devdocs.json'; diff --git a/api_docs/kbn_discover_utils.mdx b/api_docs/kbn_discover_utils.mdx index 4c9abacd13f5c..775eea3ac4532 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: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/discover-utils'] --- import kbnDiscoverUtilsObj from './kbn_discover_utils.devdocs.json'; diff --git a/api_docs/kbn_doc_links.devdocs.json b/api_docs/kbn_doc_links.devdocs.json index 1650e5e3854e4..cceaa50256198 100644 --- a/api_docs/kbn_doc_links.devdocs.json +++ b/api_docs/kbn_doc_links.devdocs.json @@ -641,7 +641,7 @@ "label": "observability", "description": [], "signature": [ - "{ readonly guide: string; readonly infrastructureThreshold: string; readonly logsThreshold: string; readonly metricsThreshold: string; readonly customThreshold: string; readonly monitorStatus: string; readonly monitorUptime: string; readonly tlsCertificate: string; readonly uptimeDurationAnomaly: string; readonly monitorLogs: string; readonly analyzeMetrics: string; readonly monitorUptimeSynthetics: string; readonly userExperience: string; readonly createAlerts: string; readonly syntheticsAlerting: string; readonly syntheticsCommandReference: string; readonly syntheticsProjectMonitors: string; readonly syntheticsMigrateFromIntegration: string; readonly sloBurnRateRule: string; readonly aiAssistant: string; }" + "{ readonly guide: string; readonly infrastructureThreshold: string; readonly logsThreshold: string; readonly metricsThreshold: string; readonly customThreshold: string; readonly monitorStatus: string; readonly monitorUptime: string; readonly tlsCertificate: string; readonly uptimeDurationAnomaly: string; readonly monitorLogs: string; readonly analyzeMetrics: string; readonly monitorUptimeSynthetics: string; readonly userExperience: string; readonly createAlerts: string; readonly syntheticsAlerting: string; readonly syntheticsCommandReference: string; readonly syntheticsProjectMonitors: string; readonly syntheticsMigrateFromIntegration: string; readonly slo: string; readonly sloBurnRateRule: string; readonly aiAssistant: string; }" ], "path": "src/platform/packages/shared/kbn-doc-links/src/types.ts", "deprecated": false, diff --git a/api_docs/kbn_doc_links.mdx b/api_docs/kbn_doc_links.mdx index 55400bf1e1893..cb00adafd1e1c 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: 2025-01-24 +date: 2025-01-27 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 a2a82e04d6e69..34971af49de6e 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: 2025-01-24 +date: 2025-01-27 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 60854e18ee576..9b602ecd7756c 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: 2025-01-24 +date: 2025-01-27 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 2992f4c04ea13..ab8a2fac40244 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: 2025-01-24 +date: 2025-01-27 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 2823d5e4c88e5..ba5bb9c3f6620 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: 2025-01-24 +date: 2025-01-27 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 c70ccc0fce326..b8631e347867c 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: 2025-01-24 +date: 2025-01-27 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 360594f3af77a..a81ae16bca3d1 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: 2025-01-24 +date: 2025-01-27 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 08a09f461fb82..b7df47172d2ed 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: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/elastic-assistant-common'] --- import kbnElasticAssistantCommonObj from './kbn_elastic_assistant_common.devdocs.json'; diff --git a/api_docs/kbn_entities_schema.mdx b/api_docs/kbn_entities_schema.mdx index 3af558ea9c200..0eb5a2f72cfd8 100644 --- a/api_docs/kbn_entities_schema.mdx +++ b/api_docs/kbn_entities_schema.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-entities-schema title: "@kbn/entities-schema" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/entities-schema plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/entities-schema'] --- import kbnEntitiesSchemaObj from './kbn_entities_schema.devdocs.json'; diff --git a/api_docs/kbn_es.mdx b/api_docs/kbn_es.mdx index 436771506e962..7356b75303fe8 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: 2025-01-24 +date: 2025-01-27 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 bb29a27694ea4..4569fe3d3a3a4 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: 2025-01-24 +date: 2025-01-27 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 5080cbcbd262c..2146e311a011d 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: 2025-01-24 +date: 2025-01-27 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 5a25c236b3b32..2d72a0526c945 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: 2025-01-24 +date: 2025-01-27 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 32f8ea96d22ea..fd59527f3f1fa 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: 2025-01-24 +date: 2025-01-27 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 21f8a38d461f0..8d2f2b304069a 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: 2025-01-24 +date: 2025-01-27 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 cd623b9589bb6..92c84d546e523 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: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/esql-ast'] --- import kbnEsqlAstObj from './kbn_esql_ast.devdocs.json'; diff --git a/api_docs/kbn_esql_editor.mdx b/api_docs/kbn_esql_editor.mdx index acdae3b8aa7ec..62158772f48c1 100644 --- a/api_docs/kbn_esql_editor.mdx +++ b/api_docs/kbn_esql_editor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-esql-editor title: "@kbn/esql-editor" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/esql-editor plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/esql-editor'] --- import kbnEsqlEditorObj from './kbn_esql_editor.devdocs.json'; diff --git a/api_docs/kbn_esql_utils.mdx b/api_docs/kbn_esql_utils.mdx index 9d2af135cd82d..2f0ac9f701bfb 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: 2025-01-24 +date: 2025-01-27 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 a7bcf848f0f87..394d51c552e31 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: 2025-01-24 +date: 2025-01-27 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 d0fbf25abc655..ccf5c925ba974 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: 2025-01-24 +date: 2025-01-27 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 0fffededac931..f3e0c0aa79498 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: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/event-annotation-components'] --- import kbnEventAnnotationComponentsObj from './kbn_event_annotation_components.devdocs.json'; diff --git a/api_docs/kbn_event_stacktrace.mdx b/api_docs/kbn_event_stacktrace.mdx index 3ae76bc5ad0c8..a4bffb964915a 100644 --- a/api_docs/kbn_event_stacktrace.mdx +++ b/api_docs/kbn_event_stacktrace.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-event-stacktrace title: "@kbn/event-stacktrace" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/event-stacktrace plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/event-stacktrace'] --- import kbnEventStacktraceObj from './kbn_event_stacktrace.devdocs.json'; diff --git a/api_docs/kbn_expandable_flyout.mdx b/api_docs/kbn_expandable_flyout.mdx index bee2c168f966f..5da3a2bc3fc6a 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: 2025-01-24 +date: 2025-01-27 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 e5787827a6fb8..9755280fa8347 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: 2025-01-24 +date: 2025-01-27 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 b6f385d09108e..4d6206a35f5b2 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: 2025-01-24 +date: 2025-01-27 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 4ca47c0c5a441..3b14f208f0ed7 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: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/find-used-node-modules'] --- import kbnFindUsedNodeModulesObj from './kbn_find_used_node_modules.devdocs.json'; diff --git a/api_docs/kbn_ftr_common_functional_services.mdx b/api_docs/kbn_ftr_common_functional_services.mdx index 6a8948b0a88df..eebcc199d543c 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: 2025-01-24 +date: 2025-01-27 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 214206408a9b2..57ce1f64729ba 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: 2025-01-24 +date: 2025-01-27 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_gen_ai_functional_testing.mdx b/api_docs/kbn_gen_ai_functional_testing.mdx index 1ab33bf41528e..e94c84a8c103f 100644 --- a/api_docs/kbn_gen_ai_functional_testing.mdx +++ b/api_docs/kbn_gen_ai_functional_testing.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-gen-ai-functional-testing title: "@kbn/gen-ai-functional-testing" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/gen-ai-functional-testing plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/gen-ai-functional-testing'] --- import kbnGenAiFunctionalTestingObj from './kbn_gen_ai_functional_testing.devdocs.json'; diff --git a/api_docs/kbn_generate.mdx b/api_docs/kbn_generate.mdx index f0430ff3ed85a..65878f589f048 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: 2025-01-24 +date: 2025-01-27 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 a92fd2ee27c26..2bfca1b34c7a5 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: 2025-01-24 +date: 2025-01-27 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 04356c13af4ea..baa94300846d3 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: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/generate-csv'] --- import kbnGenerateCsvObj from './kbn_generate_csv.devdocs.json'; diff --git a/api_docs/kbn_grid_layout.mdx b/api_docs/kbn_grid_layout.mdx index 7a552b83a3029..1bbf62db4f57f 100644 --- a/api_docs/kbn_grid_layout.mdx +++ b/api_docs/kbn_grid_layout.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-grid-layout title: "@kbn/grid-layout" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/grid-layout plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/grid-layout'] --- import kbnGridLayoutObj from './kbn_grid_layout.devdocs.json'; diff --git a/api_docs/kbn_grouping.mdx b/api_docs/kbn_grouping.mdx index 9ab3bd455027b..d6873d85d235a 100644 --- a/api_docs/kbn_grouping.mdx +++ b/api_docs/kbn_grouping.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-grouping title: "@kbn/grouping" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/grouping plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/grouping'] --- import kbnGroupingObj from './kbn_grouping.devdocs.json'; diff --git a/api_docs/kbn_guided_onboarding.devdocs.json b/api_docs/kbn_guided_onboarding.devdocs.json index a306320bd5963..819e395230d19 100644 --- a/api_docs/kbn_guided_onboarding.devdocs.json +++ b/api_docs/kbn_guided_onboarding.devdocs.json @@ -146,7 +146,7 @@ "label": "guideId", "description": [], "signature": [ - "\"siem\" | \"kubernetes\" | \"appSearch\" | \"websiteSearch\" | \"databaseSearch\" | \"testGuide\"" + "\"siem\" | \"kubernetes\" | \"websiteSearch\" | \"databaseSearch\" | \"testGuide\"" ], "path": "src/platform/packages/shared/kbn-guided-onboarding/src/types.ts", "deprecated": false, @@ -485,7 +485,7 @@ "label": "GuideId", "description": [], "signature": [ - "\"siem\" | \"kubernetes\" | \"appSearch\" | \"websiteSearch\" | \"databaseSearch\" | \"testGuide\"" + "\"siem\" | \"kubernetes\" | \"websiteSearch\" | \"databaseSearch\" | \"testGuide\"" ], "path": "src/platform/packages/shared/kbn-guided-onboarding/src/types.ts", "deprecated": false, @@ -564,7 +564,7 @@ "label": "testGuideId", "description": [], "signature": [ - "\"siem\" | \"kubernetes\" | \"appSearch\" | \"websiteSearch\" | \"databaseSearch\" | \"testGuide\"" + "\"siem\" | \"kubernetes\" | \"websiteSearch\" | \"databaseSearch\" | \"testGuide\"" ], "path": "src/platform/packages/shared/kbn-guided-onboarding/src/common/test_guide_config.ts", "deprecated": false, diff --git a/api_docs/kbn_guided_onboarding.mdx b/api_docs/kbn_guided_onboarding.mdx index 5a54600464e03..abd160006d2df 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: 2025-01-24 +date: 2025-01-27 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 9d98bc0538c69..0fa56c2e758ce 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: 2025-01-24 +date: 2025-01-27 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 292b55d76c56f..14fe16a6d255d 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: 2025-01-24 +date: 2025-01-27 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 c2c00b6a19181..ad0a54a2d10f3 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: 2025-01-24 +date: 2025-01-27 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 445c635c108f1..b0f4d8da62c63 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: 2025-01-24 +date: 2025-01-27 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 991e073b5d63a..29ba023f653b7 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: 2025-01-24 +date: 2025-01-27 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 8ed11aac665cb..e3d6173d5d5c2 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: 2025-01-24 +date: 2025-01-27 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 d80f04fa6829c..05d208bb7b43c 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: 2025-01-24 +date: 2025-01-27 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 9836ee02b843d..ae3478991a336 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: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/import-resolver'] --- import kbnImportResolverObj from './kbn_import_resolver.devdocs.json'; diff --git a/api_docs/kbn_index_adapter.mdx b/api_docs/kbn_index_adapter.mdx index 6d292203d1e6a..e98a6ea5a4d73 100644 --- a/api_docs/kbn_index_adapter.mdx +++ b/api_docs/kbn_index_adapter.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-index-adapter title: "@kbn/index-adapter" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/index-adapter plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/index-adapter'] --- import kbnIndexAdapterObj from './kbn_index_adapter.devdocs.json'; diff --git a/api_docs/kbn_index_lifecycle_management_common_shared.mdx b/api_docs/kbn_index_lifecycle_management_common_shared.mdx index d73a72520b821..bef3cf20c642a 100644 --- a/api_docs/kbn_index_lifecycle_management_common_shared.mdx +++ b/api_docs/kbn_index_lifecycle_management_common_shared.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-index-lifecycle-management-common-shared title: "@kbn/index-lifecycle-management-common-shared" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/index-lifecycle-management-common-shared plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/index-lifecycle-management-common-shared'] --- import kbnIndexLifecycleManagementCommonSharedObj from './kbn_index_lifecycle_management_common_shared.devdocs.json'; diff --git a/api_docs/kbn_index_management_shared_types.mdx b/api_docs/kbn_index_management_shared_types.mdx index 900653e241d63..4f0030edf1870 100644 --- a/api_docs/kbn_index_management_shared_types.mdx +++ b/api_docs/kbn_index_management_shared_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-index-management-shared-types title: "@kbn/index-management-shared-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/index-management-shared-types plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/index-management-shared-types'] --- import kbnIndexManagementSharedTypesObj from './kbn_index_management_shared_types.devdocs.json'; diff --git a/api_docs/kbn_inference_common.devdocs.json b/api_docs/kbn_inference_common.devdocs.json index 2778018fa058f..e4fc955a5a135 100644 --- a/api_docs/kbn_inference_common.devdocs.json +++ b/api_docs/kbn_inference_common.devdocs.json @@ -1626,7 +1626,7 @@ "tags": [], "label": "functionCalling", "description": [ - "\nFunction calling mode, defaults to \"native\"." + "\nFunction calling mode, defaults to \"auto\"." ], "signature": [ { @@ -2803,10 +2803,10 @@ "tags": [], "label": "FunctionCallingMode", "description": [ - "\nDefine the function calling mode when using inference APIs.\n- native will use the LLM's native function calling (requires the LLM to have native support)\n- simulated: will emulate function calling with function calling instructions" + "\nDefine the function calling mode when using inference APIs.\n- \"native\": will use the LLM's native function calling (requires the LLM to have native support)\n- \"simulated\": will emulate function calling with function calling instructions\n- \"auto\": will use \"native\" for providers we know are supporting native function call, \"simulated\" otherwise" ], "signature": [ - "\"native\" | \"simulated\"" + "\"auto\" | \"native\" | \"simulated\"" ], "path": "x-pack/platform/packages/shared/ai-infra/inference-common/src/chat_complete/api.ts", "deprecated": false, diff --git a/api_docs/kbn_inference_common.mdx b/api_docs/kbn_inference_common.mdx index 2dd9efc50d301..e4f07337d5f89 100644 --- a/api_docs/kbn_inference_common.mdx +++ b/api_docs/kbn_inference_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-inference-common title: "@kbn/inference-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/inference-common plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/inference-common'] --- import kbnInferenceCommonObj from './kbn_inference_common.devdocs.json'; diff --git a/api_docs/kbn_inference_endpoint_ui_common.mdx b/api_docs/kbn_inference_endpoint_ui_common.mdx index 8de34d663310b..907cfbd6eadba 100644 --- a/api_docs/kbn_inference_endpoint_ui_common.mdx +++ b/api_docs/kbn_inference_endpoint_ui_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-inference-endpoint-ui-common title: "@kbn/inference-endpoint-ui-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/inference-endpoint-ui-common plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/inference-endpoint-ui-common'] --- import kbnInferenceEndpointUiCommonObj from './kbn_inference_endpoint_ui_common.devdocs.json'; diff --git a/api_docs/kbn_inference_integration_flyout.mdx b/api_docs/kbn_inference_integration_flyout.mdx index a544c5eacd266..d7580e0b2e8de 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: 2025-01-24 +date: 2025-01-27 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 ab3c6d203d899..5c184aa4446e1 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: 2025-01-24 +date: 2025-01-27 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 3a667c948411d..9fa73238c8844 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: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/interpreter'] --- import kbnInterpreterObj from './kbn_interpreter.devdocs.json'; diff --git a/api_docs/kbn_investigation_shared.mdx b/api_docs/kbn_investigation_shared.mdx index 93c79d2e77ef6..97441b18cc26d 100644 --- a/api_docs/kbn_investigation_shared.mdx +++ b/api_docs/kbn_investigation_shared.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-investigation-shared title: "@kbn/investigation-shared" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/investigation-shared plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/investigation-shared'] --- import kbnInvestigationSharedObj from './kbn_investigation_shared.devdocs.json'; diff --git a/api_docs/kbn_io_ts_utils.mdx b/api_docs/kbn_io_ts_utils.mdx index 7f61acfcd1af0..2b46de7476527 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: 2025-01-24 +date: 2025-01-27 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 a2f4e00f5f78f..d03062a66031d 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: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ipynb'] --- import kbnIpynbObj from './kbn_ipynb.devdocs.json'; diff --git a/api_docs/kbn_item_buffer.mdx b/api_docs/kbn_item_buffer.mdx index 268b5b82f2faa..ca3403975673a 100644 --- a/api_docs/kbn_item_buffer.mdx +++ b/api_docs/kbn_item_buffer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-item-buffer title: "@kbn/item-buffer" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/item-buffer plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/item-buffer'] --- import kbnItemBufferObj from './kbn_item_buffer.devdocs.json'; diff --git a/api_docs/kbn_jest_serializers.mdx b/api_docs/kbn_jest_serializers.mdx index d26f4e07caf1c..5c8be12b3fdbc 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: 2025-01-24 +date: 2025-01-27 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 c9aa650952bce..5ed3ba4bdb8f6 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: 2025-01-24 +date: 2025-01-27 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 1984c55d6daee..dcf1fb581f18c 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: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/json-ast'] --- import kbnJsonAstObj from './kbn_json_ast.devdocs.json'; diff --git a/api_docs/kbn_json_schemas.mdx b/api_docs/kbn_json_schemas.mdx index fdef09b47ffd7..29d40330cc955 100644 --- a/api_docs/kbn_json_schemas.mdx +++ b/api_docs/kbn_json_schemas.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-json-schemas title: "@kbn/json-schemas" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/json-schemas plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/json-schemas'] --- import kbnJsonSchemasObj from './kbn_json_schemas.devdocs.json'; diff --git a/api_docs/kbn_key_value_metadata_table.mdx b/api_docs/kbn_key_value_metadata_table.mdx index ba4d6c0742335..dd856308e299e 100644 --- a/api_docs/kbn_key_value_metadata_table.mdx +++ b/api_docs/kbn_key_value_metadata_table.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-key-value-metadata-table title: "@kbn/key-value-metadata-table" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/key-value-metadata-table plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/key-value-metadata-table'] --- import kbnKeyValueMetadataTableObj from './kbn_key_value_metadata_table.devdocs.json'; diff --git a/api_docs/kbn_kibana_manifest_schema.mdx b/api_docs/kbn_kibana_manifest_schema.mdx index e63050d5e5e01..62ba73b1e2e3e 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: 2025-01-24 +date: 2025-01-27 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.mdx b/api_docs/kbn_language_documentation.mdx index 1263e86dfca1f..674301ec95a6b 100644 --- a/api_docs/kbn_language_documentation.mdx +++ b/api_docs/kbn_language_documentation.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-language-documentation title: "@kbn/language-documentation" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/language-documentation plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/language-documentation'] --- import kbnLanguageDocumentationObj from './kbn_language_documentation.devdocs.json'; diff --git a/api_docs/kbn_lens_embeddable_utils.mdx b/api_docs/kbn_lens_embeddable_utils.mdx index 7620a80c237d6..9a02441872b3b 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: 2025-01-24 +date: 2025-01-27 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 ad82bac2f2921..18bc60a70092c 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: 2025-01-24 +date: 2025-01-27 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 27e6ffdd3f207..ead71e4f5b006 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: 2025-01-24 +date: 2025-01-27 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 5d5d87c9e938d..e6f4805f12eae 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: 2025-01-24 +date: 2025-01-27 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 460939cceec71..0079124aa0df1 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: 2025-01-24 +date: 2025-01-27 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 8e0f328f5ec91..6acaee6cf8ce8 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: 2025-01-24 +date: 2025-01-27 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 24f5e931f143d..0eaa949c17e8d 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: 2025-01-24 +date: 2025-01-27 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 bebe592d357b8..2f66e049a425a 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: 2025-01-24 +date: 2025-01-27 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 da72dfa5d9fcf..2e40651f301f3 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: 2025-01-24 +date: 2025-01-27 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 10cab40e1c7d6..1059f4d9c4946 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: 2025-01-24 +date: 2025-01-27 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 937874b975c7b..5330e235dcb30 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: 2025-01-24 +date: 2025-01-27 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 89fe1f9495feb..daff941392934 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: 2025-01-24 +date: 2025-01-27 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 0e0b20cb300bc..7663d479f8a61 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: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-settings-field-definition'] --- import kbnManagementSettingsFieldDefinitionObj from './kbn_management_settings_field_definition.devdocs.json'; diff --git a/api_docs/kbn_management_settings_ids.mdx b/api_docs/kbn_management_settings_ids.mdx index a31aa8d2a15f5..c621816a90826 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: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-settings-ids'] --- import kbnManagementSettingsIdsObj from './kbn_management_settings_ids.devdocs.json'; diff --git a/api_docs/kbn_management_settings_section_registry.mdx b/api_docs/kbn_management_settings_section_registry.mdx index 9e038a44eb67e..51f217037c784 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: 2025-01-24 +date: 2025-01-27 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 621995a9e1938..9597689fca986 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: 2025-01-24 +date: 2025-01-27 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 e4156fe26bdf9..72044a1914693 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: 2025-01-24 +date: 2025-01-27 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 8315d30d83536..702cc0386404a 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: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-storybook-config'] --- import kbnManagementStorybookConfigObj from './kbn_management_storybook_config.devdocs.json'; diff --git a/api_docs/kbn_manifest.mdx b/api_docs/kbn_manifest.mdx index eac3c0bbc7367..defb0e219d690 100644 --- a/api_docs/kbn_manifest.mdx +++ b/api_docs/kbn_manifest.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-manifest title: "@kbn/manifest" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/manifest plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/manifest'] --- import kbnManifestObj from './kbn_manifest.devdocs.json'; diff --git a/api_docs/kbn_mapbox_gl.mdx b/api_docs/kbn_mapbox_gl.mdx index 01a5fc8b3c9dc..e6ac5465236f6 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: 2025-01-24 +date: 2025-01-27 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 e70702cb440c2..71eb5ae9c39cf 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: 2025-01-24 +date: 2025-01-27 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 e5025a7c9568d..1ccd6102aef7a 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: 2025-01-24 +date: 2025-01-27 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 642ebac8661a9..c047061034284 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: 2025-01-24 +date: 2025-01-27 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 92028e1894726..800a855e353f6 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: 2025-01-24 +date: 2025-01-27 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 e35e2e532a358..19470aca759ee 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: 2025-01-24 +date: 2025-01-27 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 b1245e5c9e345..8aa8a36889bf9 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: 2025-01-24 +date: 2025-01-27 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 66a2a478cb260..4960215f6b781 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: 2025-01-24 +date: 2025-01-27 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 3110a82586828..dfe098e98ecc6 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: 2025-01-24 +date: 2025-01-27 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 40dbddf0c4637..66df0b229318e 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: 2025-01-24 +date: 2025-01-27 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 8fe01d9c33261..892c74326f2e1 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: 2025-01-24 +date: 2025-01-27 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 c32ff700e91b6..6cb4f2de6ddbc 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: 2025-01-24 +date: 2025-01-27 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_field_stats_flyout.mdx b/api_docs/kbn_ml_field_stats_flyout.mdx index 72423ef5871c5..3ca6c98f5d7de 100644 --- a/api_docs/kbn_ml_field_stats_flyout.mdx +++ b/api_docs/kbn_ml_field_stats_flyout.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-field-stats-flyout title: "@kbn/ml-field-stats-flyout" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-field-stats-flyout plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-field-stats-flyout'] --- import kbnMlFieldStatsFlyoutObj from './kbn_ml_field_stats_flyout.devdocs.json'; diff --git a/api_docs/kbn_ml_in_memory_table.mdx b/api_docs/kbn_ml_in_memory_table.mdx index 1fb73c55b0e85..f90447727f4da 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: 2025-01-24 +date: 2025-01-27 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 370fca37a1063..a86d0a34f907f 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: 2025-01-24 +date: 2025-01-27 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 6abbe26c149e1..b2e693c6c18e6 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: 2025-01-24 +date: 2025-01-27 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_local_storage.mdx b/api_docs/kbn_ml_local_storage.mdx index b2edcabcdbf04..58a8a797d1387 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: 2025-01-24 +date: 2025-01-27 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 0204465928b7c..40558a2b80b91 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: 2025-01-24 +date: 2025-01-27 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 9a1ac6388b3b8..a8af7dbc1c4c4 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: 2025-01-24 +date: 2025-01-27 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_parse_interval.mdx b/api_docs/kbn_ml_parse_interval.mdx index 7ad8c292235be..f306aed8c025b 100644 --- a/api_docs/kbn_ml_parse_interval.mdx +++ b/api_docs/kbn_ml_parse_interval.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-parse-interval title: "@kbn/ml-parse-interval" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-parse-interval plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-parse-interval'] --- import kbnMlParseIntervalObj from './kbn_ml_parse_interval.devdocs.json'; diff --git a/api_docs/kbn_ml_query_utils.mdx b/api_docs/kbn_ml_query_utils.mdx index b79a256ea3824..58cd701ec9df6 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: 2025-01-24 +date: 2025-01-27 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 ee94481dda36a..cf9c4da4742c5 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: 2025-01-24 +date: 2025-01-27 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 7f94998e81e90..d2cb3c683b7c4 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: 2025-01-24 +date: 2025-01-27 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 f7e92dee82ffc..409b7277f9be8 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: 2025-01-24 +date: 2025-01-27 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 db514276a252d..dcd45374e6142 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: 2025-01-24 +date: 2025-01-27 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 740a890674612..ef8f2d367e716 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: 2025-01-24 +date: 2025-01-27 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 3b223390a14e2..8f65865ae7fdd 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: 2025-01-24 +date: 2025-01-27 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 0f62e063a636a..ef1840f3c2794 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: 2025-01-24 +date: 2025-01-27 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 e4b4c47d3b875..8952c4744303c 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: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-url-state'] --- import kbnMlUrlStateObj from './kbn_ml_url_state.devdocs.json'; diff --git a/api_docs/kbn_ml_validators.mdx b/api_docs/kbn_ml_validators.mdx index 0d15d74f8e85a..468d4be2abae9 100644 --- a/api_docs/kbn_ml_validators.mdx +++ b/api_docs/kbn_ml_validators.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-validators title: "@kbn/ml-validators" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-validators plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-validators'] --- import kbnMlValidatorsObj from './kbn_ml_validators.devdocs.json'; diff --git a/api_docs/kbn_mock_idp_utils.mdx b/api_docs/kbn_mock_idp_utils.mdx index 94a2a7c2fcf4e..62370a6bb5408 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: 2025-01-24 +date: 2025-01-27 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 75e53f9613c51..bf6a2790fe408 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: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/monaco'] --- import kbnMonacoObj from './kbn_monaco.devdocs.json'; diff --git a/api_docs/kbn_object_utils.mdx b/api_docs/kbn_object_utils.mdx index 6e0bcefd066a1..df05593d6e1a4 100644 --- a/api_docs/kbn_object_utils.mdx +++ b/api_docs/kbn_object_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-object-utils title: "@kbn/object-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/object-utils plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/object-utils'] --- import kbnObjectUtilsObj from './kbn_object_utils.devdocs.json'; diff --git a/api_docs/kbn_object_versioning.mdx b/api_docs/kbn_object_versioning.mdx index e494b43cde77b..1d570f1397021 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: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/object-versioning'] --- import kbnObjectVersioningObj from './kbn_object_versioning.devdocs.json'; diff --git a/api_docs/kbn_object_versioning_utils.mdx b/api_docs/kbn_object_versioning_utils.mdx index d5f89c8792b2b..32afbebd867c3 100644 --- a/api_docs/kbn_object_versioning_utils.mdx +++ b/api_docs/kbn_object_versioning_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-object-versioning-utils title: "@kbn/object-versioning-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/object-versioning-utils plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/object-versioning-utils'] --- import kbnObjectVersioningUtilsObj from './kbn_object_versioning_utils.devdocs.json'; diff --git a/api_docs/kbn_observability_alert_details.mdx b/api_docs/kbn_observability_alert_details.mdx index b538b64dce1ab..183cdb7e16426 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: 2025-01-24 +date: 2025-01-27 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_rule_utils.mdx b/api_docs/kbn_observability_alerting_rule_utils.mdx index 460b6c77a3e30..79a2b0bee3fcb 100644 --- a/api_docs/kbn_observability_alerting_rule_utils.mdx +++ b/api_docs/kbn_observability_alerting_rule_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-observability-alerting-rule-utils title: "@kbn/observability-alerting-rule-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/observability-alerting-rule-utils plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/observability-alerting-rule-utils'] --- import kbnObservabilityAlertingRuleUtilsObj from './kbn_observability_alerting_rule_utils.devdocs.json'; diff --git a/api_docs/kbn_observability_alerting_test_data.mdx b/api_docs/kbn_observability_alerting_test_data.mdx index 7bc7b94b58967..b1fdff2d50638 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: 2025-01-24 +date: 2025-01-27 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 c681d6745c59e..c5856f2ec279e 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: 2025-01-24 +date: 2025-01-27 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_observability_logs_overview.mdx b/api_docs/kbn_observability_logs_overview.mdx index 17bbceec801f6..e886509b47673 100644 --- a/api_docs/kbn_observability_logs_overview.mdx +++ b/api_docs/kbn_observability_logs_overview.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-observability-logs-overview title: "@kbn/observability-logs-overview" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/observability-logs-overview plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/observability-logs-overview'] --- import kbnObservabilityLogsOverviewObj from './kbn_observability_logs_overview.devdocs.json'; diff --git a/api_docs/kbn_observability_synthetics_test_data.mdx b/api_docs/kbn_observability_synthetics_test_data.mdx index c5b4991cee8f5..20fbce803ba28 100644 --- a/api_docs/kbn_observability_synthetics_test_data.mdx +++ b/api_docs/kbn_observability_synthetics_test_data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-observability-synthetics-test-data title: "@kbn/observability-synthetics-test-data" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/observability-synthetics-test-data plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/observability-synthetics-test-data'] --- import kbnObservabilitySyntheticsTestDataObj from './kbn_observability_synthetics_test_data.devdocs.json'; diff --git a/api_docs/kbn_openapi_bundler.mdx b/api_docs/kbn_openapi_bundler.mdx index 542f97b319116..10b7f681a0306 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: 2025-01-24 +date: 2025-01-27 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 1241ea81bb339..32b1089b5389b 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: 2025-01-24 +date: 2025-01-27 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 0344137101087..11d9a7f50acac 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: 2025-01-24 +date: 2025-01-27 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 773fafa794a1d..62f6ec1bf86c0 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: 2025-01-24 +date: 2025-01-27 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 1e945b54e5e46..647f7f8b7bf21 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: 2025-01-24 +date: 2025-01-27 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_palettes.mdx b/api_docs/kbn_palettes.mdx index e6ebee2c84525..2b012e7f5f80f 100644 --- a/api_docs/kbn_palettes.mdx +++ b/api_docs/kbn_palettes.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-palettes title: "@kbn/palettes" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/palettes plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/palettes'] --- import kbnPalettesObj from './kbn_palettes.devdocs.json'; diff --git a/api_docs/kbn_panel_loader.mdx b/api_docs/kbn_panel_loader.mdx index 28b970d885f58..caf16d5ac95a2 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: 2025-01-24 +date: 2025-01-27 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 87cd586a8f401..8a7ab02841d1d 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: 2025-01-24 +date: 2025-01-27 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 6945b89a1dedd..4c6be7ea67f81 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: 2025-01-24 +date: 2025-01-27 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 1026d88a262de..e5bf611613575 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: 2025-01-24 +date: 2025-01-27 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 147ccaf2ba061..0c65665b70c09 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: 2025-01-24 +date: 2025-01-27 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 d072761f36626..dddaa344878d9 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: 2025-01-24 +date: 2025-01-27 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 82653e3be3837..6dd5f84b9d0de 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: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/presentation-publishing'] --- import kbnPresentationPublishingObj from './kbn_presentation_publishing.devdocs.json'; diff --git a/api_docs/kbn_product_doc_artifact_builder.mdx b/api_docs/kbn_product_doc_artifact_builder.mdx index bf44a28689581..aac2d0f8d83b0 100644 --- a/api_docs/kbn_product_doc_artifact_builder.mdx +++ b/api_docs/kbn_product_doc_artifact_builder.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-product-doc-artifact-builder title: "@kbn/product-doc-artifact-builder" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/product-doc-artifact-builder plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/product-doc-artifact-builder'] --- import kbnProductDocArtifactBuilderObj from './kbn_product_doc_artifact_builder.devdocs.json'; diff --git a/api_docs/kbn_product_doc_common.mdx b/api_docs/kbn_product_doc_common.mdx index 844216a2f81e1..f45f12bb958b4 100644 --- a/api_docs/kbn_product_doc_common.mdx +++ b/api_docs/kbn_product_doc_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-product-doc-common title: "@kbn/product-doc-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/product-doc-common plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/product-doc-common'] --- import kbnProductDocCommonObj from './kbn_product_doc_common.devdocs.json'; diff --git a/api_docs/kbn_profiling_utils.mdx b/api_docs/kbn_profiling_utils.mdx index 8a46bea085148..7d81269989ed9 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: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/profiling-utils'] --- import kbnProfilingUtilsObj from './kbn_profiling_utils.devdocs.json'; diff --git a/api_docs/kbn_random_sampling.devdocs.json b/api_docs/kbn_random_sampling.devdocs.json index ae4576fd3e309..57e3ea2c25fba 100644 --- a/api_docs/kbn_random_sampling.devdocs.json +++ b/api_docs/kbn_random_sampling.devdocs.json @@ -120,7 +120,7 @@ "Allowed values to show on the Control Slider" ], "signature": [ - "number[]" + "{ label: string; value: number; accessibleLabel?: string | undefined; }[]" ], "path": "x-pack/platform/packages/private/kbn-random-sampling/src/ui/slider_control/index.tsx", "deprecated": false, diff --git a/api_docs/kbn_random_sampling.mdx b/api_docs/kbn_random_sampling.mdx index c687965f90991..124042fc4f3d1 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: 2025-01-24 +date: 2025-01-27 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 3b87d88fab5d2..f5db4e8dff97f 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: 2025-01-24 +date: 2025-01-27 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 fbf13b00852f8..3550e39e9e6fa 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: 2025-01-24 +date: 2025-01-27 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 f3f1bd6d8bdad..9280adfa00812 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: 2025-01-24 +date: 2025-01-27 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 ca1c40a7cc334..1bd5cffc3ecda 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: 2025-01-24 +date: 2025-01-27 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 3189deba488af..f753610630922 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: 2025-01-24 +date: 2025-01-27 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 4765ae86f71e6..10d25a0a43308 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: 2025-01-24 +date: 2025-01-27 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 4089a6f38f06a..87e46083b5bbe 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: 2025-01-24 +date: 2025-01-27 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 c627deb3cc9be..8b6426df24a3b 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: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/react-kibana-mount'] --- import kbnReactKibanaMountObj from './kbn_react_kibana_mount.devdocs.json'; diff --git a/api_docs/kbn_react_mute_legacy_root_warning.mdx b/api_docs/kbn_react_mute_legacy_root_warning.mdx index 78eed755318cb..cb69f06aff320 100644 --- a/api_docs/kbn_react_mute_legacy_root_warning.mdx +++ b/api_docs/kbn_react_mute_legacy_root_warning.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-react-mute-legacy-root-warning title: "@kbn/react-mute-legacy-root-warning" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/react-mute-legacy-root-warning plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/react-mute-legacy-root-warning'] --- import kbnReactMuteLegacyRootWarningObj from './kbn_react_mute_legacy_root_warning.devdocs.json'; diff --git a/api_docs/kbn_recently_accessed.mdx b/api_docs/kbn_recently_accessed.mdx index b0e9b56dbd51e..0efdb4d6c94b0 100644 --- a/api_docs/kbn_recently_accessed.mdx +++ b/api_docs/kbn_recently_accessed.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-recently-accessed title: "@kbn/recently-accessed" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/recently-accessed plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/recently-accessed'] --- import kbnRecentlyAccessedObj from './kbn_recently_accessed.devdocs.json'; diff --git a/api_docs/kbn_relocate.mdx b/api_docs/kbn_relocate.mdx index 7c3357b6d1665..52afbfda90700 100644 --- a/api_docs/kbn_relocate.mdx +++ b/api_docs/kbn_relocate.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-relocate title: "@kbn/relocate" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/relocate plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/relocate'] --- import kbnRelocateObj from './kbn_relocate.devdocs.json'; diff --git a/api_docs/kbn_repo_file_maps.mdx b/api_docs/kbn_repo_file_maps.mdx index c6be7480319f5..6166985212f79 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: 2025-01-24 +date: 2025-01-27 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 112db87c569c2..96d4a46749509 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: 2025-01-24 +date: 2025-01-27 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 77931ef2efa9f..16ca22a0c764a 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: 2025-01-24 +date: 2025-01-27 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 616d890f8627e..abbb644530f23 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: 2025-01-24 +date: 2025-01-27 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 03f23b680cce6..dfdffd9f13366 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: 2025-01-24 +date: 2025-01-27 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 f3a866cf97e8c..9b77132d51862 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: 2025-01-24 +date: 2025-01-27 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 eea0757b6ab61..b576bb0f656f8 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: 2025-01-24 +date: 2025-01-27 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 262735fd7bad9..41c6e32d0bc5a 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: 2025-01-24 +date: 2025-01-27 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 998e6b7b921a4..0b31dc1374cbb 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: 2025-01-24 +date: 2025-01-27 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 6d1f89aa90cb4..05e2469da6a58 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: 2025-01-24 +date: 2025-01-27 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 0de1a1e6fcdfa..4a225d1023bd3 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: 2025-01-24 +date: 2025-01-27 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 869f281b78726..5bc55f3b1a92e 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: 2025-01-24 +date: 2025-01-27 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 4914500c33981..ee087c9e4c55a 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: 2025-01-24 +date: 2025-01-27 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 6e113ff83f270..36d636d51bc91 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: 2025-01-24 +date: 2025-01-27 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 be36a27fda3ff..1730909fc7883 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: 2025-01-24 +date: 2025-01-27 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 b2e72af5f814f..8175fb3fff524 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: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/resizable-layout'] --- import kbnResizableLayoutObj from './kbn_resizable_layout.devdocs.json'; diff --git a/api_docs/kbn_response_ops_rule_form.mdx b/api_docs/kbn_response_ops_rule_form.mdx index c4c5d6019381b..3e28e34075397 100644 --- a/api_docs/kbn_response_ops_rule_form.mdx +++ b/api_docs/kbn_response_ops_rule_form.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-response-ops-rule-form title: "@kbn/response-ops-rule-form" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/response-ops-rule-form plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/response-ops-rule-form'] --- import kbnResponseOpsRuleFormObj from './kbn_response_ops_rule_form.devdocs.json'; diff --git a/api_docs/kbn_response_ops_rule_params.mdx b/api_docs/kbn_response_ops_rule_params.mdx index d48e330508585..e940267582d22 100644 --- a/api_docs/kbn_response_ops_rule_params.mdx +++ b/api_docs/kbn_response_ops_rule_params.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-response-ops-rule-params title: "@kbn/response-ops-rule-params" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/response-ops-rule-params plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/response-ops-rule-params'] --- import kbnResponseOpsRuleParamsObj from './kbn_response_ops_rule_params.devdocs.json'; diff --git a/api_docs/kbn_rison.mdx b/api_docs/kbn_rison.mdx index 600c7cfc115f2..7a5470a46e95f 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: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/rison'] --- import kbnRisonObj from './kbn_rison.devdocs.json'; diff --git a/api_docs/kbn_rollup.mdx b/api_docs/kbn_rollup.mdx index 3e0319270537d..a4c6d65faa086 100644 --- a/api_docs/kbn_rollup.mdx +++ b/api_docs/kbn_rollup.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-rollup title: "@kbn/rollup" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/rollup plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/rollup'] --- import kbnRollupObj from './kbn_rollup.devdocs.json'; diff --git a/api_docs/kbn_router_to_openapispec.mdx b/api_docs/kbn_router_to_openapispec.mdx index df8da791070c5..b7e79ade6aaa8 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: 2025-01-24 +date: 2025-01-27 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 0d8cd0d625ab3..16870e7cea64e 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: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/router-utils'] --- import kbnRouterUtilsObj from './kbn_router_utils.devdocs.json'; diff --git a/api_docs/kbn_rrule.devdocs.json b/api_docs/kbn_rrule.devdocs.json index a23407ad0bb04..adc2d8fafcc4a 100644 --- a/api_docs/kbn_rrule.devdocs.json +++ b/api_docs/kbn_rrule.devdocs.json @@ -203,6 +203,40 @@ } ], "returnComment": [] + }, + { + "parentPluginId": "@kbn/rrule", + "id": "def-common.RRule.isValid", + "type": "Function", + "tags": [], + "label": "isValid", + "description": [], + "signature": [ + "(options: ", + "ConstructorOptions", + ") => boolean" + ], + "path": "src/platform/packages/shared/kbn-rrule/rrule.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/rrule", + "id": "def-common.RRule.isValid.$1", + "type": "CompoundType", + "tags": [], + "label": "options", + "description": [], + "signature": [ + "ConstructorOptions" + ], + "path": "src/platform/packages/shared/kbn-rrule/rrule.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] } ], "initialIsOpen": false diff --git a/api_docs/kbn_rrule.mdx b/api_docs/kbn_rrule.mdx index edb2132e55736..4537f8e936a2b 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: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/rrule'] --- import kbnRruleObj from './kbn_rrule.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/response-ops](https://github.com/orgs/elastic/teams/response-o | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 16 | 0 | 16 | 1 | +| 18 | 0 | 18 | 2 | ## Common diff --git a/api_docs/kbn_rule_data_utils.mdx b/api_docs/kbn_rule_data_utils.mdx index bf3475908f1e4..fcef6936fa1c8 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: 2025-01-24 +date: 2025-01-27 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 842095fc54e54..9155e08fc00a9 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: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/saved-objects-settings'] --- import kbnSavedObjectsSettingsObj from './kbn_saved_objects_settings.devdocs.json'; diff --git a/api_docs/kbn_saved_search_component.mdx b/api_docs/kbn_saved_search_component.mdx index b9f5c7783f1b2..6f4c430536622 100644 --- a/api_docs/kbn_saved_search_component.mdx +++ b/api_docs/kbn_saved_search_component.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-saved-search-component title: "@kbn/saved-search-component" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/saved-search-component plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/saved-search-component'] --- import kbnSavedSearchComponentObj from './kbn_saved_search_component.devdocs.json'; diff --git a/api_docs/kbn_scout.mdx b/api_docs/kbn_scout.mdx index ac23375e41a8b..300d94a600e74 100644 --- a/api_docs/kbn_scout.mdx +++ b/api_docs/kbn_scout.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-scout title: "@kbn/scout" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/scout plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/scout'] --- import kbnScoutObj from './kbn_scout.devdocs.json'; diff --git a/api_docs/kbn_scout_info.mdx b/api_docs/kbn_scout_info.mdx index 7638982b80324..c655d76ecd78c 100644 --- a/api_docs/kbn_scout_info.mdx +++ b/api_docs/kbn_scout_info.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-scout-info title: "@kbn/scout-info" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/scout-info plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/scout-info'] --- import kbnScoutInfoObj from './kbn_scout_info.devdocs.json'; diff --git a/api_docs/kbn_scout_reporting.mdx b/api_docs/kbn_scout_reporting.mdx index 532bf0e3b826a..6ae7d30020fde 100644 --- a/api_docs/kbn_scout_reporting.mdx +++ b/api_docs/kbn_scout_reporting.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-scout-reporting title: "@kbn/scout-reporting" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/scout-reporting plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/scout-reporting'] --- import kbnScoutReportingObj from './kbn_scout_reporting.devdocs.json'; diff --git a/api_docs/kbn_screenshotting_server.mdx b/api_docs/kbn_screenshotting_server.mdx index a2b9ce9b17485..448d3b274d37b 100644 --- a/api_docs/kbn_screenshotting_server.mdx +++ b/api_docs/kbn_screenshotting_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-screenshotting-server title: "@kbn/screenshotting-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/screenshotting-server plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/screenshotting-server'] --- import kbnScreenshottingServerObj from './kbn_screenshotting_server.devdocs.json'; diff --git a/api_docs/kbn_search_api_keys_components.mdx b/api_docs/kbn_search_api_keys_components.mdx index 58f0a382ffdc2..7f93f446f3f66 100644 --- a/api_docs/kbn_search_api_keys_components.mdx +++ b/api_docs/kbn_search_api_keys_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-search-api-keys-components title: "@kbn/search-api-keys-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/search-api-keys-components plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/search-api-keys-components'] --- import kbnSearchApiKeysComponentsObj from './kbn_search_api_keys_components.devdocs.json'; diff --git a/api_docs/kbn_search_api_keys_server.mdx b/api_docs/kbn_search_api_keys_server.mdx index 05eed46256d82..0cf16e967aa1a 100644 --- a/api_docs/kbn_search_api_keys_server.mdx +++ b/api_docs/kbn_search_api_keys_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-search-api-keys-server title: "@kbn/search-api-keys-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/search-api-keys-server plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/search-api-keys-server'] --- import kbnSearchApiKeysServerObj from './kbn_search_api_keys_server.devdocs.json'; diff --git a/api_docs/kbn_search_api_panels.mdx b/api_docs/kbn_search_api_panels.mdx index 6316348a444f5..a8f2bcbe082a2 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: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/search-api-panels'] --- import kbnSearchApiPanelsObj from './kbn_search_api_panels.devdocs.json'; diff --git a/api_docs/kbn_search_connectors.mdx b/api_docs/kbn_search_connectors.mdx index 2a9ffc4d96d0c..07fc5ff39b7bd 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: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/search-connectors'] --- import kbnSearchConnectorsObj from './kbn_search_connectors.devdocs.json'; diff --git a/api_docs/kbn_search_errors.mdx b/api_docs/kbn_search_errors.mdx index 2678d8ace4271..5f4b2505956db 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: 2025-01-24 +date: 2025-01-27 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 39c2c37a6ab14..9a272a38416b4 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: 2025-01-24 +date: 2025-01-27 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 30b14abc7a443..25b7f9a036868 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: 2025-01-24 +date: 2025-01-27 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_shared_ui.mdx b/api_docs/kbn_search_shared_ui.mdx index ab52d47ae105b..fc500a613440d 100644 --- a/api_docs/kbn_search_shared_ui.mdx +++ b/api_docs/kbn_search_shared_ui.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-search-shared-ui title: "@kbn/search-shared-ui" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/search-shared-ui plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/search-shared-ui'] --- import kbnSearchSharedUiObj from './kbn_search_shared_ui.devdocs.json'; diff --git a/api_docs/kbn_search_types.mdx b/api_docs/kbn_search_types.mdx index 2118ecaa9e876..5c147fda578ab 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: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/search-types'] --- import kbnSearchTypesObj from './kbn_search_types.devdocs.json'; diff --git a/api_docs/kbn_security_api_key_management.mdx b/api_docs/kbn_security_api_key_management.mdx index 5d9fd97e181c1..b304be3ac6001 100644 --- a/api_docs/kbn_security_api_key_management.mdx +++ b/api_docs/kbn_security_api_key_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-security-api-key-management title: "@kbn/security-api-key-management" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/security-api-key-management plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-api-key-management'] --- import kbnSecurityApiKeyManagementObj from './kbn_security_api_key_management.devdocs.json'; diff --git a/api_docs/kbn_security_authorization_core.mdx b/api_docs/kbn_security_authorization_core.mdx index 87d886f605066..70cd8b7d8f619 100644 --- a/api_docs/kbn_security_authorization_core.mdx +++ b/api_docs/kbn_security_authorization_core.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-security-authorization-core title: "@kbn/security-authorization-core" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/security-authorization-core plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-authorization-core'] --- import kbnSecurityAuthorizationCoreObj from './kbn_security_authorization_core.devdocs.json'; diff --git a/api_docs/kbn_security_authorization_core_common.mdx b/api_docs/kbn_security_authorization_core_common.mdx index 2de70a5a06684..994e23859316b 100644 --- a/api_docs/kbn_security_authorization_core_common.mdx +++ b/api_docs/kbn_security_authorization_core_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-security-authorization-core-common title: "@kbn/security-authorization-core-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/security-authorization-core-common plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-authorization-core-common'] --- import kbnSecurityAuthorizationCoreCommonObj from './kbn_security_authorization_core_common.devdocs.json'; diff --git a/api_docs/kbn_security_form_components.mdx b/api_docs/kbn_security_form_components.mdx index 20783a4fb86df..ee8591a920286 100644 --- a/api_docs/kbn_security_form_components.mdx +++ b/api_docs/kbn_security_form_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-security-form-components title: "@kbn/security-form-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/security-form-components plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-form-components'] --- import kbnSecurityFormComponentsObj from './kbn_security_form_components.devdocs.json'; diff --git a/api_docs/kbn_security_hardening.mdx b/api_docs/kbn_security_hardening.mdx index 3600fdb8af660..54b73e6c69aca 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: 2025-01-24 +date: 2025-01-27 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 f3f262ef3b2df..bc63d898b7650 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: 2025-01-24 +date: 2025-01-27 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 e69f384827eea..9503e97686709 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: 2025-01-24 +date: 2025-01-27 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 f2bf1c4ce4e2b..6bb7c017b365c 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: 2025-01-24 +date: 2025-01-27 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_role_management_model.mdx b/api_docs/kbn_security_role_management_model.mdx index 2d06c7be66472..233d8319bdf44 100644 --- a/api_docs/kbn_security_role_management_model.mdx +++ b/api_docs/kbn_security_role_management_model.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-security-role-management-model title: "@kbn/security-role-management-model" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/security-role-management-model plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-role-management-model'] --- import kbnSecurityRoleManagementModelObj from './kbn_security_role_management_model.devdocs.json'; diff --git a/api_docs/kbn_security_solution_connectors.devdocs.json b/api_docs/kbn_security_solution_connectors.devdocs.json new file mode 100644 index 0000000000000..772f9fef0d45f --- /dev/null +++ b/api_docs/kbn_security_solution_connectors.devdocs.json @@ -0,0 +1,174 @@ +{ + "id": "@kbn/security-solution-connectors", + "client": { + "classes": [], + "functions": [ + { + "parentPluginId": "@kbn/security-solution-connectors", + "id": "def-public.ConnectorSelector", + "type": "Function", + "tags": [], + "label": "ConnectorSelector", + "description": [], + "signature": [ + "React.NamedExoticComponent<", + { + "pluginId": "@kbn/security-solution-connectors", + "scope": "public", + "docId": "kibKbnSecuritySolutionConnectorsPluginApi", + "section": "def-public.ConnectorSelectorProps", + "text": "ConnectorSelectorProps" + }, + ">" + ], + "path": "x-pack/solutions/security/packages/connectors/src/connector_selector.tsx", + "deprecated": false, + "trackAdoption": false, + "returnComment": [], + "children": [ + { + "parentPluginId": "@kbn/security-solution-connectors", + "id": "def-public.ConnectorSelector.$1", + "type": "Uncategorized", + "tags": [], + "label": "props", + "description": [], + "signature": [ + "P" + ], + "path": "node_modules/@types/react/ts5.0/index.d.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + } + ], + "interfaces": [ + { + "parentPluginId": "@kbn/security-solution-connectors", + "id": "def-public.ConnectorSelectorProps", + "type": "Interface", + "tags": [], + "label": "ConnectorSelectorProps", + "description": [], + "path": "x-pack/solutions/security/packages/connectors/src/connector_selector.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/security-solution-connectors", + "id": "def-public.ConnectorSelectorProps.connectors", + "type": "Array", + "tags": [], + "label": "connectors", + "description": [], + "signature": [ + "ConnectorDetails", + "[]" + ], + "path": "x-pack/solutions/security/packages/connectors/src/connector_selector.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/security-solution-connectors", + "id": "def-public.ConnectorSelectorProps.onChange", + "type": "Function", + "tags": [], + "label": "onChange", + "description": [], + "signature": [ + "(connectorId: string) => void" + ], + "path": "x-pack/solutions/security/packages/connectors/src/connector_selector.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/security-solution-connectors", + "id": "def-public.ConnectorSelectorProps.onChange.$1", + "type": "string", + "tags": [], + "label": "connectorId", + "description": [], + "signature": [ + "string" + ], + "path": "x-pack/solutions/security/packages/connectors/src/connector_selector.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/security-solution-connectors", + "id": "def-public.ConnectorSelectorProps.selectedId", + "type": "string", + "tags": [], + "label": "selectedId", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "x-pack/solutions/security/packages/connectors/src/connector_selector.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/security-solution-connectors", + "id": "def-public.ConnectorSelectorProps.onNewConnectorClicked", + "type": "Function", + "tags": [], + "label": "onNewConnectorClicked", + "description": [], + "signature": [ + "(() => void) | undefined" + ], + "path": "x-pack/solutions/security/packages/connectors/src/connector_selector.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/security-solution-connectors", + "id": "def-public.ConnectorSelectorProps.isDisabled", + "type": "CompoundType", + "tags": [], + "label": "isDisabled", + "description": [], + "signature": [ + "boolean | undefined" + ], + "path": "x-pack/solutions/security/packages/connectors/src/connector_selector.tsx", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + } + ], + "enums": [], + "misc": [], + "objects": [] + }, + "server": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "common": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + } +} \ No newline at end of file diff --git a/api_docs/kbn_security_solution_connectors.mdx b/api_docs/kbn_security_solution_connectors.mdx new file mode 100644 index 0000000000000..a1a7ca55b09bf --- /dev/null +++ b/api_docs/kbn_security_solution_connectors.mdx @@ -0,0 +1,33 @@ +--- +#### +#### This document is auto-generated and is meant to be viewed inside our experimental, new docs system. +#### Reach out in #docs-engineering for more info. +#### +id: kibKbnSecuritySolutionConnectorsPluginApi +slug: /kibana-dev-docs/api/kbn-security-solution-connectors +title: "@kbn/security-solution-connectors" +image: https://source.unsplash.com/400x175/?github +description: API docs for the @kbn/security-solution-connectors plugin +date: 2025-01-27 +tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-solution-connectors'] +--- +import kbnSecuritySolutionConnectorsObj from './kbn_security_solution_connectors.devdocs.json'; + + + +Contact [@elastic/security-threat-hunting-explore](https://github.com/orgs/elastic/teams/security-threat-hunting-explore) for questions regarding this plugin. + +**Code health stats** + +| Public API count | Any count | Items lacking comments | Missing exports | +|-------------------|-----------|------------------------|-----------------| +| 9 | 0 | 8 | 1 | + +## Client + +### Functions + + +### Interfaces + + diff --git a/api_docs/kbn_security_solution_distribution_bar.mdx b/api_docs/kbn_security_solution_distribution_bar.mdx index afb5e09dba7bc..17b8530af2ca8 100644 --- a/api_docs/kbn_security_solution_distribution_bar.mdx +++ b/api_docs/kbn_security_solution_distribution_bar.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-security-solution-distribution-bar title: "@kbn/security-solution-distribution-bar" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/security-solution-distribution-bar plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-solution-distribution-bar'] --- import kbnSecuritySolutionDistributionBarObj from './kbn_security_solution_distribution_bar.devdocs.json'; diff --git a/api_docs/kbn_security_solution_features.mdx b/api_docs/kbn_security_solution_features.mdx index 4bce4f8ed73b2..014a53c1cc787 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: 2025-01-24 +date: 2025-01-27 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 715f3627c2111..b3e5d8513aa78 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: 2025-01-24 +date: 2025-01-27 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 3becec02010b3..a78101eaafa52 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: 2025-01-24 +date: 2025-01-27 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 85aebd42b68ab..b81703bd5bbd5 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: 2025-01-24 +date: 2025-01-27 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_security_ui_components.mdx b/api_docs/kbn_security_ui_components.mdx index e3813d4139323..5516fc3c11943 100644 --- a/api_docs/kbn_security_ui_components.mdx +++ b/api_docs/kbn_security_ui_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-security-ui-components title: "@kbn/security-ui-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/security-ui-components plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-ui-components'] --- import kbnSecurityUiComponentsObj from './kbn_security_ui_components.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_autocomplete.mdx b/api_docs/kbn_securitysolution_autocomplete.mdx index 6d9deec819b8d..15866e1013f66 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: 2025-01-24 +date: 2025-01-27 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 4855f7f712d60..56888972aaff2 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: 2025-01-24 +date: 2025-01-27 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 216d0d84564c9..fb047cda8db79 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: 2025-01-24 +date: 2025-01-27 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 c0a735e0b2336..e06d66a870ed0 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: 2025-01-24 +date: 2025-01-27 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 d8620be2f1779..9805e953c845d 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: 2025-01-24 +date: 2025-01-27 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_hook_utils.mdx b/api_docs/kbn_securitysolution_hook_utils.mdx index 59d3c71799f43..02c0eccba5403 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: 2025-01-24 +date: 2025-01-27 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 65af7cbc5929a..fd264e8925fe2 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: 2025-01-24 +date: 2025-01-27 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 eef47e4559b31..b666e112d1022 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: 2025-01-24 +date: 2025-01-27 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 92a0975d577ec..28541a5d7af70 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: 2025-01-24 +date: 2025-01-27 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 8df147fab29d9..b76714d501b40 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: 2025-01-24 +date: 2025-01-27 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 d436be5d55a62..77745e32a1c3b 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: 2025-01-24 +date: 2025-01-27 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 bb013980d6316..c09f97d6ba5a3 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: 2025-01-24 +date: 2025-01-27 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 4b2112ec8a747..96e9438e07cff 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: 2025-01-24 +date: 2025-01-27 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 0ad5ad86ab82e..c0493d4c482f6 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: 2025-01-24 +date: 2025-01-27 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 fc86c8e030da8..1a09498d167a2 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: 2025-01-24 +date: 2025-01-27 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 8587ec3aa82c0..f350776c91e12 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: 2025-01-24 +date: 2025-01-27 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 fbdf4216ae879..208806f481873 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: 2025-01-24 +date: 2025-01-27 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 9275996871ebe..f6ca54209ee3e 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: 2025-01-24 +date: 2025-01-27 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 ea77c146ca4bd..971f01d7196cd 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: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/server-route-repository'] --- import kbnServerRouteRepositoryObj from './kbn_server_route_repository.devdocs.json'; diff --git a/api_docs/kbn_server_route_repository_client.mdx b/api_docs/kbn_server_route_repository_client.mdx index f78c492104ff4..d0775d04b9d5e 100644 --- a/api_docs/kbn_server_route_repository_client.mdx +++ b/api_docs/kbn_server_route_repository_client.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-server-route-repository-client title: "@kbn/server-route-repository-client" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/server-route-repository-client plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/server-route-repository-client'] --- import kbnServerRouteRepositoryClientObj from './kbn_server_route_repository_client.devdocs.json'; diff --git a/api_docs/kbn_server_route_repository_utils.mdx b/api_docs/kbn_server_route_repository_utils.mdx index f86dfa34d4ce8..75ea1c49e04b1 100644 --- a/api_docs/kbn_server_route_repository_utils.mdx +++ b/api_docs/kbn_server_route_repository_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-server-route-repository-utils title: "@kbn/server-route-repository-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/server-route-repository-utils plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/server-route-repository-utils'] --- import kbnServerRouteRepositoryUtilsObj from './kbn_server_route_repository_utils.devdocs.json'; diff --git a/api_docs/kbn_serverless_common_settings.mdx b/api_docs/kbn_serverless_common_settings.mdx index 9651b260086a7..115d7ed97255a 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: 2025-01-24 +date: 2025-01-27 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 a42e17dffc053..3d9960e1222e2 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: 2025-01-24 +date: 2025-01-27 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 8c33e40853255..b5c02b722e868 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: 2025-01-24 +date: 2025-01-27 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 b311a5b2b9fa4..f59b5c78c00ff 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: 2025-01-24 +date: 2025-01-27 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 381ed4e3a3eec..ce8a473b0299e 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: 2025-01-24 +date: 2025-01-27 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 6a6fd191d5ab3..dbb5bee79810b 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: 2025-01-24 +date: 2025-01-27 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 91111651db820..5df8c081b36ba 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: 2025-01-24 +date: 2025-01-27 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.devdocs.json b/api_docs/kbn_shared_ux_avatar_solution.devdocs.json index 4b4d59baf59bd..c60821f47baac 100644 --- a/api_docs/kbn_shared_ux_avatar_solution.devdocs.json +++ b/api_docs/kbn_shared_ux_avatar_solution.devdocs.json @@ -1,27 +1,11 @@ { "id": "@kbn/shared-ux-avatar-solution", "client": { - "classes": [], - "functions": [], - "interfaces": [], - "enums": [], - "misc": [], - "objects": [] - }, - "server": { - "classes": [], - "functions": [], - "interfaces": [], - "enums": [], - "misc": [], - "objects": [] - }, - "common": { "classes": [], "functions": [ { "parentPluginId": "@kbn/shared-ux-avatar-solution", - "id": "def-common.KibanaSolutionAvatar", + "id": "def-public.KibanaSolutionAvatar", "type": "Function", "tags": [], "label": "KibanaSolutionAvatar", @@ -32,9 +16,9 @@ "(props: ", { "pluginId": "@kbn/shared-ux-avatar-solution", - "scope": "common", + "scope": "public", "docId": "kibKbnSharedUxAvatarSolutionPluginApi", - "section": "def-common.KibanaSolutionAvatarProps", + "section": "def-public.KibanaSolutionAvatarProps", "text": "KibanaSolutionAvatarProps" }, ") => React.JSX.Element" @@ -45,7 +29,7 @@ "children": [ { "parentPluginId": "@kbn/shared-ux-avatar-solution", - "id": "def-common.KibanaSolutionAvatar.$1", + "id": "def-public.KibanaSolutionAvatar.$1", "type": "CompoundType", "tags": [], "label": "props", @@ -53,9 +37,9 @@ "signature": [ { "pluginId": "@kbn/shared-ux-avatar-solution", - "scope": "common", + "scope": "public", "docId": "kibKbnSharedUxAvatarSolutionPluginApi", - "section": "def-common.KibanaSolutionAvatarProps", + "section": "def-public.KibanaSolutionAvatarProps", "text": "KibanaSolutionAvatarProps" } ], @@ -74,7 +58,7 @@ "misc": [ { "parentPluginId": "@kbn/shared-ux-avatar-solution", - "id": "def-common.KibanaSolutionAvatarProps", + "id": "def-public.KibanaSolutionAvatarProps", "type": "Type", "tags": [], "label": "KibanaSolutionAvatarProps", @@ -91,5 +75,21 @@ } ], "objects": [] + }, + "server": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "common": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] } } \ No newline at end of file diff --git a/api_docs/kbn_shared_ux_avatar_solution.mdx b/api_docs/kbn_shared_ux_avatar_solution.mdx index 476adcba5132a..7fc7d75b75b04 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: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-avatar-solution'] --- import kbnSharedUxAvatarSolutionObj from './kbn_shared_ux_avatar_solution.devdocs.json'; @@ -23,11 +23,11 @@ Contact [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sh |-------------------|-----------|------------------------|-----------------| | 3 | 0 | 2 | 2 | -## Common +## Client ### Functions - + ### Consts, variables and types - + 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 41c12e0e90325..78f77defae2bb 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: 2025-01-24 +date: 2025-01-27 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 48d277b0dc4e8..053046f9884f3 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: 2025-01-24 +date: 2025-01-27 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 188df2d62cf93..18a86ead7e978 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: 2025-01-24 +date: 2025-01-27 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 22944f769cadc..e65925c3bee29 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: 2025-01-24 +date: 2025-01-27 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 1b9b129b5bc14..a89dbaf3ef853 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: 2025-01-24 +date: 2025-01-27 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 7cf2be4b41aba..b6ac5cff7bc85 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: 2025-01-24 +date: 2025-01-27 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 9799d7104e903..1740ed16301a0 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: 2025-01-24 +date: 2025-01-27 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 d720c8940c78f..7e775ed8fae60 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: 2025-01-24 +date: 2025-01-27 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 42fd78ca1e1e2..1608b56611379 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: 2025-01-24 +date: 2025-01-27 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 e54ba842d5f80..05914b140289b 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: 2025-01-24 +date: 2025-01-27 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 a94044bba3a21..d74c4aee0ab66 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: 2025-01-24 +date: 2025-01-27 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 482983fc52503..787df3fa0c66b 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: 2025-01-24 +date: 2025-01-27 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 7fe55eb06984f..643be58beac10 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: 2025-01-24 +date: 2025-01-27 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 4509ed5b760fc..cb8abf24b0c58 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: 2025-01-24 +date: 2025-01-27 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 0dd8cf515d911..4f6741ebf8e23 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: 2025-01-24 +date: 2025-01-27 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 a6de79203aa6c..1d3fa8d06363a 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: 2025-01-24 +date: 2025-01-27 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 e423609ada2bf..fec3d9f6744fc 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: 2025-01-24 +date: 2025-01-27 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 25bba72511b9b..9b64c9d920a77 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: 2025-01-24 +date: 2025-01-27 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 bb85eb93448bb..4e0fbf50eba09 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: 2025-01-24 +date: 2025-01-27 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 2b96a330f7297..98fb542074c0e 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: 2025-01-24 +date: 2025-01-27 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 db1146b8162c3..62aef2fc9aa2b 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: 2025-01-24 +date: 2025-01-27 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 62117b8172d5d..de709f7e9a44d 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: 2025-01-24 +date: 2025-01-27 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.devdocs.json b/api_docs/kbn_shared_ux_page_kibana_template.devdocs.json index 0e9290d527d72..615cf27af1df3 100644 --- a/api_docs/kbn_shared_ux_page_kibana_template.devdocs.json +++ b/api_docs/kbn_shared_ux_page_kibana_template.devdocs.json @@ -186,9 +186,9 @@ " | undefined; } & { isEmptyState?: boolean | undefined; emptyPageBody?: React.ReactNode; solutionNav?: ", { "pluginId": "@kbn/shared-ux-page-solution-nav", - "scope": "common", + "scope": "public", "docId": "kibKbnSharedUxPageSolutionNavPluginApi", - "section": "def-common.SolutionNavProps", + "section": "def-public.SolutionNavProps", "text": "SolutionNavProps" }, " | undefined; noDataConfig?: ", diff --git a/api_docs/kbn_shared_ux_page_kibana_template.mdx b/api_docs/kbn_shared_ux_page_kibana_template.mdx index c2c7016a167e3..2845768f0b36c 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: 2025-01-24 +date: 2025-01-27 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 0b57be6816f24..921d24cc73f01 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: 2025-01-24 +date: 2025-01-27 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 99dae84a3a070..5b2b2b0be9ecd 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: 2025-01-24 +date: 2025-01-27 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.devdocs.json b/api_docs/kbn_shared_ux_page_no_data_config.devdocs.json index 97a09336048c8..907b4cff40cae 100644 --- a/api_docs/kbn_shared_ux_page_no_data_config.devdocs.json +++ b/api_docs/kbn_shared_ux_page_no_data_config.devdocs.json @@ -146,9 +146,9 @@ " & { solutionNav: ", { "pluginId": "@kbn/shared-ux-page-solution-nav", - "scope": "common", + "scope": "public", "docId": "kibKbnSharedUxPageSolutionNavPluginApi", - "section": "def-common.SolutionNavProps", + "section": "def-public.SolutionNavProps", "text": "SolutionNavProps" }, "; }" 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 3461aa0120f59..4f4ba35a036f7 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: 2025-01-24 +date: 2025-01-27 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 f80add13891a3..91b5b4781d3f7 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: 2025-01-24 +date: 2025-01-27 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 6aee08a1d3307..743a4d607fc66 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: 2025-01-24 +date: 2025-01-27 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.devdocs.json b/api_docs/kbn_shared_ux_page_solution_nav.devdocs.json index 5e0f591f175eb..e2dc1a60cd917 100644 --- a/api_docs/kbn_shared_ux_page_solution_nav.devdocs.json +++ b/api_docs/kbn_shared_ux_page_solution_nav.devdocs.json @@ -1,27 +1,11 @@ { "id": "@kbn/shared-ux-page-solution-nav", "client": { - "classes": [], - "functions": [], - "interfaces": [], - "enums": [], - "misc": [], - "objects": [] - }, - "server": { - "classes": [], - "functions": [], - "interfaces": [], - "enums": [], - "misc": [], - "objects": [] - }, - "common": { "classes": [], "functions": [ { "parentPluginId": "@kbn/shared-ux-page-solution-nav", - "id": "def-common.SolutionNav", + "id": "def-public.SolutionNav", "type": "Function", "tags": [], "label": "SolutionNav", @@ -32,9 +16,9 @@ "({ children, headingProps, icon, isOpenOnDesktop, items, mobileBreakpoints, closeFlyoutButtonPosition, name, onCollapse, canBeCollapsed, ...rest }: ", { "pluginId": "@kbn/shared-ux-page-solution-nav", - "scope": "common", + "scope": "public", "docId": "kibKbnSharedUxPageSolutionNavPluginApi", - "section": "def-common.SolutionNavProps", + "section": "def-public.SolutionNavProps", "text": "SolutionNavProps" }, ") => React.JSX.Element" @@ -45,7 +29,7 @@ "children": [ { "parentPluginId": "@kbn/shared-ux-page-solution-nav", - "id": "def-common.SolutionNav.$1", + "id": "def-public.SolutionNav.$1", "type": "CompoundType", "tags": [], "label": "{\n children,\n headingProps,\n icon,\n isOpenOnDesktop = false,\n items,\n mobileBreakpoints = ['xs', 's'],\n closeFlyoutButtonPosition = 'outside',\n name,\n onCollapse,\n canBeCollapsed = true,\n ...rest\n}", @@ -53,9 +37,9 @@ "signature": [ { "pluginId": "@kbn/shared-ux-page-solution-nav", - "scope": "common", + "scope": "public", "docId": "kibKbnSharedUxPageSolutionNavPluginApi", - "section": "def-common.SolutionNavProps", + "section": "def-public.SolutionNavProps", "text": "SolutionNavProps" } ], @@ -70,7 +54,7 @@ }, { "parentPluginId": "@kbn/shared-ux-page-solution-nav", - "id": "def-common.withSolutionNav", + "id": "def-public.withSolutionNav", "type": "Function", "tags": [], "label": "withSolutionNav", @@ -86,7 +70,7 @@ "children": [ { "parentPluginId": "@kbn/shared-ux-page-solution-nav", - "id": "def-common.withSolutionNav.$1", + "id": "def-public.withSolutionNav.$1", "type": "CompoundType", "tags": [], "label": "WrappedComponent", @@ -109,7 +93,7 @@ "misc": [ { "parentPluginId": "@kbn/shared-ux-page-solution-nav", - "id": "def-common.SolutionNavProps", + "id": "def-public.SolutionNavProps", "type": "Type", "tags": [], "label": "SolutionNavProps", @@ -132,5 +116,21 @@ } ], "objects": [] + }, + "server": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "common": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] } } \ No newline at end of file diff --git a/api_docs/kbn_shared_ux_page_solution_nav.mdx b/api_docs/kbn_shared_ux_page_solution_nav.mdx index 8ecb18c81f9d0..998982c151f0c 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: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-solution-nav'] --- import kbnSharedUxPageSolutionNavObj from './kbn_shared_ux_page_solution_nav.devdocs.json'; @@ -23,11 +23,11 @@ Contact [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sh |-------------------|-----------|------------------------|-----------------| | 5 | 0 | 3 | 1 | -## Common +## Client ### Functions - + ### Consts, variables and types - + 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 a19787c21acfe..3df45616feb01 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: 2025-01-24 +date: 2025-01-27 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 34587826b29f6..f02108afd5990 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: 2025-01-24 +date: 2025-01-27 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 27a91e81da4fc..9f3bcaa9eb0a0 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: 2025-01-24 +date: 2025-01-27 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 d20d785df5746..63330aa9ca23d 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: 2025-01-24 +date: 2025-01-27 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 de4028d4d2f29..097aed32f005b 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: 2025-01-24 +date: 2025-01-27 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 14091bd3464e3..656d89cf6f5bd 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: 2025-01-24 +date: 2025-01-27 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 77952f8d37b0c..01b584401ac11 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: 2025-01-24 +date: 2025-01-27 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 9e8bb3545fb5c..f8fddf6696eea 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: 2025-01-24 +date: 2025-01-27 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_table_persist.mdx b/api_docs/kbn_shared_ux_table_persist.mdx index accc17cfab623..79fa32eb3e290 100644 --- a/api_docs/kbn_shared_ux_table_persist.mdx +++ b/api_docs/kbn_shared_ux_table_persist.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-table-persist title: "@kbn/shared-ux-table-persist" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-table-persist plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-table-persist'] --- import kbnSharedUxTablePersistObj from './kbn_shared_ux_table_persist.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_utility.mdx b/api_docs/kbn_shared_ux_utility.mdx index 9722e1e22b513..7648f56c80c47 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: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-utility'] --- import kbnSharedUxUtilityObj from './kbn_shared_ux_utility.devdocs.json'; diff --git a/api_docs/kbn_slo_schema.mdx b/api_docs/kbn_slo_schema.mdx index 83caf49a60d0f..0cfec6da1dcf7 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: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/slo-schema'] --- import kbnSloSchemaObj from './kbn_slo_schema.devdocs.json'; diff --git a/api_docs/kbn_some_dev_log.mdx b/api_docs/kbn_some_dev_log.mdx index ea823ddbd6e36..33cd510861ce5 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: 2025-01-24 +date: 2025-01-27 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 70ac874d6800c..e9f634821c774 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: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/sort-predicates'] --- import kbnSortPredicatesObj from './kbn_sort_predicates.devdocs.json'; diff --git a/api_docs/kbn_sse_utils.mdx b/api_docs/kbn_sse_utils.mdx index f04b8ffa64f0f..63cdef08d2e67 100644 --- a/api_docs/kbn_sse_utils.mdx +++ b/api_docs/kbn_sse_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-sse-utils title: "@kbn/sse-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/sse-utils plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/sse-utils'] --- import kbnSseUtilsObj from './kbn_sse_utils.devdocs.json'; diff --git a/api_docs/kbn_sse_utils_client.mdx b/api_docs/kbn_sse_utils_client.mdx index c5791ea83e83f..38281ba22407c 100644 --- a/api_docs/kbn_sse_utils_client.mdx +++ b/api_docs/kbn_sse_utils_client.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-sse-utils-client title: "@kbn/sse-utils-client" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/sse-utils-client plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/sse-utils-client'] --- import kbnSseUtilsClientObj from './kbn_sse_utils_client.devdocs.json'; diff --git a/api_docs/kbn_sse_utils_server.mdx b/api_docs/kbn_sse_utils_server.mdx index 30aca73db61af..e8044fff1e7bb 100644 --- a/api_docs/kbn_sse_utils_server.mdx +++ b/api_docs/kbn_sse_utils_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-sse-utils-server title: "@kbn/sse-utils-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/sse-utils-server plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/sse-utils-server'] --- import kbnSseUtilsServerObj from './kbn_sse_utils_server.devdocs.json'; diff --git a/api_docs/kbn_std.mdx b/api_docs/kbn_std.mdx index fd723147fc085..bab701e9da38c 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: 2025-01-24 +date: 2025-01-27 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 ab36e4221b2d7..e56989fef9ca1 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: 2025-01-24 +date: 2025-01-27 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 b24a6f006ede5..e097d899836f3 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: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/storybook'] --- import kbnStorybookObj from './kbn_storybook.devdocs.json'; diff --git a/api_docs/kbn_streams_schema.devdocs.json b/api_docs/kbn_streams_schema.devdocs.json index 2ffa181e5176d..3ad2fa28c96ef 100644 --- a/api_docs/kbn_streams_schema.devdocs.json +++ b/api_docs/kbn_streams_schema.devdocs.json @@ -292,6 +292,39 @@ "returnComment": [], "initialIsOpen": false }, + { + "parentPluginId": "@kbn/streams-schema", + "id": "def-common.getAncestorsAndSelf", + "type": "Function", + "tags": [], + "label": "getAncestorsAndSelf", + "description": [], + "signature": [ + "(id: string) => string[]" + ], + "path": "x-pack/solutions/observability/packages/kbn-streams-schema/src/helpers/hierarchy.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/streams-schema", + "id": "def-common.getAncestorsAndSelf.$1", + "type": "string", + "tags": [], + "label": "id", + "description": [], + "signature": [ + "string" + ], + "path": "x-pack/solutions/observability/packages/kbn-streams-schema/src/helpers/hierarchy.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, { "parentPluginId": "@kbn/streams-schema", "id": "def-common.getParentId", @@ -412,6 +445,39 @@ "returnComment": [], "initialIsOpen": false }, + { + "parentPluginId": "@kbn/streams-schema", + "id": "def-common.getSegments", + "type": "Function", + "tags": [], + "label": "getSegments", + "description": [], + "signature": [ + "(id: string) => string[]" + ], + "path": "x-pack/solutions/observability/packages/kbn-streams-schema/src/helpers/hierarchy.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/streams-schema", + "id": "def-common.getSegments.$1", + "type": "string", + "tags": [], + "label": "id", + "description": [], + "signature": [ + "string" + ], + "path": "x-pack/solutions/observability/packages/kbn-streams-schema/src/helpers/hierarchy.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, { "parentPluginId": "@kbn/streams-schema", "id": "def-common.isAlwaysCondition", @@ -684,6 +750,46 @@ "returnComment": [], "initialIsOpen": false }, + { + "parentPluginId": "@kbn/streams-schema", + "id": "def-common.isDisabledLifecycle", + "type": "Function", + "tags": [], + "label": "isDisabledLifecycle", + "description": [], + "signature": [ + "(value: TValue) => value is Extract" + ], + "path": "x-pack/solutions/observability/packages/kbn-streams-schema/src/models/ingest/lifecycle/index.ts", + "deprecated": false, + "trackAdoption": false, + "returnComment": [], + "children": [ + { + "parentPluginId": "@kbn/streams-schema", + "id": "def-common.isDisabledLifecycle.$1", + "type": "Uncategorized", + "tags": [], + "label": "value", + "description": [], + "signature": [ + "TValue" + ], + "path": "x-pack/solutions/observability/packages/kbn-streams-schema/src/helpers/type_guards.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, { "parentPluginId": "@kbn/streams-schema", "id": "def-common.isDissectProcessorDefinition", @@ -732,6 +838,46 @@ ], "initialIsOpen": false }, + { + "parentPluginId": "@kbn/streams-schema", + "id": "def-common.isDslLifecycle", + "type": "Function", + "tags": [], + "label": "isDslLifecycle", + "description": [], + "signature": [ + "(value: TValue) => value is Extract" + ], + "path": "x-pack/solutions/observability/packages/kbn-streams-schema/src/models/ingest/lifecycle/index.ts", + "deprecated": false, + "trackAdoption": false, + "returnComment": [], + "children": [ + { + "parentPluginId": "@kbn/streams-schema", + "id": "def-common.isDslLifecycle.$1", + "type": "Uncategorized", + "tags": [], + "label": "value", + "description": [], + "signature": [ + "TValue" + ], + "path": "x-pack/solutions/observability/packages/kbn-streams-schema/src/helpers/type_guards.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, { "parentPluginId": "@kbn/streams-schema", "id": "def-common.isFilterCondition", @@ -836,6 +982,46 @@ ], "initialIsOpen": false }, + { + "parentPluginId": "@kbn/streams-schema", + "id": "def-common.isIlmLifecycle", + "type": "Function", + "tags": [], + "label": "isIlmLifecycle", + "description": [], + "signature": [ + "(value: TValue) => value is Extract" + ], + "path": "x-pack/solutions/observability/packages/kbn-streams-schema/src/models/ingest/lifecycle/index.ts", + "deprecated": false, + "trackAdoption": false, + "returnComment": [], + "children": [ + { + "parentPluginId": "@kbn/streams-schema", + "id": "def-common.isIlmLifecycle.$1", + "type": "Uncategorized", + "tags": [], + "label": "value", + "description": [], + "signature": [ + "TValue" + ], + "path": "x-pack/solutions/observability/packages/kbn-streams-schema/src/helpers/type_guards.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, { "parentPluginId": "@kbn/streams-schema", "id": "def-common.isIngestStreamDefinition", @@ -884,6 +1070,46 @@ ], "initialIsOpen": false }, + { + "parentPluginId": "@kbn/streams-schema", + "id": "def-common.isInheritLifecycle", + "type": "Function", + "tags": [], + "label": "isInheritLifecycle", + "description": [], + "signature": [ + "(value: TValue) => value is Extract" + ], + "path": "x-pack/solutions/observability/packages/kbn-streams-schema/src/models/ingest/lifecycle/index.ts", + "deprecated": false, + "trackAdoption": false, + "returnComment": [], + "children": [ + { + "parentPluginId": "@kbn/streams-schema", + "id": "def-common.isInheritLifecycle.$1", + "type": "Uncategorized", + "tags": [], + "label": "value", + "description": [], + "signature": [ + "TValue" + ], + "path": "x-pack/solutions/observability/packages/kbn-streams-schema/src/helpers/type_guards.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, { "parentPluginId": "@kbn/streams-schema", "id": "def-common.isNeverCondition", @@ -2014,40 +2240,54 @@ }, { "parentPluginId": "@kbn/streams-schema", - "id": "def-common.IngestStreamLifecycleDLM", + "id": "def-common.IngestStreamLifecycleDisabled", "type": "Interface", "tags": [], - "label": "IngestStreamLifecycleDLM", + "label": "IngestStreamLifecycleDisabled", "description": [], - "path": "x-pack/solutions/observability/packages/kbn-streams-schema/src/models/ingest/common.ts", + "path": "x-pack/solutions/observability/packages/kbn-streams-schema/src/models/ingest/lifecycle/index.ts", "deprecated": false, "trackAdoption": false, "children": [ { "parentPluginId": "@kbn/streams-schema", - "id": "def-common.IngestStreamLifecycleDLM.type", - "type": "string", + "id": "def-common.IngestStreamLifecycleDisabled.disabled", + "type": "Object", "tags": [], - "label": "type", + "label": "disabled", "description": [], "signature": [ - "\"dlm\"" + "{}" ], - "path": "x-pack/solutions/observability/packages/kbn-streams-schema/src/models/ingest/common.ts", + "path": "x-pack/solutions/observability/packages/kbn-streams-schema/src/models/ingest/lifecycle/index.ts", "deprecated": false, "trackAdoption": false - }, + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/streams-schema", + "id": "def-common.IngestStreamLifecycleDSL", + "type": "Interface", + "tags": [], + "label": "IngestStreamLifecycleDSL", + "description": [], + "path": "x-pack/solutions/observability/packages/kbn-streams-schema/src/models/ingest/lifecycle/index.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ { "parentPluginId": "@kbn/streams-schema", - "id": "def-common.IngestStreamLifecycleDLM.data_retention", - "type": "string", + "id": "def-common.IngestStreamLifecycleDSL.dsl", + "type": "Object", "tags": [], - "label": "data_retention", + "label": "dsl", "description": [], "signature": [ - "string | undefined" + "{ data_retention?: string | undefined; }" ], - "path": "x-pack/solutions/observability/packages/kbn-streams-schema/src/models/ingest/common.ts", + "path": "x-pack/solutions/observability/packages/kbn-streams-schema/src/models/ingest/lifecycle/index.ts", "deprecated": false, "trackAdoption": false } @@ -2061,32 +2301,49 @@ "tags": [], "label": "IngestStreamLifecycleILM", "description": [], - "path": "x-pack/solutions/observability/packages/kbn-streams-schema/src/models/ingest/common.ts", + "path": "x-pack/solutions/observability/packages/kbn-streams-schema/src/models/ingest/lifecycle/index.ts", "deprecated": false, "trackAdoption": false, "children": [ { "parentPluginId": "@kbn/streams-schema", - "id": "def-common.IngestStreamLifecycleILM.type", - "type": "string", + "id": "def-common.IngestStreamLifecycleILM.ilm", + "type": "Object", "tags": [], - "label": "type", + "label": "ilm", "description": [], "signature": [ - "\"ilm\"" + "{ policy: string; }" ], - "path": "x-pack/solutions/observability/packages/kbn-streams-schema/src/models/ingest/common.ts", + "path": "x-pack/solutions/observability/packages/kbn-streams-schema/src/models/ingest/lifecycle/index.ts", "deprecated": false, "trackAdoption": false - }, + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/streams-schema", + "id": "def-common.IngestStreamLifecycleInherit", + "type": "Interface", + "tags": [], + "label": "IngestStreamLifecycleInherit", + "description": [], + "path": "x-pack/solutions/observability/packages/kbn-streams-schema/src/models/ingest/lifecycle/index.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ { "parentPluginId": "@kbn/streams-schema", - "id": "def-common.IngestStreamLifecycleILM.policy", - "type": "string", + "id": "def-common.IngestStreamLifecycleInherit.inherit", + "type": "Object", "tags": [], - "label": "policy", + "label": "inherit", "description": [], - "path": "x-pack/solutions/observability/packages/kbn-streams-schema/src/models/ingest/common.ts", + "signature": [ + "{}" + ], + "path": "x-pack/solutions/observability/packages/kbn-streams-schema/src/models/ingest/lifecycle/index.ts", "deprecated": false, "trackAdoption": false } @@ -2569,6 +2826,50 @@ "path": "x-pack/solutions/observability/packages/kbn-streams-schema/src/models/legacy.ts", "deprecated": false, "trackAdoption": false + }, + { + "parentPluginId": "@kbn/streams-schema", + "id": "def-common.UnwiredReadStreamDefinition.effective_lifecycle", + "type": "CompoundType", + "tags": [], + "label": "effective_lifecycle", + "description": [], + "signature": [ + { + "pluginId": "@kbn/streams-schema", + "scope": "common", + "docId": "kibKbnStreamsSchemaPluginApi", + "section": "def-common.IngestStreamLifecycleDSL", + "text": "IngestStreamLifecycleDSL" + }, + " | ", + { + "pluginId": "@kbn/streams-schema", + "scope": "common", + "docId": "kibKbnStreamsSchemaPluginApi", + "section": "def-common.IngestStreamLifecycleILM", + "text": "IngestStreamLifecycleILM" + }, + " | ", + { + "pluginId": "@kbn/streams-schema", + "scope": "common", + "docId": "kibKbnStreamsSchemaPluginApi", + "section": "def-common.IngestStreamLifecycleInherit", + "text": "IngestStreamLifecycleInherit" + }, + " | ", + { + "pluginId": "@kbn/streams-schema", + "scope": "common", + "docId": "kibKbnStreamsSchemaPluginApi", + "section": "def-common.IngestStreamLifecycleDisabled", + "text": "IngestStreamLifecycleDisabled" + } + ], + "path": "x-pack/solutions/observability/packages/kbn-streams-schema/src/models/legacy.ts", + "deprecated": false, + "trackAdoption": false } ], "initialIsOpen": false @@ -2633,7 +2934,8 @@ "section": "def-common.UnwiredStreamGetResponse", "text": "UnwiredStreamGetResponse" }, - " extends IngestStreamGetResponseBase" + " extends ", + "StreamGetResponseBase" ], "path": "x-pack/solutions/observability/packages/kbn-streams-schema/src/models/ingest/api.ts", "deprecated": false, @@ -2681,6 +2983,50 @@ "path": "x-pack/solutions/observability/packages/kbn-streams-schema/src/models/ingest/api.ts", "deprecated": false, "trackAdoption": false + }, + { + "parentPluginId": "@kbn/streams-schema", + "id": "def-common.UnwiredStreamGetResponse.effective_lifecycle", + "type": "CompoundType", + "tags": [], + "label": "effective_lifecycle", + "description": [], + "signature": [ + { + "pluginId": "@kbn/streams-schema", + "scope": "common", + "docId": "kibKbnStreamsSchemaPluginApi", + "section": "def-common.IngestStreamLifecycleDSL", + "text": "IngestStreamLifecycleDSL" + }, + " | ", + { + "pluginId": "@kbn/streams-schema", + "scope": "common", + "docId": "kibKbnStreamsSchemaPluginApi", + "section": "def-common.IngestStreamLifecycleILM", + "text": "IngestStreamLifecycleILM" + }, + " | ", + { + "pluginId": "@kbn/streams-schema", + "scope": "common", + "docId": "kibKbnStreamsSchemaPluginApi", + "section": "def-common.IngestStreamLifecycleInherit", + "text": "IngestStreamLifecycleInherit" + }, + " | ", + { + "pluginId": "@kbn/streams-schema", + "scope": "common", + "docId": "kibKbnStreamsSchemaPluginApi", + "section": "def-common.IngestStreamLifecycleDisabled", + "text": "IngestStreamLifecycleDisabled" + } + ], + "path": "x-pack/solutions/observability/packages/kbn-streams-schema/src/models/ingest/api.ts", + "deprecated": false, + "trackAdoption": false } ], "initialIsOpen": false @@ -2727,6 +3073,50 @@ "path": "x-pack/solutions/observability/packages/kbn-streams-schema/src/models/ingest/base.ts", "deprecated": false, "trackAdoption": false + }, + { + "parentPluginId": "@kbn/streams-schema", + "id": "def-common.WiredIngest.lifecycle", + "type": "CompoundType", + "tags": [], + "label": "lifecycle", + "description": [], + "signature": [ + { + "pluginId": "@kbn/streams-schema", + "scope": "common", + "docId": "kibKbnStreamsSchemaPluginApi", + "section": "def-common.IngestStreamLifecycleDSL", + "text": "IngestStreamLifecycleDSL" + }, + " | ", + { + "pluginId": "@kbn/streams-schema", + "scope": "common", + "docId": "kibKbnStreamsSchemaPluginApi", + "section": "def-common.IngestStreamLifecycleILM", + "text": "IngestStreamLifecycleILM" + }, + " | ", + { + "pluginId": "@kbn/streams-schema", + "scope": "common", + "docId": "kibKbnStreamsSchemaPluginApi", + "section": "def-common.IngestStreamLifecycleInherit", + "text": "IngestStreamLifecycleInherit" + }, + " | ", + { + "pluginId": "@kbn/streams-schema", + "scope": "common", + "docId": "kibKbnStreamsSchemaPluginApi", + "section": "def-common.IngestStreamLifecycleDisabled", + "text": "IngestStreamLifecycleDisabled" + } + ], + "path": "x-pack/solutions/observability/packages/kbn-streams-schema/src/models/ingest/base.ts", + "deprecated": false, + "trackAdoption": false } ], "initialIsOpen": false @@ -2805,6 +3195,27 @@ "path": "x-pack/solutions/observability/packages/kbn-streams-schema/src/models/legacy.ts", "deprecated": false, "trackAdoption": false + }, + { + "parentPluginId": "@kbn/streams-schema", + "id": "def-common.WiredReadStreamDefinition.effective_lifecycle", + "type": "CompoundType", + "tags": [], + "label": "effective_lifecycle", + "description": [], + "signature": [ + { + "pluginId": "@kbn/streams-schema", + "scope": "common", + "docId": "kibKbnStreamsSchemaPluginApi", + "section": "def-common.IngestStreamLifecycle", + "text": "IngestStreamLifecycle" + }, + " & { from: string; }" + ], + "path": "x-pack/solutions/observability/packages/kbn-streams-schema/src/models/legacy.ts", + "deprecated": false, + "trackAdoption": false } ], "initialIsOpen": false @@ -2860,7 +3271,9 @@ "type": "Interface", "tags": [], "label": "WiredStreamGetResponse", - "description": [], + "description": [ + "\nStream get response" + ], "signature": [ { "pluginId": "@kbn/streams-schema", @@ -2869,7 +3282,8 @@ "section": "def-common.WiredStreamGetResponse", "text": "WiredStreamGetResponse" }, - " extends IngestStreamGetResponseBase" + " extends ", + "StreamGetResponseBase" ], "path": "x-pack/solutions/observability/packages/kbn-streams-schema/src/models/ingest/api.ts", "deprecated": false, @@ -2916,6 +3330,27 @@ "path": "x-pack/solutions/observability/packages/kbn-streams-schema/src/models/ingest/api.ts", "deprecated": false, "trackAdoption": false + }, + { + "parentPluginId": "@kbn/streams-schema", + "id": "def-common.WiredStreamGetResponse.effective_lifecycle", + "type": "CompoundType", + "tags": [], + "label": "effective_lifecycle", + "description": [], + "signature": [ + { + "pluginId": "@kbn/streams-schema", + "scope": "common", + "docId": "kibKbnStreamsSchemaPluginApi", + "section": "def-common.IngestStreamLifecycle", + "text": "IngestStreamLifecycle" + }, + " & { from: string; }" + ], + "path": "x-pack/solutions/observability/packages/kbn-streams-schema/src/models/ingest/api.ts", + "deprecated": false, + "trackAdoption": false } ], "initialIsOpen": false @@ -3120,8 +3555,8 @@ "pluginId": "@kbn/streams-schema", "scope": "common", "docId": "kibKbnStreamsSchemaPluginApi", - "section": "def-common.IngestStreamLifecycleDLM", - "text": "IngestStreamLifecycleDLM" + "section": "def-common.IngestStreamLifecycleDSL", + "text": "IngestStreamLifecycleDSL" }, " | ", { @@ -3130,9 +3565,25 @@ "docId": "kibKbnStreamsSchemaPluginApi", "section": "def-common.IngestStreamLifecycleILM", "text": "IngestStreamLifecycleILM" + }, + " | ", + { + "pluginId": "@kbn/streams-schema", + "scope": "common", + "docId": "kibKbnStreamsSchemaPluginApi", + "section": "def-common.IngestStreamLifecycleInherit", + "text": "IngestStreamLifecycleInherit" + }, + " | ", + { + "pluginId": "@kbn/streams-schema", + "scope": "common", + "docId": "kibKbnStreamsSchemaPluginApi", + "section": "def-common.IngestStreamLifecycleDisabled", + "text": "IngestStreamLifecycleDisabled" } ], - "path": "x-pack/solutions/observability/packages/kbn-streams-schema/src/models/ingest/common.ts", + "path": "x-pack/solutions/observability/packages/kbn-streams-schema/src/models/ingest/lifecycle/index.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false @@ -3181,6 +3632,28 @@ "trackAdoption": false, "initialIsOpen": false }, + { + "parentPluginId": "@kbn/streams-schema", + "id": "def-common.InheritedIngestStreamLifecycle", + "type": "Type", + "tags": [], + "label": "InheritedIngestStreamLifecycle", + "description": [], + "signature": [ + { + "pluginId": "@kbn/streams-schema", + "scope": "common", + "docId": "kibKbnStreamsSchemaPluginApi", + "section": "def-common.IngestStreamLifecycle", + "text": "IngestStreamLifecycle" + }, + " & { from: string; }" + ], + "path": "x-pack/solutions/observability/packages/kbn-streams-schema/src/models/ingest/lifecycle/index.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, { "parentPluginId": "@kbn/streams-schema", "id": "def-common.ProcessorConfig", @@ -3802,7 +4275,7 @@ }, ">" ], - "path": "x-pack/solutions/observability/packages/kbn-streams-schema/src/models/ingest/common.ts", + "path": "x-pack/solutions/observability/packages/kbn-streams-schema/src/models/ingest/lifecycle/index.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false @@ -3900,6 +4373,37 @@ "trackAdoption": false, "initialIsOpen": false }, + { + "parentPluginId": "@kbn/streams-schema", + "id": "def-common.inheritedIngestStreamLifecycleSchema", + "type": "Object", + "tags": [], + "label": "inheritedIngestStreamLifecycleSchema", + "description": [], + "signature": [ + "Zod.ZodType<", + { + "pluginId": "@kbn/streams-schema", + "scope": "common", + "docId": "kibKbnStreamsSchemaPluginApi", + "section": "def-common.InheritedIngestStreamLifecycle", + "text": "InheritedIngestStreamLifecycle" + }, + ", Zod.ZodTypeDef, ", + { + "pluginId": "@kbn/streams-schema", + "scope": "common", + "docId": "kibKbnStreamsSchemaPluginApi", + "section": "def-common.InheritedIngestStreamLifecycle", + "text": "InheritedIngestStreamLifecycle" + }, + ">" + ], + "path": "x-pack/solutions/observability/packages/kbn-streams-schema/src/models/ingest/lifecycle/index.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, { "parentPluginId": "@kbn/streams-schema", "id": "def-common.namedFieldDefinitionConfigSchema", diff --git a/api_docs/kbn_streams_schema.mdx b/api_docs/kbn_streams_schema.mdx index b428eb1d57bd9..0fbc178a23b61 100644 --- a/api_docs/kbn_streams_schema.mdx +++ b/api_docs/kbn_streams_schema.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-streams-schema title: "@kbn/streams-schema" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/streams-schema plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/streams-schema'] --- import kbnStreamsSchemaObj from './kbn_streams_schema.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/streams-program-team](https://github.com/orgs/elastic/teams/st | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 201 | 1 | 201 | 1 | +| 222 | 1 | 221 | 2 | ## Common diff --git a/api_docs/kbn_synthetics_e2e.mdx b/api_docs/kbn_synthetics_e2e.mdx index 501b1d52e8f7e..281186eea4232 100644 --- a/api_docs/kbn_synthetics_e2e.mdx +++ b/api_docs/kbn_synthetics_e2e.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-synthetics-e2e title: "@kbn/synthetics-e2e" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/synthetics-e2e plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/synthetics-e2e'] --- import kbnSyntheticsE2eObj from './kbn_synthetics_e2e.devdocs.json'; diff --git a/api_docs/kbn_synthetics_private_location.mdx b/api_docs/kbn_synthetics_private_location.mdx index 600eb91a2fad7..37a690788daaf 100644 --- a/api_docs/kbn_synthetics_private_location.mdx +++ b/api_docs/kbn_synthetics_private_location.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-synthetics-private-location title: "@kbn/synthetics-private-location" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/synthetics-private-location plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/synthetics-private-location'] --- import kbnSyntheticsPrivateLocationObj from './kbn_synthetics_private_location.devdocs.json'; diff --git a/api_docs/kbn_telemetry_tools.mdx b/api_docs/kbn_telemetry_tools.mdx index 83dcbaae4c981..9d9636b14e834 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: 2025-01-24 +date: 2025-01-27 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 b8eff1a5066d0..668d3fabd239a 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: 2025-01-24 +date: 2025-01-27 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 2d4dc01c77727..facd0be1f2713 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: 2025-01-24 +date: 2025-01-27 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 f6e3784e7baef..5d4bf0f63e4b9 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: 2025-01-24 +date: 2025-01-27 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 1d7104f68a767..f046295491148 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: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/test-subj-selector'] --- import kbnTestSubjSelectorObj from './kbn_test_subj_selector.devdocs.json'; diff --git a/api_docs/kbn_timerange.mdx b/api_docs/kbn_timerange.mdx index efa6495f613ee..4257755e999a4 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: 2025-01-24 +date: 2025-01-27 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 691f8be4af89a..065fccc5019ad 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: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/tooling-log'] --- import kbnToolingLogObj from './kbn_tooling_log.devdocs.json'; diff --git a/api_docs/kbn_transpose_utils.mdx b/api_docs/kbn_transpose_utils.mdx index 51edd84e3c444..a2e53dc05ac94 100644 --- a/api_docs/kbn_transpose_utils.mdx +++ b/api_docs/kbn_transpose_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-transpose-utils title: "@kbn/transpose-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/transpose-utils plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/transpose-utils'] --- import kbnTransposeUtilsObj from './kbn_transpose_utils.devdocs.json'; diff --git a/api_docs/kbn_triggers_actions_ui_types.mdx b/api_docs/kbn_triggers_actions_ui_types.mdx index d44f203b0eeb5..7ed382e49850a 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: 2025-01-24 +date: 2025-01-27 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 6900764456047..9078d3305a489 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: 2025-01-24 +date: 2025-01-27 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 9ea5aa19e898a..ea742a3700601 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: 2025-01-24 +date: 2025-01-27 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 bb48d9ab80651..f8ae63cb8fe00 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: 2025-01-24 +date: 2025-01-27 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 1c202bf3efdf0..928ce16f43d3c 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: 2025-01-24 +date: 2025-01-27 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 16d36c407c4af..9b893de418833 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: 2025-01-24 +date: 2025-01-27 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 1ef21ea34fec9..67e0e3483f837 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: 2025-01-24 +date: 2025-01-27 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 c2058045728d0..52c99cec92c80 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: 2025-01-24 +date: 2025-01-27 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 226468d730be4..617e5625acf9d 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: 2025-01-24 +date: 2025-01-27 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 decfccbdc26e3..9add82c88317b 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: 2025-01-24 +date: 2025-01-27 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 1f6d404c0aa5b..a4d2fec892fc5 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: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/unsaved-changes-badge'] --- import kbnUnsavedChangesBadgeObj from './kbn_unsaved_changes_badge.devdocs.json'; diff --git a/api_docs/kbn_unsaved_changes_prompt.mdx b/api_docs/kbn_unsaved_changes_prompt.mdx index 15b83adfbced2..eaa1a4fd03d15 100644 --- a/api_docs/kbn_unsaved_changes_prompt.mdx +++ b/api_docs/kbn_unsaved_changes_prompt.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-unsaved-changes-prompt title: "@kbn/unsaved-changes-prompt" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/unsaved-changes-prompt plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/unsaved-changes-prompt'] --- import kbnUnsavedChangesPromptObj from './kbn_unsaved_changes_prompt.devdocs.json'; diff --git a/api_docs/kbn_use_tracked_promise.mdx b/api_docs/kbn_use_tracked_promise.mdx index 96faf7e561fd7..73d61cc2a2453 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: 2025-01-24 +date: 2025-01-27 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 cc885c294008c..9ed8727d9afbe 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: 2025-01-24 +date: 2025-01-27 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 ce1657ca26d6a..6be7ed854c921 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: 2025-01-24 +date: 2025-01-27 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 355b47631f058..b2b98d27f4f86 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: 2025-01-24 +date: 2025-01-27 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 6f4629643865c..b05e189cc98f8 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: 2025-01-24 +date: 2025-01-27 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 4359caa50b6ad..15693b5afeed0 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: 2025-01-24 +date: 2025-01-27 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 175ad5cfc5dbe..93a4d40aec124 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: 2025-01-24 +date: 2025-01-27 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 06bda234db60a..819bcd05d2aeb 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: 2025-01-24 +date: 2025-01-27 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 82a35f927427e..819e587b76a57 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: 2025-01-24 +date: 2025-01-27 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.mdx b/api_docs/kbn_zod.mdx index 3f4cceb70d3ff..faf9150429231 100644 --- a/api_docs/kbn_zod.mdx +++ b/api_docs/kbn_zod.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-zod title: "@kbn/zod" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/zod plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/zod'] --- import kbnZodObj from './kbn_zod.devdocs.json'; diff --git a/api_docs/kbn_zod_helpers.mdx b/api_docs/kbn_zod_helpers.mdx index b1022e3749bf4..953ad94fd46d3 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: 2025-01-24 +date: 2025-01-27 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 39ca179b2f039..9ee3c86efc13e 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: 2025-01-24 +date: 2025-01-27 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 397968cfc227f..96d90fdb3e126 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: 2025-01-24 +date: 2025-01-27 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 88dade307779a..85a3c91096ab9 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: 2025-01-24 +date: 2025-01-27 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 4837deca96eeb..9848296167a2e 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: 2025-01-24 +date: 2025-01-27 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 40b096a3140b5..04dd9ec53a86f 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: 2025-01-24 +date: 2025-01-27 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 e558cd06f67f8..b9994ad70b020 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: 2025-01-24 +date: 2025-01-27 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 96036d148dc5f..15d248cd3b046 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: 2025-01-24 +date: 2025-01-27 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 00c3eac0c1f96..8735f75a0b410 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: 2025-01-24 +date: 2025-01-27 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 d644d9313e8d1..10fa7054cbd34 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: 2025-01-24 +date: 2025-01-27 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 c33f64ad6c6b2..dca119e4141ed 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: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'lists'] --- import listsObj from './lists.devdocs.json'; diff --git a/api_docs/llm_tasks.mdx b/api_docs/llm_tasks.mdx index 274961c62ed65..73b0667a5009d 100644 --- a/api_docs/llm_tasks.mdx +++ b/api_docs/llm_tasks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/llmTasks title: "llmTasks" image: https://source.unsplash.com/400x175/?github description: API docs for the llmTasks plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'llmTasks'] --- import llmTasksObj from './llm_tasks.devdocs.json'; diff --git a/api_docs/logs_data_access.mdx b/api_docs/logs_data_access.mdx index e9c5eda51b86a..85122426bc7db 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: 2025-01-24 +date: 2025-01-27 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 ce212dd201fb4..4bb1cda80dc1e 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: 2025-01-24 +date: 2025-01-27 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 8af68b5f50ab7..80ca9932315b1 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: 2025-01-24 +date: 2025-01-27 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 4c1bb05dad9da..07d9997303d3a 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: 2025-01-24 +date: 2025-01-27 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 bb852b829543f..1252193405396 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: 2025-01-24 +date: 2025-01-27 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 55fb1780c2ba1..b6d6a7f600ea4 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: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'mapsEms'] --- import mapsEmsObj from './maps_ems.devdocs.json'; diff --git a/api_docs/metrics_data_access.mdx b/api_docs/metrics_data_access.mdx index 7f29c6f258fd5..2f69d5b3b2b8d 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: 2025-01-24 +date: 2025-01-27 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 16fb4e4866750..88bb4f72cad44 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: 2025-01-24 +date: 2025-01-27 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 7e0c4fea72d0f..468ab729deef8 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: 2025-01-24 +date: 2025-01-27 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 89f9d660d77c3..e5d3a9e1dc7de 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: 2025-01-24 +date: 2025-01-27 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 a2d754be6a04e..9df9fe2b6be72 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: 2025-01-24 +date: 2025-01-27 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 332b8f8037786..6145cf0ec6f93 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: 2025-01-24 +date: 2025-01-27 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 1a1ad2be1ae2d..adca2db57641e 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: 2025-01-24 +date: 2025-01-27 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 93e495d8e40b0..c507c8a57564b 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: 2025-01-24 +date: 2025-01-27 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 ec26417a60fb7..7a79ca8e21558 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: 2025-01-24 +date: 2025-01-27 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 ba1008f830762..ff9557ed503a0 100644 --- a/api_docs/observability.devdocs.json +++ b/api_docs/observability.devdocs.json @@ -14775,7 +14775,7 @@ "label": "observabilityPaths", "description": [], "signature": [ - "{ alerts: string; annotations: string; alertDetails: (alertId: string) => string; rules: string; ruleDetails: (ruleId: string) => string; }" + "{ alerts: string; annotations: string; alertDetails: (alertId: string) => string; rules: string; ruleDetails: (ruleId: string) => string; createRule: (ruleTypeId: string) => string; }" ], "path": "x-pack/solutions/observability/plugins/observability/common/index.ts", "deprecated": false, diff --git a/api_docs/observability.mdx b/api_docs/observability.mdx index 868e03f3c566f..61ff48acf3e38 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: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'observability'] --- import observabilityObj from './observability.devdocs.json'; diff --git a/api_docs/observability_a_i_assistant.mdx b/api_docs/observability_a_i_assistant.mdx index 27ad128672bf3..ebae1e56ec6a3 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: 2025-01-24 +date: 2025-01-27 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 232da0fe4b8f0..2a4b5ec2ead36 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: 2025-01-24 +date: 2025-01-27 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 2b71d1ce7b41d..1aeac49e1ed20 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: 2025-01-24 +date: 2025-01-27 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 33dd340880432..6717e2d76df8f 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: 2025-01-24 +date: 2025-01-27 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 6b93dbc4be6d9..dcac8623f5108 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: 2025-01-24 +date: 2025-01-27 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 545bebe647ef7..f5259bec0927e 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: 2025-01-24 +date: 2025-01-27 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 ca1b62fb5a602..18fef7c9c0c52 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: 2025-01-24 +date: 2025-01-27 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 30e6d6498d4ce..b88699e09195e 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: 2025-01-24 +date: 2025-01-27 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 17b00e57c98ec..b06fa79e754e6 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: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- @@ -15,13 +15,13 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | Count | Plugins or Packages with a
public API | Number of teams | |--------------|----------|------------------------| -| 909 | 773 | 43 | +| 910 | 774 | 43 | ### Public API health stats | API Count | Any Count | Missing comments | Missing exports | |--------------|----------|-----------------|--------| -| 55229 | 242 | 41548 | 2710 | +| 55290 | 242 | 41605 | 2713 | ## Plugin Directory @@ -176,7 +176,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 97 | 2 | 96 | 3 | | | [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | - | 26 | 0 | 26 | 1 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 148 | 0 | 139 | 2 | -| | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 36 | 0 | 30 | 3 | +| | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 65 | 0 | 57 | 3 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 105 | 0 | 58 | 0 | | | [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | This plugin contains the definition and helper methods around saved searches, used by discover and visualizations. | 62 | 0 | 61 | 3 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 32 | 0 | 13 | 0 | @@ -688,7 +688,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/kibana-management](https://github.com/orgs/elastic/teams/kibana-management) | - | 3 | 0 | 3 | 0 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 10 | 0 | 9 | 1 | | | [@elastic/obs-ux-logs-team](https://github.com/orgs/elastic/teams/obs-ux-logs-team) | - | 2 | 0 | 1 | 1 | -| | [@elastic/response-ops](https://github.com/orgs/elastic/teams/response-ops) | - | 16 | 0 | 16 | 1 | +| | [@elastic/response-ops](https://github.com/orgs/elastic/teams/response-ops) | - | 18 | 0 | 18 | 2 | | | [@elastic/security-detections-response](https://github.com/orgs/elastic/teams/security-detections-response) | - | 152 | 0 | 140 | 0 | | | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 2 | 0 | 2 | 0 | | | [@elastic/obs-ux-logs-team](https://github.com/orgs/elastic/teams/obs-ux-logs-team) | - | 15 | 0 | 14 | 0 | @@ -714,6 +714,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/kibana-security](https://github.com/orgs/elastic/teams/kibana-security) | - | 67 | 0 | 40 | 0 | | | [@elastic/kibana-security](https://github.com/orgs/elastic/teams/kibana-security) | - | 282 | 1 | 161 | 0 | | | [@elastic/kibana-security](https://github.com/orgs/elastic/teams/kibana-security) | - | 74 | 0 | 73 | 0 | +| | [@elastic/security-threat-hunting-explore](https://github.com/orgs/elastic/teams/security-threat-hunting-explore) | - | 9 | 0 | 8 | 1 | | | [@elastic/kibana-cloud-security-posture](https://github.com/orgs/elastic/teams/kibana-cloud-security-posture) | - | 7 | 0 | 0 | 0 | | | [@elastic/security-threat-hunting-explore](https://github.com/orgs/elastic/teams/security-threat-hunting-explore) | - | 17 | 0 | 17 | 9 | | | [@elastic/security-threat-hunting-explore](https://github.com/orgs/elastic/teams/security-threat-hunting-explore) | - | 54 | 0 | 49 | 0 | @@ -797,7 +798,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 108 | 2 | 70 | 1 | | | [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kibana-operations) | - | 4 | 0 | 2 | 0 | | | [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kibana-operations) | - | 41 | 2 | 21 | 0 | -| | [@elastic/streams-program-team](https://github.com/orgs/elastic/teams/streams-program-team) | - | 201 | 1 | 201 | 1 | +| | [@elastic/streams-program-team](https://github.com/orgs/elastic/teams/streams-program-team) | - | 222 | 1 | 221 | 2 | | | [@elastic/obs-ux-management-team](https://github.com/orgs/elastic/teams/obs-ux-management-team) | - | 9 | 0 | 9 | 0 | | | [@elastic/obs-ux-management-team](https://github.com/orgs/elastic/teams/obs-ux-management-team) | - | 19 | 0 | 19 | 0 | | | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 7 | 0 | 5 | 1 | diff --git a/api_docs/presentation_panel.mdx b/api_docs/presentation_panel.mdx index 6c45a1c672436..010b862e9f02d 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: 2025-01-24 +date: 2025-01-27 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 9ec6f5a7b8e76..431a0d832995a 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: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'presentationUtil'] --- import presentationUtilObj from './presentation_util.devdocs.json'; diff --git a/api_docs/product_doc_base.mdx b/api_docs/product_doc_base.mdx index f8e2016089427..2e76765d29e26 100644 --- a/api_docs/product_doc_base.mdx +++ b/api_docs/product_doc_base.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/productDocBase title: "productDocBase" image: https://source.unsplash.com/400x175/?github description: API docs for the productDocBase plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'productDocBase'] --- import productDocBaseObj from './product_doc_base.devdocs.json'; diff --git a/api_docs/profiling.mdx b/api_docs/profiling.mdx index e50065a915154..f805db19b1d67 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: 2025-01-24 +date: 2025-01-27 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 57fc8d8c034eb..088c41b4a575c 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: 2025-01-24 +date: 2025-01-27 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 049fa74590b0e..f314a90d50f30 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: 2025-01-24 +date: 2025-01-27 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 fc25bfd527890..e9d39b1011cf1 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: 2025-01-24 +date: 2025-01-27 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 fc99f7d6eff11..c08cbf40d3f44 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: 2025-01-24 +date: 2025-01-27 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 752dfd77354ee..7eb21240eb081 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: 2025-01-24 +date: 2025-01-27 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 485898e45b04b..c7e9becfb1a6f 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: 2025-01-24 +date: 2025-01-27 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 4f7f89c78692a..d840b2037cea6 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: 2025-01-24 +date: 2025-01-27 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 9f3ff7af45897..63169fff3832e 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: 2025-01-24 +date: 2025-01-27 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 333108b2d9079..01a3e5822462e 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: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjectsManagement'] --- import savedObjectsManagementObj from './saved_objects_management.devdocs.json'; diff --git a/api_docs/saved_objects_tagging.devdocs.json b/api_docs/saved_objects_tagging.devdocs.json index f45a6cb72bdd9..9d4c0166f3db2 100644 --- a/api_docs/saved_objects_tagging.devdocs.json +++ b/api_docs/saved_objects_tagging.devdocs.json @@ -236,6 +236,195 @@ } ], "returnComment": [] + }, + { + "parentPluginId": "savedObjectsTagging", + "id": "def-server.SavedObjectTaggingStart.convertTagNameToId", + "type": "Function", + "tags": [], + "label": "convertTagNameToId", + "description": [], + "signature": [ + "(tagName: string, allTags: ", + { + "pluginId": "savedObjectsTaggingOss", + "scope": "common", + "docId": "kibSavedObjectsTaggingOssPluginApi", + "section": "def-common.Tag", + "text": "Tag" + }, + "[]) => string | undefined" + ], + "path": "x-pack/platform/plugins/shared/saved_objects_tagging/server/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "savedObjectsTagging", + "id": "def-server.SavedObjectTaggingStart.convertTagNameToId.$1", + "type": "string", + "tags": [], + "label": "tagName", + "description": [], + "signature": [ + "string" + ], + "path": "x-pack/platform/plugins/shared/saved_objects_tagging/server/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "savedObjectsTagging", + "id": "def-server.SavedObjectTaggingStart.convertTagNameToId.$2", + "type": "Array", + "tags": [], + "label": "allTags", + "description": [], + "signature": [ + { + "pluginId": "savedObjectsTaggingOss", + "scope": "common", + "docId": "kibSavedObjectsTaggingOssPluginApi", + "section": "def-common.Tag", + "text": "Tag" + }, + "[]" + ], + "path": "x-pack/platform/plugins/shared/saved_objects_tagging/server/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "savedObjectsTagging", + "id": "def-server.SavedObjectTaggingStart.getTagsFromReferences", + "type": "Function", + "tags": [], + "label": "getTagsFromReferences", + "description": [], + "signature": [ + "(references: ", + "SavedObjectReference", + "[], allTags: ", + { + "pluginId": "savedObjectsTaggingOss", + "scope": "common", + "docId": "kibSavedObjectsTaggingOssPluginApi", + "section": "def-common.Tag", + "text": "Tag" + }, + "[]) => { tags: ", + { + "pluginId": "savedObjectsTaggingOss", + "scope": "common", + "docId": "kibSavedObjectsTaggingOssPluginApi", + "section": "def-common.Tag", + "text": "Tag" + }, + "[]; missingRefs: ", + "SavedObjectReference", + "[]; }" + ], + "path": "x-pack/platform/plugins/shared/saved_objects_tagging/server/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "savedObjectsTagging", + "id": "def-server.SavedObjectTaggingStart.getTagsFromReferences.$1", + "type": "Array", + "tags": [], + "label": "references", + "description": [], + "signature": [ + "SavedObjectReference", + "[]" + ], + "path": "x-pack/platform/plugins/shared/saved_objects_tagging/server/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "savedObjectsTagging", + "id": "def-server.SavedObjectTaggingStart.getTagsFromReferences.$2", + "type": "Array", + "tags": [], + "label": "allTags", + "description": [], + "signature": [ + { + "pluginId": "savedObjectsTaggingOss", + "scope": "common", + "docId": "kibSavedObjectsTaggingOssPluginApi", + "section": "def-common.Tag", + "text": "Tag" + }, + "[]" + ], + "path": "x-pack/platform/plugins/shared/saved_objects_tagging/server/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "savedObjectsTagging", + "id": "def-server.SavedObjectTaggingStart.replaceTagReferences", + "type": "Function", + "tags": [], + "label": "replaceTagReferences", + "description": [], + "signature": [ + "(references: ", + "SavedObjectReference", + "[], newTagIds: string[]) => ", + "SavedObjectReference", + "[]" + ], + "path": "x-pack/platform/plugins/shared/saved_objects_tagging/server/types.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "savedObjectsTagging", + "id": "def-server.SavedObjectTaggingStart.replaceTagReferences.$1", + "type": "Array", + "tags": [], + "label": "references", + "description": [], + "signature": [ + "SavedObjectReference", + "[]" + ], + "path": "x-pack/platform/plugins/shared/saved_objects_tagging/server/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "savedObjectsTagging", + "id": "def-server.SavedObjectTaggingStart.replaceTagReferences.$2", + "type": "Array", + "tags": [], + "label": "newTagIds", + "description": [], + "signature": [ + "string[]" + ], + "path": "x-pack/platform/plugins/shared/saved_objects_tagging/server/types.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] } ], "lifecycle": "start", @@ -245,6 +434,261 @@ "common": { "classes": [], "functions": [ + { + "parentPluginId": "savedObjectsTagging", + "id": "def-common.convertTagNameToId", + "type": "Function", + "tags": [], + "label": "convertTagNameToId", + "description": [], + "signature": [ + "(tagName: string, allTags: ", + { + "pluginId": "savedObjectsTaggingOss", + "scope": "common", + "docId": "kibSavedObjectsTaggingOssPluginApi", + "section": "def-common.Tag", + "text": "Tag" + }, + "[]) => string | undefined" + ], + "path": "x-pack/platform/plugins/shared/saved_objects_tagging/common/references.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "savedObjectsTagging", + "id": "def-common.convertTagNameToId.$1", + "type": "string", + "tags": [], + "label": "tagName", + "description": [], + "signature": [ + "string" + ], + "path": "x-pack/platform/plugins/shared/saved_objects_tagging/common/references.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "savedObjectsTagging", + "id": "def-common.convertTagNameToId.$2", + "type": "Array", + "tags": [], + "label": "allTags", + "description": [], + "signature": [ + { + "pluginId": "savedObjectsTaggingOss", + "scope": "common", + "docId": "kibSavedObjectsTaggingOssPluginApi", + "section": "def-common.Tag", + "text": "Tag" + }, + "[]" + ], + "path": "x-pack/platform/plugins/shared/saved_objects_tagging/common/references.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "savedObjectsTagging", + "id": "def-common.getObjectTags", + "type": "Function", + "tags": [], + "label": "getObjectTags", + "description": [], + "signature": [ + "(object: { references: ", + "SavedObjectReference", + "[]; }, allTags: ", + { + "pluginId": "savedObjectsTaggingOss", + "scope": "common", + "docId": "kibSavedObjectsTaggingOssPluginApi", + "section": "def-common.Tag", + "text": "Tag" + }, + "[]) => { tags: ", + { + "pluginId": "savedObjectsTaggingOss", + "scope": "common", + "docId": "kibSavedObjectsTaggingOssPluginApi", + "section": "def-common.Tag", + "text": "Tag" + }, + "[]; missingRefs: ", + "SavedObjectReference", + "[]; }" + ], + "path": "x-pack/platform/plugins/shared/saved_objects_tagging/common/references.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "savedObjectsTagging", + "id": "def-common.getObjectTags.$1", + "type": "Object", + "tags": [], + "label": "object", + "description": [], + "path": "x-pack/platform/plugins/shared/saved_objects_tagging/common/references.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "savedObjectsTagging", + "id": "def-common.getObjectTags.$1.references", + "type": "Array", + "tags": [], + "label": "references", + "description": [], + "signature": [ + "SavedObjectReference", + "[]" + ], + "path": "x-pack/platform/plugins/shared/saved_objects_tagging/common/references.ts", + "deprecated": false, + "trackAdoption": false + } + ] + }, + { + "parentPluginId": "savedObjectsTagging", + "id": "def-common.getObjectTags.$2", + "type": "Array", + "tags": [], + "label": "allTags", + "description": [], + "signature": [ + { + "pluginId": "savedObjectsTaggingOss", + "scope": "common", + "docId": "kibSavedObjectsTaggingOssPluginApi", + "section": "def-common.Tag", + "text": "Tag" + }, + "[]" + ], + "path": "x-pack/platform/plugins/shared/saved_objects_tagging/common/references.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "savedObjectsTagging", + "id": "def-common.getTag", + "type": "Function", + "tags": [], + "label": "getTag", + "description": [], + "signature": [ + "(tagId: string, allTags: ", + { + "pluginId": "savedObjectsTaggingOss", + "scope": "common", + "docId": "kibSavedObjectsTaggingOssPluginApi", + "section": "def-common.Tag", + "text": "Tag" + }, + "[]) => ", + { + "pluginId": "savedObjectsTaggingOss", + "scope": "common", + "docId": "kibSavedObjectsTaggingOssPluginApi", + "section": "def-common.Tag", + "text": "Tag" + }, + " | undefined" + ], + "path": "x-pack/platform/plugins/shared/saved_objects_tagging/common/references.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "savedObjectsTagging", + "id": "def-common.getTag.$1", + "type": "string", + "tags": [], + "label": "tagId", + "description": [], + "signature": [ + "string" + ], + "path": "x-pack/platform/plugins/shared/saved_objects_tagging/common/references.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "savedObjectsTagging", + "id": "def-common.getTag.$2", + "type": "Array", + "tags": [], + "label": "allTags", + "description": [], + "signature": [ + { + "pluginId": "savedObjectsTaggingOss", + "scope": "common", + "docId": "kibSavedObjectsTaggingOssPluginApi", + "section": "def-common.Tag", + "text": "Tag" + }, + "[]" + ], + "path": "x-pack/platform/plugins/shared/saved_objects_tagging/common/references.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "savedObjectsTagging", + "id": "def-common.getTagIdsFromReferences", + "type": "Function", + "tags": [], + "label": "getTagIdsFromReferences", + "description": [], + "signature": [ + "(references: SavedObjectReferenceLike[]) => string[]" + ], + "path": "x-pack/platform/plugins/shared/saved_objects_tagging/common/references.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "savedObjectsTagging", + "id": "def-common.getTagIdsFromReferences.$1", + "type": "Array", + "tags": [], + "label": "references", + "description": [], + "signature": [ + "SavedObjectReferenceLike[]" + ], + "path": "x-pack/platform/plugins/shared/saved_objects_tagging/common/references.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, { "parentPluginId": "savedObjectsTagging", "id": "def-common.getTagsCapabilities", @@ -287,6 +731,173 @@ "returnComment": [], "initialIsOpen": false }, + { + "parentPluginId": "savedObjectsTagging", + "id": "def-common.getTagsFromReferences", + "type": "Function", + "tags": [], + "label": "getTagsFromReferences", + "description": [], + "signature": [ + "(references: ", + "SavedObjectReference", + "[], allTags: ", + { + "pluginId": "savedObjectsTaggingOss", + "scope": "common", + "docId": "kibSavedObjectsTaggingOssPluginApi", + "section": "def-common.Tag", + "text": "Tag" + }, + "[]) => { tags: ", + { + "pluginId": "savedObjectsTaggingOss", + "scope": "common", + "docId": "kibSavedObjectsTaggingOssPluginApi", + "section": "def-common.Tag", + "text": "Tag" + }, + "[]; missingRefs: ", + "SavedObjectReference", + "[]; }" + ], + "path": "x-pack/platform/plugins/shared/saved_objects_tagging/common/references.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "savedObjectsTagging", + "id": "def-common.getTagsFromReferences.$1", + "type": "Array", + "tags": [], + "label": "references", + "description": [], + "signature": [ + "SavedObjectReference", + "[]" + ], + "path": "x-pack/platform/plugins/shared/saved_objects_tagging/common/references.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "savedObjectsTagging", + "id": "def-common.getTagsFromReferences.$2", + "type": "Array", + "tags": [], + "label": "allTags", + "description": [], + "signature": [ + { + "pluginId": "savedObjectsTaggingOss", + "scope": "common", + "docId": "kibSavedObjectsTaggingOssPluginApi", + "section": "def-common.Tag", + "text": "Tag" + }, + "[]" + ], + "path": "x-pack/platform/plugins/shared/saved_objects_tagging/common/references.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "savedObjectsTagging", + "id": "def-common.replaceTagReferences", + "type": "Function", + "tags": [], + "label": "replaceTagReferences", + "description": [ + "\nUpdate the given `references` array, replacing all the `tag` references with\nreferences for the given `newTagIds`, while preserving all references to non-tag objects." + ], + "signature": [ + "(references: ", + "SavedObjectReference", + "[], newTagIds: string[]) => ", + "SavedObjectReference", + "[]" + ], + "path": "x-pack/platform/plugins/shared/saved_objects_tagging/common/references.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "savedObjectsTagging", + "id": "def-common.replaceTagReferences.$1", + "type": "Array", + "tags": [], + "label": "references", + "description": [], + "signature": [ + "SavedObjectReference", + "[]" + ], + "path": "x-pack/platform/plugins/shared/saved_objects_tagging/common/references.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "savedObjectsTagging", + "id": "def-common.replaceTagReferences.$2", + "type": "Array", + "tags": [], + "label": "newTagIds", + "description": [], + "signature": [ + "string[]" + ], + "path": "x-pack/platform/plugins/shared/saved_objects_tagging/common/references.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "savedObjectsTagging", + "id": "def-common.tagIdToReference", + "type": "Function", + "tags": [], + "label": "tagIdToReference", + "description": [ + "\nCreate a {@link SavedObjectReference | reference} for given tag id." + ], + "signature": [ + "(tagId: string) => ", + "SavedObjectReference" + ], + "path": "x-pack/platform/plugins/shared/saved_objects_tagging/common/references.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "savedObjectsTagging", + "id": "def-common.tagIdToReference.$1", + "type": "string", + "tags": [], + "label": "tagId", + "description": [], + "signature": [ + "string" + ], + "path": "x-pack/platform/plugins/shared/saved_objects_tagging/common/references.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, { "parentPluginId": "savedObjectsTagging", "id": "def-common.validateTagColor", diff --git a/api_docs/saved_objects_tagging.mdx b/api_docs/saved_objects_tagging.mdx index f9c4d65fc798a..9be9a05f7b17d 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: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjectsTagging'] --- import savedObjectsTaggingObj from './saved_objects_tagging.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sh | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 36 | 0 | 30 | 3 | +| 65 | 0 | 57 | 3 | ## Client diff --git a/api_docs/saved_objects_tagging_oss.mdx b/api_docs/saved_objects_tagging_oss.mdx index 97d802b6d1265..b0fb94094b37d 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: 2025-01-24 +date: 2025-01-27 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 aa9290293d36d..de58951d5e640 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: 2025-01-24 +date: 2025-01-27 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 34101264d8024..ae22cbe386a4f 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: 2025-01-24 +date: 2025-01-27 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 0a5288d128323..7110f9a285512 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: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'screenshotting'] --- import screenshottingObj from './screenshotting.devdocs.json'; diff --git a/api_docs/search_assistant.mdx b/api_docs/search_assistant.mdx index d9b0a01e8951a..ccc00e436abb0 100644 --- a/api_docs/search_assistant.mdx +++ b/api_docs/search_assistant.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/searchAssistant title: "searchAssistant" image: https://source.unsplash.com/400x175/?github description: API docs for the searchAssistant plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'searchAssistant'] --- import searchAssistantObj from './search_assistant.devdocs.json'; diff --git a/api_docs/search_connectors.mdx b/api_docs/search_connectors.mdx index be6fd9044219c..608f340303b4e 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: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'searchConnectors'] --- import searchConnectorsObj from './search_connectors.devdocs.json'; diff --git a/api_docs/search_homepage.mdx b/api_docs/search_homepage.mdx index 0bf859750123b..86a7c7f8c4c91 100644 --- a/api_docs/search_homepage.mdx +++ b/api_docs/search_homepage.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/searchHomepage title: "searchHomepage" image: https://source.unsplash.com/400x175/?github description: API docs for the searchHomepage plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'searchHomepage'] --- import searchHomepageObj from './search_homepage.devdocs.json'; diff --git a/api_docs/search_indices.mdx b/api_docs/search_indices.mdx index 6c34babb4f99e..d3a89d393ce86 100644 --- a/api_docs/search_indices.mdx +++ b/api_docs/search_indices.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/searchIndices title: "searchIndices" image: https://source.unsplash.com/400x175/?github description: API docs for the searchIndices plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'searchIndices'] --- import searchIndicesObj from './search_indices.devdocs.json'; diff --git a/api_docs/search_inference_endpoints.mdx b/api_docs/search_inference_endpoints.mdx index 59815ad03fee4..fe3d4226ef486 100644 --- a/api_docs/search_inference_endpoints.mdx +++ b/api_docs/search_inference_endpoints.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/searchInferenceEndpoints title: "searchInferenceEndpoints" image: https://source.unsplash.com/400x175/?github description: API docs for the searchInferenceEndpoints plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'searchInferenceEndpoints'] --- import searchInferenceEndpointsObj from './search_inference_endpoints.devdocs.json'; diff --git a/api_docs/search_navigation.devdocs.json b/api_docs/search_navigation.devdocs.json index 57616c4984477..26013fb6fa1fb 100644 --- a/api_docs/search_navigation.devdocs.json +++ b/api_docs/search_navigation.devdocs.json @@ -293,9 +293,9 @@ ") => ", { "pluginId": "@kbn/shared-ux-page-solution-nav", - "scope": "common", + "scope": "public", "docId": "kibKbnSharedUxPageSolutionNavPluginApi", - "section": "def-common.SolutionNavProps", + "section": "def-public.SolutionNavProps", "text": "SolutionNavProps" }, " | undefined" diff --git a/api_docs/search_navigation.mdx b/api_docs/search_navigation.mdx index 8c2cc3a58e92c..d61e2b5f4ef7c 100644 --- a/api_docs/search_navigation.mdx +++ b/api_docs/search_navigation.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/searchNavigation title: "searchNavigation" image: https://source.unsplash.com/400x175/?github description: API docs for the searchNavigation plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'searchNavigation'] --- import searchNavigationObj from './search_navigation.devdocs.json'; diff --git a/api_docs/search_notebooks.mdx b/api_docs/search_notebooks.mdx index daaa067073aed..0e8698d293017 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: 2025-01-24 +date: 2025-01-27 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 98d089b8f1a33..9dd1a580e80a9 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: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'searchPlayground'] --- import searchPlaygroundObj from './search_playground.devdocs.json'; diff --git a/api_docs/search_synonyms.mdx b/api_docs/search_synonyms.mdx index 0fad25f48cdb9..8b0123bbba261 100644 --- a/api_docs/search_synonyms.mdx +++ b/api_docs/search_synonyms.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/searchSynonyms title: "searchSynonyms" image: https://source.unsplash.com/400x175/?github description: API docs for the searchSynonyms plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'searchSynonyms'] --- import searchSynonymsObj from './search_synonyms.devdocs.json'; diff --git a/api_docs/security.mdx b/api_docs/security.mdx index 30e0f4fc41ef7..94a93d9a8b214 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: 2025-01-24 +date: 2025-01-27 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 f9237260114d3..bf158e630a7f3 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: 2025-01-24 +date: 2025-01-27 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 464560adedebc..3895c1bda824c 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: 2025-01-24 +date: 2025-01-27 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 9dd3590593a4b..61317838d65ad 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: 2025-01-24 +date: 2025-01-27 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 0494220cca1e5..f9683bc8cd4d9 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: 2025-01-24 +date: 2025-01-27 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 122653350be8b..d9e7c3f0400d5 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: 2025-01-24 +date: 2025-01-27 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 50ce736cc8933..ca5aca0bbe728 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: 2025-01-24 +date: 2025-01-27 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 9e10a404ba64b..479a0a694dfe0 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: 2025-01-24 +date: 2025-01-27 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 0d9c089fde616..c53cfb788c263 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: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'share'] --- import shareObj from './share.devdocs.json'; diff --git a/api_docs/slo.mdx b/api_docs/slo.mdx index 25d992039ab91..d7df72aa24ed9 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: 2025-01-24 +date: 2025-01-27 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 10b12c5419552..49edf8c9ac629 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: 2025-01-24 +date: 2025-01-27 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 52b18878342f5..4b35ebcfaf5a3 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: 2025-01-24 +date: 2025-01-27 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 15caa9ea13001..421a1ac3ca717 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: 2025-01-24 +date: 2025-01-27 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 ff2956096a421..1c8a7bd3b861a 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: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'stackConnectors'] --- import stackConnectorsObj from './stack_connectors.devdocs.json'; diff --git a/api_docs/streams.mdx b/api_docs/streams.mdx index 5ad1e7f27f234..f1f1c04ccabf7 100644 --- a/api_docs/streams.mdx +++ b/api_docs/streams.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/streams title: "streams" image: https://source.unsplash.com/400x175/?github description: API docs for the streams plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'streams'] --- import streamsObj from './streams.devdocs.json'; diff --git a/api_docs/streams_app.mdx b/api_docs/streams_app.mdx index 2323728735af2..3fbc4e8aa978e 100644 --- a/api_docs/streams_app.mdx +++ b/api_docs/streams_app.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/streamsApp title: "streamsApp" image: https://source.unsplash.com/400x175/?github description: API docs for the streamsApp plugin -date: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'streamsApp'] --- import streamsAppObj from './streams_app.devdocs.json'; diff --git a/api_docs/task_manager.mdx b/api_docs/task_manager.mdx index 97fe7f0dcbf91..c56ac5820f256 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: 2025-01-24 +date: 2025-01-27 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 afcf9e82b7aae..a12f8bc4551db 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: 2025-01-24 +date: 2025-01-27 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 a97252dd3bfb2..f1067983620d7 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: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'telemetryCollectionManager'] --- import telemetryCollectionManagerObj from './telemetry_collection_manager.devdocs.json'; diff --git a/api_docs/telemetry_management_section.mdx b/api_docs/telemetry_management_section.mdx index e9746d8a9ffd5..c969502eaad52 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: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'telemetryManagementSection'] --- import telemetryManagementSectionObj from './telemetry_management_section.devdocs.json'; diff --git a/api_docs/threat_intelligence.mdx b/api_docs/threat_intelligence.mdx index 5d54739bc84ab..4399b11c146bc 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: 2025-01-24 +date: 2025-01-27 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 d02a320edebff..146ff429bb143 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: 2025-01-24 +date: 2025-01-27 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 0e272de3477b3..3ea05fbba83bf 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: 2025-01-24 +date: 2025-01-27 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 b328e0afd5f74..1c065a8d313d8 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: 2025-01-24 +date: 2025-01-27 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 bf99963e124fd..9bb863cd28290 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: 2025-01-24 +date: 2025-01-27 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 62904e2c3ca73..a7ac352b46d77 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: 2025-01-24 +date: 2025-01-27 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 626d1a05b880e..82ecd3654fa7f 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: 2025-01-24 +date: 2025-01-27 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 a173db87ad70b..9130ff34f763a 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: 2025-01-24 +date: 2025-01-27 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 a0b46a6771648..59d637a2baed3 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: 2025-01-24 +date: 2025-01-27 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 73975fedbb471..0101e768f8a58 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: 2025-01-24 +date: 2025-01-27 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 a8c9be2c1aaf3..b491049a77dc8 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: 2025-01-24 +date: 2025-01-27 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 ba6f1ff6d7361..7199e78cdc953 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: 2025-01-24 +date: 2025-01-27 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 faa302f975c14..9fbadbe98ff89 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: 2025-01-24 +date: 2025-01-27 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 3ec53daaac523..d0a557e6d633d 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: 2025-01-24 +date: 2025-01-27 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 c9c418d4152fc..ffd19f6edf414 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: 2025-01-24 +date: 2025-01-27 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 339c345fc337c..ddcebc6fac068 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: 2025-01-24 +date: 2025-01-27 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 6d4aa58f7c52f..eb48951a2e30c 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: 2025-01-24 +date: 2025-01-27 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 af323279b8216..9c7c8f0de1658 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: 2025-01-24 +date: 2025-01-27 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 a1a5723bf7d4e..41329960712dc 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: 2025-01-24 +date: 2025-01-27 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 d809a2ea1bbf7..e1be13c8f7eca 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: 2025-01-24 +date: 2025-01-27 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 c274d1b7ed9bb..a47cef9cd9404 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: 2025-01-24 +date: 2025-01-27 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 28b3aeb8ff3f7..1cc3cdad8956d 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: 2025-01-24 +date: 2025-01-27 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 d4b64d8b831f8..32b91c45fc10f 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: 2025-01-24 +date: 2025-01-27 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 760695e4126d4..11de779e66971 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: 2025-01-24 +date: 2025-01-27 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 bdf67fde32b3f..5138949b52f1c 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: 2025-01-24 +date: 2025-01-27 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visualizations'] --- import visualizationsObj from './visualizations.devdocs.json'; diff --git a/docs/api/synthetics/private-locations/create-private-location.asciidoc b/docs/api/synthetics/private-locations/create-private-location.asciidoc index 61a71de535b9a..040cf26d851ec 100644 --- a/docs/api/synthetics/private-locations/create-private-location.asciidoc +++ b/docs/api/synthetics/private-locations/create-private-location.asciidoc @@ -37,6 +37,9 @@ The request body should contain the following attributes: - `lat` (Required, number): The latitude of the location. - `lon` (Required, number): The longitude of the location. +`spaces`:: +(Optional, array of strings) An array of space IDs where the private location is available. If not provided, the private location is available in all spaces. + [[private-location-create-example]] ==== Example @@ -53,6 +56,7 @@ POST /api/private_locations "lat": 40.7128, "lon": -74.0060 } + "spaces": ["default"] } -------------------------------------------------- diff --git a/docs/api/upgrade-assistant/status.asciidoc b/docs/api/upgrade-assistant/status.asciidoc index aec280e8d16f9..7a91ac76cdfcc 100644 --- a/docs/api/upgrade-assistant/status.asciidoc +++ b/docs/api/upgrade-assistant/status.asciidoc @@ -11,13 +11,19 @@ Check the status of your cluster. [[upgrade-assistant-api-status-request]] ==== Request -`GET :/api/upgrade_assistant/status` +`GET :/api/upgrade_assistant/status?targetVersion=9.0.0` + +`targetVersion`:: +(optional, string): Version to upgrade to. [[upgrade-assistant-api-status-response-codes]] ==== Response codes `200`:: Indicates a successful call. + +`403`:: + Indicates a forbidden request when the upgrade path is not supported (e.g. upgrading more than 1 major or downgrading) [[upgrade-assistant-api-status-example]] ==== Example @@ -28,11 +34,6 @@ The API returns the following: -------------------------------------------------- { "readyForUpgrade": false, - "cluster": [ - { - "message": "Cluster deprecated issue", - "details":"You have 2 system indices that must be migrated and 5 Elasticsearch deprecation issues and 0 Kibana deprecation issues that must be resolved before upgrading." - } - ] + "details":"The following issues must be resolved before upgrading: 1 Elasticsearch deprecation issue." } -------------------------------------------------- diff --git a/docs/developer/plugin-list.asciidoc b/docs/developer/plugin-list.asciidoc index 3aebfee0d2b4d..542ab1ef12869 100644 --- a/docs/developer/plugin-list.asciidoc +++ b/docs/developer/plugin-list.asciidoc @@ -670,10 +670,6 @@ the infrastructure monitoring use-case within Kibana. |undefined -|{kib-repo}blob/{branch}/x-pack/solutions/security/plugins/kubernetes_security/README.md[kubernetesSecurity] -|This plugin provides interactive visualizations of your Kubernetes workload and session data. - - |{kib-repo}blob/{branch}/x-pack/platform/plugins/shared/lens/readme.md[lens] |Lens is a visualization editor allowing to quickly and easily configure compelling visualizations to use on dashboards and canvas workpads. @@ -744,7 +740,7 @@ Elastic. |This plugin provides shared components and services for use across observability solutions, as well as the observability landing page UI. -|{kib-repo}blob/{branch}/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/README.md[observabilityAIAssistant] +|{kib-repo}blob/{branch}/x-pack/platform/plugins/shared/observability_ai_assistant/README.md[observabilityAIAssistant] |This document gives an overview of the features of the Observability AI Assistant at the time of writing, and how to use them. At a high level, the Observability AI Assistant offers contextual insights, and a chat functionality that we enrich with function calling, allowing the LLM to hook into the user's data. We also allow the LLM to store things it considers new information as embeddings into Elasticsearch, and query this knowledge base when it decides it needs more information, using ELSER. diff --git a/docs/discover/save-search.asciidoc b/docs/discover/save-search.asciidoc index d661e8c01b830..29d54f628a69b 100644 --- a/docs/discover/save-search.asciidoc +++ b/docs/discover/save-search.asciidoc @@ -10,7 +10,7 @@ and can also serve as a foundation for building visualizations. [[discover-read-only-access]] [float] === Read-only access -If you don't have sufficient privileges to save searches, the following indicator is +If you don't have sufficient privileges to save Discover sessions, the following indicator is displayed and the *Save* button is not visible. For more information, refer to <>. [role="screenshot"] diff --git a/docs/discover/search.asciidoc b/docs/discover/search.asciidoc index c7fde4159ec98..a131dd764e027 100644 --- a/docs/discover/search.asciidoc +++ b/docs/discover/search.asciidoc @@ -100,7 +100,7 @@ A Discover session includes the query text, filters, and optionally, the time fi [role="xpack"] [[discover-read-only-access]] ==== Read-only access -When you have insufficient privileges to save searches, the following indicator in Kibana will be +When you have insufficient privileges to save Discover sessions, the following indicator in Kibana will be displayed and the *Save* button won't be visible. For more information on granting access to Kibana see <>. diff --git a/docs/management/action-types.asciidoc b/docs/management/action-types.asciidoc index e3b01ba0afcf7..7e089c77fcda8 100644 --- a/docs/management/action-types.asciidoc +++ b/docs/management/action-types.asciidoc @@ -5,124 +5,33 @@ Connectors provide a central place to store connection information for services and integrations with Elastic or third party systems. Actions are instantiations of a connector that are linked to rules and run as background tasks on the {kib} server when rule conditions are met. {kib} provides the following types of connectors: -[cols="2"] -|=== - -// ifeval::["featureAIConnector"=="true"] -// a| <> - -// | Send a request to {infer}. -// endif::[] - -a| <> - -| Send a request to {bedrock}. - -a| <> - -| Add alerts to cases. - -a| <> - -| Send a request to CrowdStrike. - -a| <> - -| Send a request to D3 Security. - -a| <> - -| Send a request to {gemini}. - -a| <> - -| Send email from your server. - -a| <> - -| Create an incident in {ibm-r}. - -a| <> - -| Index data into Elasticsearch. - -a| <> - -| Create an incident in Jira. - -a| <> - -| Send a message to a Microsoft Teams channel. - -a| <> - -| Add AI-driven insights and custom actions to your workflow. - -a| <> - -| Send a request to OpenAI. - -a| <> - -| Create or close an alert in {opsgenie}. - -a| <> - -| Send an event in PagerDuty. - -a| <> - -| Send a request to SentinelOne. - -a| <> - -| Add a message to a Kibana log. - -a| <> - -| Create an incident in {sn}. - -a| <> - -| Create a security incident in {sn}. - -a| <> - -| Create an event in {sn}. - -a| <> - -| Send a message to a Slack channel or user. - -a| <> - -| Create an incident in {swimlane}. - -a| <> - -| Create cases and alerts in {hive}. - -a| <> - -| Send events to a Tines Story. - -a| <> - -| Trigger a Torq workflow. - -a| <> - -| Send a request to a web service. - -a| <> - -| Send a request to a Case Management web service. - -a| <> - -| Send actionable alerts to on-call xMatters resources. - -|=== +* <>: Send a request to {bedrock}. +* <>: Add alerts to cases. +* <>: Send a request to CrowdStrike. +* <>: Send a request to D3 Security. +* <>: Send a request to {gemini}. +* <>: Send email from your server. +* <>: Create an incident in {ibm-r}. +* <>: Index data into Elasticsearch. +* <>: Create an incident in Jira. +* <>: Send a message to a Microsoft Teams channel. +* <>: Add AI-driven insights and custom actions to your workflow. +* <>: Send a request to OpenAI. +* <>: Create or close an alert in {opsgenie}. +* <>: Send an event in PagerDuty. +* <>: Send a request to SentinelOne. +* <>: Add a message to a Kibana log. +* <>: Create an incident in {sn}. +* <>: Create a security incident in {sn}. +* <>: Create an event in {sn}. +* <>: Send a message to a Slack channel or user. +* <>: Create an incident in {swimlane}. +* <>: Create cases and alerts in {hive}. +* <>: Send events to a Tines Story. +* <>: Trigger a Torq workflow. +* <>: Send a request to a web service. +* <>: Send a request to a Case Management web service. +* <>: Send actionable alerts to on-call xMatters resources. [NOTE] ============================================== diff --git a/docs/management/cases/setup-cases.asciidoc b/docs/management/cases/setup-cases.asciidoc index 90c6bd29be561..8dc3ccbe0e6ed 100644 --- a/docs/management/cases/setup-cases.asciidoc +++ b/docs/management/cases/setup-cases.asciidoc @@ -1,20 +1,19 @@ [[setup-cases]] == Configure access to cases -:frontmatter-description: Learn about the {kib} feature privileges required to access cases. +:frontmatter-description: Learn about the {kib} feature privileges required to access cases. :frontmatter-tags-products: [kibana] -:frontmatter-tags-content-type: [how-to] +:frontmatter-tags-content-type: [how-to] :frontmatter-tags-user-goals: [configure] To access cases in *{stack-manage-app}*, you must have the appropriate {kib} privileges: -[options="header"] -|=== +[discrete] +=== Give full access to manage cases and settings + +**{kib} privileges** -| Action | {kib} privileges -| Give full access to manage cases and settings -a| * `All` for the *Cases* feature under *Management*. * `All` for the *{connectors-feature}* feature under *Management*. @@ -27,8 +26,12 @@ By default, `All` for the *Cases* feature includes authority to delete cases and comments, edit case settings, add case comments and attachments, and re-open cases unless you customize the sub-feature privileges. ==== -| Give assignee access to cases -a| `All` for the *Cases* feature under *Management*. +[discrete] +=== Give assignee access to cases + +**{kib} privileges** + +* `All` for the *Cases* feature under *Management*. [NOTE] ==== @@ -38,18 +41,28 @@ least once, which creates a user profile. This privilege is also required to add <> to rules. ==== -| Give view-only access to cases -a| `Read` for the *Cases* feature under *Management*. +[discrete] +=== Give view-only access to cases + +**{kib} privileges** + +* `Read` for the *Cases* feature under *Management*. NOTE: You can customize sub-feature privileges for deleting cases and comments, editing case settings, adding case comments and attachments, and re-opening cases. -| Revoke all access to cases | `None` for the *Cases* feature under *Management*. +[discrete] +=== Revoke all access to cases + +**{kib} privileges** + +`None` for the *Cases* feature under *Management*. -|=== +[discrete] +=== More details For more details, refer to <>. NOTE: If you are using an on-premises {kib} deployment and you want the email notifications and the external incident management systems to contain -links back to {kib}, you must configure the +links back to {kib}, you must configure the <> setting. diff --git a/docs/osquery/prebuilt-packs.asciidoc b/docs/osquery/prebuilt-packs.asciidoc index 776a1937b7a69..4b18fbe033cc1 100644 --- a/docs/osquery/prebuilt-packs.asciidoc +++ b/docs/osquery/prebuilt-packs.asciidoc @@ -1,7 +1,7 @@ [[prebuilt-packs]] == Prebuilt packs reference -This section lists all prebuilt packs available for Osquery Manager. +This section lists all prebuilt packs available for Osquery Manager. Each pack is also available as a saved object, with the name `Pack: `. For more information, refer to <>. @@ -21,10 +21,7 @@ For more information, refer to <>. |8.2 |`it-compliance` -a|Identify outdated and vulnerable software. - -Dashboard: `[Osquery Manager] Compliance pack` - +|Identify outdated and vulnerable software. Dashboard: `[Osquery Manager] Compliance pack` |https://github.com/osquery/osquery/tree/master/packs[Osquery] |8.2 @@ -34,10 +31,7 @@ Dashboard: `[Osquery Manager] Compliance pack` |8.2 |`ossec-rootkit` -a|Run rootkit detection queries to monitor for compromise. - -Dashboard: `[Osquery Manager] OSSEC rootkit pack` - +|Run rootkit detection queries to monitor for compromise. Dashboard: `[Osquery Manager] OSSEC rootkit pack` |https://github.com/osquery/osquery/tree/master/packs[Osquery] |8.2 diff --git a/docs/search/playground/index.asciidoc b/docs/search/playground/index.asciidoc index 465637e79bc02..7b51884b6a303 100644 --- a/docs/search/playground/index.asciidoc +++ b/docs/search/playground/index.asciidoc @@ -4,8 +4,8 @@ preview::[] -// Variable (attribute) definition -:x: Playground +// Variable (attribute) definition +:x: Playground Use {x} to combine your Elasticsearch data with the power of large language models (LLMs) for retrieval augmented generation (RAG). The chat interface translates your natural language questions into {es} queries, retrieves the most relevant results from your {es} documents, and passes those documents to the LLM to generate tailored responses. @@ -66,37 +66,19 @@ To use {x}, you'll need the following: ** See <> if you'd like to ingest sample data. 3. An account with a *supported LLM provider*. {x} supports the following: + -[cols="2a,2a,1a", options="header"] -|=== -| Provider | Models | Notes - -| *Amazon Bedrock* -a| -* Anthropic: Claude 3.5 Sonnet -* Anthropic: Claude 3 Haiku -a| - -| *OpenAI* -a| -* GPT-3 turbo -* GPT-4 turbo -* GPT-4 omni -a| - -| *Azure OpenAI* -a| -* GPT-3 turbo -* GPT-4 turbo -a| -Buffers responses in large chunks - -| *Google* -a| -* Google Gemini 1.5 Pro -* Google Gemini 1.5 Flash -a| - -|=== +** *Amazon Bedrock* +*** Anthropic: Claude 3.5 Sonnet +*** Anthropic: Claude 3 Haiku +** *OpenAI* +*** GPT-3 turbo +*** GPT-4 turbo +*** GPT-4 omni +** *Azure OpenAI* (note: Buffers responses in large chunks) +*** GPT-3 turbo +*** GPT-4 turbo +** *Google* +*** Google Gemini 1.5 Pro +*** Google Gemini 1.5 Flash [[playground-local-llms]] [TIP] @@ -171,7 +153,7 @@ POST /_bulk ---- ============== -We've also provided some Jupyter notebooks to easily ingest sample data into {es}. +We've also provided some Jupyter notebooks to easily ingest sample data into {es}. Find these in the https://github.com/elastic/elasticsearch-labs/blob/main/notebooks/ingestion-and-chunking[elasticsearch-labs] repository. These notebooks use the official {es} Python client. diff --git a/docs/setup/settings.asciidoc b/docs/setup/settings.asciidoc index 14c691e17408b..ceef418ed9e89 100644 --- a/docs/setup/settings.asciidoc +++ b/docs/setup/settings.asciidoc @@ -480,6 +480,40 @@ NOTE: By default, enabling `http2` requires a valid `h2c` configuration, meaning and <>, if specified, must contain at least `TLSv1.2` or `TLSv1.3`. Strict validation of the `h2c` setup can be disabled by adding `server.http2.allowUnsecure: true` to the configuration. +[[server-rate-limiter-enabled]] `server.rateLimiter.enabled`:: +Enables rate-limiting of requests to the {kib} server based on Node.js' Event Loop Utilization. +If the average event loop utilization for the specified term exceeds the configured threshold, the server will respond with a `429 Too Many Requests` status code. ++ +This functionality should be used carefully as it may impact the server's availability. +The configuration options vary per environment, so it is recommended to enable this option in a testing environment first, adjust the rate-limiter configuration, and then roll it out to production. ++ +*Default: `false`* + +`server.rateLimiter.elu`:: +The Event Loop Utilization (ELU) threshold for rate-limiting requests to the {kib} server. +The ELU is a value between 0 and 1, representing the average event loop utilization over the specified term. +If the average ELU exceeds this threshold, the server will respond with a `429 Too Many Requests` status code. ++ +In a multi-instance environment with autoscaling, this value is usually between 0.6 and 0.8 to give the autoscaler enough time to react. +This value can be higher in a single-instance environment but should not exceed 1.0. In general, the lower the value, the more aggressive the rate limiting. +And the highest possible option should be used to prevent the {kib} server from being terminated. + +`server.rateLimiter.term`:: +This value is one of `short`, `medium`, or `long`, representing the term over which the average event loop utilization is calculated. +It uses exponential moving averages (EMA) to smooth out the utilization values. +Each term corresponds to `15s`, `30s`, and `60s`, respectively. ++ +The term value also changes the way the rate limiter sees the trend in the load: ++ +- `short`: `elu.short > server.rateLimiter.term`; +- `medium`: `elu.short > server.rateLimiter.elu AND elu.medium > server.rateLimiter.elu`; +- `long`: `elu.short > server.rateLimiter.elu AND elu.medium > server.rateLimiter.elu AND elu.long > server.rateLimiter.elu`. + ++ +This behavior prevents requests from being throttled if the load starts decreasing. +In general, the shorter the term, the more aggressive the rate limiting. +In the multi-instance environment, the `medium` term makes the most sense as it gives the {kib} server enough time to spin up a new instance and prevents the existing instances from being terminated. + [[server-requestId-allowFromAnyIp]] `server.requestId.allowFromAnyIp`:: Sets whether or not the `X-Opaque-Id` header should be trusted from any IP address for identifying requests in logs and forwarded to Elasticsearch. diff --git a/docs/user/alerting/alerting-setup.asciidoc b/docs/user/alerting/alerting-setup.asciidoc index a5a529eb016f4..76fda7a5ff79a 100644 --- a/docs/user/alerting/alerting-setup.asciidoc +++ b/docs/user/alerting/alerting-setup.asciidoc @@ -5,11 +5,11 @@ ++++ :frontmatter-description: Prerequisites and production considerations for using {kib} {alert-features}. -:frontmatter-tags-products: [alerting] -:frontmatter-tags-content-type: [other] +:frontmatter-tags-products: [alerting] +:frontmatter-tags-content-type: [other] :frontmatter-tags-user-goals: [configure] -{kib} {alert-features} are automatically enabled, but might require some additional +{kib} {alert-features} are automatically enabled, but might require some additional configuration. [float] @@ -17,28 +17,28 @@ configuration. === Prerequisites If you are using an *on-premises* {stack} deployment: -* In the `kibana.yml` configuration file, add the -<> +* In the `kibana.yml` configuration file, add the +<> setting. -* For emails to have a footer with a link back to {kib}, set the +* For emails to have a footer with a link back to {kib}, set the <> configuration setting. -If you are using an *on-premises* {stack} deployment with +If you are using an *on-premises* {stack} deployment with <>: -* If you are unable to access {kib} {alert-features}, ensure that you have not +* If you are unable to access {kib} {alert-features}, ensure that you have not {ref}/security-settings.html#api-key-service-settings[explicitly disabled API keys]. -The alerting framework uses queries that require the -`search.allow_expensive_queries` setting to be `true`. See the scripts -{ref}/query-dsl-script-query.html#_allow_expensive_queries_4[documentation]. +The alerting framework uses queries that require the +`search.allow_expensive_queries` setting to be `true`. See the scripts +{ref}/query-dsl-script-query.html#_allow_expensive_queries_4[documentation]. [float] [[alerting-setup-production]] === Production considerations and scaling guidance -When relying on alerting and actions as mission critical services, make sure you -follow the +When relying on alerting and actions as mission critical services, make sure you +follow the <>. For more information on the scalability of {alert-features}, go to @@ -50,12 +50,11 @@ For more information on the scalability of {alert-features}, go to To use {alert-features} in a {kib} app, you must have the appropriate feature privileges: -[options="header"] -|=== +[discrete] +==== Give full access to manage alerts, connectors, and rules in *{stack-manage-app}* + +**{kib} privileges** -| Action | {kib} privileges -| Give full access to manage alerts, connectors, and rules in *{stack-manage-app}* -a| * `All` for the *Management > {stack-rules-feature}* feature. * `All` for the *Management > Rules Settings* feature. * `All` for the *Management > {connectors-feature}* feature. @@ -77,8 +76,11 @@ For {observability} rules, you must have `all` privileges for the appropriate {o For Security rules, refer to {security-guide}/detections-permissions-section.html[Detections prerequisites and requirements]. ==== -| Give view-only access to alerts, connectors, and rules in *{stack-manage-app}* -a| +[discrete] +==== Give view-only access to alerts, connectors, and rules in *{stack-manage-app}* + +**{kib} privileges** + * `Read` for the *Management > {stack-rules-feature}* feature. * `Read` for the *Management > Rules Settings* feature. * `Read` for the *Management > {connectors-feature}* feature. @@ -92,17 +94,25 @@ For {observability} rules, you must have `read` privileges for the appropriate { For Security rules, refer to {security-guide}/detections-permissions-section.html[Detections prerequisites and requirements]. ==== -| Give view-only access to alerts in *Discover* or *Dashboards* -a| +[discrete] +==== Give view-only access to alerts in *Discover* or *Dashboards* + +**{kib} privileges** + * `Read` index privileges for the `.alerts-*` system indices. -| Revoke all access to alerts, connectors, and rules in *{stack-manage-app}*, *Discover*, or *Dashboards* -a| +[discrete] +==== Revoke all access to alerts, connectors, and rules in *{stack-manage-app}*, *Discover*, or *Dashboards* + +**{kib} privileges** + * `None` for the *Management > {stack-rules-feature}* feature. * `None` for the *Management > Rules Settings* feature. * `None` for the *Management > {connectors-feature}* feature. * No index privileges for the `.alerts-*` system indices. -|=== + +[discrete] +==== More details For more information on configuring roles that provide access to features, go to <>. @@ -147,8 +157,8 @@ You can use <> to disable certain <> and allowlis [[alerting-spaces]] === Space isolation -Rules and connectors are isolated to the {kib} space in which they were created. -A rule or connector created in one space will not be visible in another. +Rules and connectors are isolated to the {kib} space in which they were created. +A rule or connector created in one space will not be visible in another. [float] [[alerting-ccs-setup]] diff --git a/docs/user/dashboard/aggregation-based.asciidoc b/docs/user/dashboard/aggregation-based.asciidoc index e3f1f0bea6718..0d71a50459958 100644 --- a/docs/user/dashboard/aggregation-based.asciidoc +++ b/docs/user/dashboard/aggregation-based.asciidoc @@ -27,73 +27,53 @@ Aggregation-based visualizations include the following limitations: [cols="50, 50"] |=== -a| *Area* - -Displays data points, connected by a line, where the area between the line and axes are shaded. +| *Area*: Displays data points, connected by a line, where the area between the line and axes are shaded. Use area charts to compare two or more categories over time, and display the magnitude of trends. | image:images/area.png[Area chart] -a| *Data table* - -Displays your aggregation results in a tabular format. Use data tables to display server configuration details, track counts, min, +| *Data table*: Displays your aggregation results in a tabular format. Use data tables to display server configuration details, track counts, min, or max values for a specific field, and monitor the status of key services. | image:images/data_table.png[Data table] -a| *Gauge* - -Displays your data along a scale that changes color according to where your data falls on the expected scale. Use the gauge to show how metric +| *Gauge*: Displays your data along a scale that changes color according to where your data falls on the expected scale. Use the gauge to show how metric values relate to reference threshold values, or determine how a specified field is performing versus how it is expected to perform. | image:images/gauge.png[Gauge] -a| *Goal* - -Displays how your metric progresses toward a fixed goal. Use the goal to display an easy to read visual of the status of your goal progression. +| *Goal*: Displays how your metric progresses toward a fixed goal. Use the goal to display an easy to read visual of the status of your goal progression. | image:images/goal.png[Goal] -a| *Heat map* - -Displays graphical representations of data where the individual values are represented by colors. Use heat maps when your data set includes +| *Heat map*: Displays graphical representations of data where the individual values are represented by colors. Use heat maps when your data set includes categorical data. For example, use a heat map to see the flights of origin countries compared to destination countries using the sample flight data. | image:images/heat_map.png[Heat map] -a| *Horizontal Bar* - -Displays bars side-by-side where each bar represents a category. Use bar charts to compare data across a +| *Horizontal Bar*: Displays bars side-by-side where each bar represents a category. Use bar charts to compare data across a large number of categories, display data that includes categories with negative values, and easily identify the categories that represent the highest and lowest values. {kib} also supports vertical bar charts. | image:images/bar.png[Bar chart] -a| *Line* - -Displays data points that are connected by a line. Use line charts to visualize a sequence of values, discover +| *Line*: Displays data points that are connected by a line. Use line charts to visualize a sequence of values, discover trends over time, and forecast future values. | image:images/line.png[Line chart] -a| *Metric* - -Displays a single numeric value for an aggregation. Use the metric visualization when you have a numeric value that is powerful enough to tell +| *Metric*: Displays a single numeric value for an aggregation. Use the metric visualization when you have a numeric value that is powerful enough to tell a story about your data. | image:images/metric.png[Metric] -a| *Pie* - -Displays slices that represent a data category, where the slice size is proportional to the quantity it represents. +| *Pie*: Displays slices that represent a data category, where the slice size is proportional to the quantity it represents. Use pie charts to show comparisons between multiple categories, illustrate the dominance of one category over others, and show percentage or proportional data. | image:images/pie.png[Pie chart] -a| *Tag cloud* - -Graphical representations of how frequently a word appears in the source text. Use tag clouds to easily produce a summary of large documents and +| *Tag cloud*: Graphical representations of how frequently a word appears in the source text. Use tag clouds to easily produce a summary of large documents and create visual art for a specific topic. | image:images/tag_cloud.png[Tag cloud] @@ -112,19 +92,19 @@ Choose the type of visualization you want to create, then use the editor to conf .. Select the data source you want to visualize. + -NOTE: There is no performance impact on the data source you select. For example, saved Discover sessions perform the same as {data-sources}. +NOTE: There is no performance impact on the data source you select. For example, saved Discover sessions perform the same as {data-sources}. -. Add the <> you want to visualize using the editor, then click *Update*. +. Add the <> you want to visualize using the editor, then click *Update*. + NOTE: For the *Date Histogram* to use an *auto interval*, the date field must match the primary time field of the {data-source}. -. To change the order, drag and drop the aggregations in the editor. -+ +. To change the order, drag and drop the aggregations in the editor. ++ [role="screenshot"] image:images/bar-chart-tutorial-3.png[Option to change the order of aggregations] . To customize the series colors, click the series in the legend, then select the color you want to use. -+ ++ [role="screenshot"] image:images/aggregation-based-color-picker.png[Color picker] @@ -149,7 +129,7 @@ Add the sample web logs data that you'll use to create the bar chart, then creat [float] ===== Open and set up the aggregation-based bar chart -Open the *Aggregation based* editor and change the time range. +Open the *Aggregation based* editor and change the time range. . On the dashboard, click *All types > Aggregation based*, select *Vertical bar*, then select *Kibana Sample Data Logs*. @@ -237,6 +217,3 @@ To save the panel to the dashboard: .. On the *Panel settings* window, select *Show title*. .. Enter the *Title*, then click *Save*. - - - diff --git a/docs/user/dashboard/drilldowns.asciidoc b/docs/user/dashboard/drilldowns.asciidoc index cb568d97e69ee..ac9ae7ca32941 100644 --- a/docs/user/dashboard/drilldowns.asciidoc +++ b/docs/user/dashboard/drilldowns.asciidoc @@ -2,20 +2,20 @@ [[drilldowns]] === Add drilldowns -Panels have built-in interactive capabilities that apply filters to the dashboard data. For example, when you drag a time range or click a pie slice, a filter for the time range or pie slice is applied. Drilldowns let you customize the interactive behavior while keeping the context of the interaction. +Panels have built-in interactive capabilities that apply filters to the dashboard data. For example, when you drag a time range or click a pie slice, a filter for the time range or pie slice is applied. Drilldowns let you customize the interactive behavior while keeping the context of the interaction. There are three types of drilldowns you can add to dashboards: * *Dashboard* — Navigates you from one dashboard to another dashboard. For example, create a drilldown for a *Lens* panel that navigates you from a summary dashboard to a dashboard with a filter for a specific host name. -* *URL* — Navigates you from a dashboard to an external website. For example, a website with the specific host name as a parameter. +* *URL* — Navigates you from a dashboard to an external website. For example, a website with the specific host name as a parameter. -* *Discover* — Navigates you from a *Lens* dashboard panel to *Discover*. For example, create a drilldown for a *Lens* visualization that opens the visualization data in *Discover* for further exploration. +* *Discover* — Navigates you from a *Lens* dashboard panel to *Discover*. For example, create a drilldown for a *Lens* visualization that opens the visualization data in *Discover* for further exploration. Third-party developers can create drilldowns. To learn how to code drilldowns, refer to {kib-repo}blob/{branch}/x-pack/examples/ui_actions_enhanced_examples[this example plugin]. ++++ - > you use to create a <> depends on the trigger you choose. URL drilldowns support these types of triggers: * *Single click* — A single data point in the panel. @@ -171,7 +171,7 @@ image:images/dashboard_urlDrilldownGithub_8.3.png[Open ios issues in the elastic Discover drilldowns enable you to open *Discover* from a *Lens* dashboard panel, taking the time range, filters, and other parameters with you so the context remains the same. -For example, when you create a Discover drilldown for a pie chart, you can click a slice in the pie chart, and only the documents for the slice appear in *Discover*. +For example, when you create a Discover drilldown for a pie chart, you can click a slice in the pie chart, and only the documents for the slice appear in *Discover*. [role="screenshot"] image:images/dashboard_discoverDrilldown_8.3.gif[Drilldown on bar vertical stacked chart that navigates to Discover] @@ -204,7 +204,7 @@ image::images/dashboard_discoverDrilldown_8.3.png[Drilldown on bar vertical stac [[manage-drilldowns]] ==== Manage drilldowns -Make changes to your drilldowns, make a copy of your drilldowns for another panel, and delete drilldowns. +Make changes to your drilldowns, make a copy of your drilldowns for another panel, and delete drilldowns. . Open the panel menu that includes the drilldown, then click *Manage drilldowns*. @@ -212,7 +212,7 @@ Make changes to your drilldowns, make a copy of your drilldowns for another pane * To change drilldowns, click *Edit* next to the drilldown you want to change, make your changes, then click *Save*. -* To make a copy, click *Copy* next to the drilldown you want to change, enter the drilldown name, then click *Create drilldown*. +* To make a copy, click *Copy* next to the drilldown you want to change, enter the drilldown name, then click *Create drilldown*. * To delete a drilldown, select the drilldown you want to delete, then click *Delete*. @@ -236,11 +236,12 @@ In addition to https://ela.st/handlebars-helpers[built-in] Handlebars helpers, Refer to Handlebars https://ela.st/handlebars-docs#expressions[documentation] to learn about advanced use cases. -|=== -|Custom helper |Use case +[float] +==== Custom helpers + +**json** -|json -a|Serialize variables in JSON format. +Serialize variables in JSON format. Example: @@ -249,8 +250,9 @@ Example: `{{json filters=context.panel.filters}}` -|rison -a|Serialize variables in https://github.com/w33ble/rison-node[rison] format. Rison is a common format for {kib} apps for storing state in the URL. +**rison** + +Serialize variables in https://github.com/w33ble/rison-node[rison] format. Rison is a common format for {kib} apps for storing state in the URL. Example: @@ -258,107 +260,121 @@ Example: `{{rison event.key event.value}}` + `{{rison filters=context.panel.filters}}` +**date** -|date -a|Format dates. Supports relative dates expressions (for example, "now-15d"). Refer to the https://momentjs.com/docs/#/displaying/format/[moment] docs for different formatting options. +Format dates. Supports relative dates expressions (for example, "now-15d"). Refer to the https://momentjs.com/docs/#/displaying/format/[moment] docs for different formatting options. Example: `{{date event.from “YYYY MM DD”}}` + `{{date “now-15”}}` -|formatNumber -a|Format numbers. Numbers can be formatted to look like currency, percentages, times or numbers with decimal places, thousands, and abbreviations. -Refer to the http://numeraljs.com/#format[numeral.js] for different formatting options. +**formatNumber** + +Format numbers. Numbers can be formatted to look like currency, percentages, times or numbers with decimal places, thousands, and abbreviations. +Refer to the http://numeraljs.com/#format[numeral.js] for different formatting options. Example: `{{formatNumber event.value "0.0"}}` -|lowercase -a|Converts a string to lower case. +**lowercase** + +Converts a string to lower case. Example: `{{lowercase event.value}}` -|uppercase -a|Converts a string to upper case. +**uppercase** + +Converts a string to upper case. Example: `{{uppercase event.value}}` -|trim -a|Removes leading and trailing spaces from a string. +**trim** + +Removes leading and trailing spaces from a string. Example: `{{trim event.value}}` -|trimLeft -a|Removes leading spaces from a string. +**trimLeft** + +Removes leading spaces from a string. Example: `{{trimLeft event.value}}` -|trimRight -a|Removes trailing spaces from a string. +**trimRight** + +Removes trailing spaces from a string. Example: `{{trimRight event.value}}` -|mid -a|Extracts a substring from a string by start position and number of characters to extract. +**mid** + +Extracts a substring from a string by start position and number of characters to extract. Example: -`{{mid event.value 3 5}}` - extracts five characters starting from a third character. +`{{mid event.value 3 5}}` - extracts five characters starting from a third character. + +**left** -|left -a|Extracts a number of characters from a string (starting from left). +Extracts a number of characters from a string (starting from left). Example: `{{left event.value 3}}` -|right -a|Extracts a number of characters from a string (starting from right). +**right** + +Extracts a number of characters from a string (starting from right). Example: `{{right event.value 3}}` -|concat -a|Concatenates two or more strings. +**concat** + +Concatenates two or more strings. Example: `{{concat event.value "," event.key}}` -|replace -a|Replaces all substrings within a string. +**replace** + +Replaces all substrings within a string. Example: `{{replace event.value "stringToReplace" "stringToReplaceWith"}}` -|split -a|Splits a string using a provided splitter. +**split** + +Splits a string using a provided splitter. Example: `{{split event.value ","}}` -|encodeURIComponent -a|Escapes string using built in `encodeURIComponent` function. +**encodeURIComponent** + +Escapes string using built in `encodeURIComponent` function. + +**encodeURIQuery** + +Escapes string using built in `encodeURIComponent` function, while keeping "@", ":", "$", ",", and ";" characters as is. -|encodeURIQuery -a|Escapes string using built in `encodeURIComponent` function, while keeping "@", ":", "$", ",", and ";" characters as is. -|=== [float] @@ -453,7 +469,7 @@ Example: Note: -`{{event.value}}` is a shorthand for `{{event.points.[0].value}}` + +`{{event.value}}` is a shorthand for `{{event.points.[0].value}}` + `{{event.key}}` is a shorthand for `{{event.points.[0].key}}` | *Row click* diff --git a/docs/user/dashboard/url-drilldown.asciidoc b/docs/user/dashboard/url-drilldown.asciidoc index 3fc2b76cf9e67..d0ad4552d5d68 100644 --- a/docs/user/dashboard/url-drilldown.asciidoc +++ b/docs/user/dashboard/url-drilldown.asciidoc @@ -17,11 +17,12 @@ In addition to https://ela.st/handlebars-helpers[built-in] Handlebars helpers, Refer to Handlebars https://ela.st/handlebars-docs#expressions[documentation] to learn about advanced use cases. -|=== -|Custom helper |Use case +[discrete] +==== Custom helpers + +**json** -|json -a|Serialize variables in JSON format. +Serialize variables in JSON format. Example: @@ -29,9 +30,9 @@ Example: `{{json event.key event.value}}` + `{{json filters=context.panel.filters}}` +**rison** -|rison -a|Serialize variables in https://github.com/w33ble/rison-node[rison] format. Rison is a common format for {kib} apps for storing state in the URL. +Serialize variables in https://github.com/w33ble/rison-node[rison] format. Rison is a common format for {kib} apps for storing state in the URL. Example: @@ -39,106 +40,96 @@ Example: `{{rison event.key event.value}}` + `{{rison filters=context.panel.filters}}` +**date** -|date -a|Format dates. Supports relative dates expressions (for example, "now-15d"). Refer to the https://momentjs.com/docs/#/displaying/format/[moment] docs for different formatting options. +Format dates. Supports relative dates expressions (for example, "now-15d"). Refer to the https://momentjs.com/docs/#/displaying/format/[moment] docs for different formatting options. Example: `{{date event.from “YYYY MM DD”}}` + -`{{date “now-15d”}}` + +`{{date “now-15d”}}` + `{{date “now/d” roundUp=true}}` -|formatNumber -a|Format numbers. Numbers can be formatted to look like currency, percentages, times or numbers with decimal places, thousands, and abbreviations. -Refer to the http://numeraljs.com/#format[numeral.js] for different formatting options. +**formatNumber** -Example: +Format numbers. Numbers can be formatted to look like currency, percentages, times or numbers with decimal places, thousands, and abbreviations. +Refer to the http://numeraljs.com/#format[numeral.js] for different formatting options. -`{{formatNumber event.value "0.0"}}` +Example: `{{formatNumber event.value "0.0"}}` -|lowercase -a|Converts a string to lower case. +**lowercase** -Example: +Converts a string to lower case. -`{{lowercase event.value}}` +Example: `{{lowercase event.value}}` -|uppercase -a|Converts a string to upper case. +**uppercase** -Example: +Converts a string to upper case. -`{{uppercase event.value}}` +Example: `{{uppercase event.value}}` -|trim -a|Removes leading and trailing spaces from a string. +**trim** -Example: +Removes leading and trailing spaces from a string. -`{{trim event.value}}` +Example: `{{trim event.value}}` -|trimLeft -a|Removes leading spaces from a string. +**trimLeft** -Example: +Removes leading spaces from a string. -`{{trimLeft event.value}}` +Example: `{{trimLeft event.value}}` -|trimRight -a|Removes trailing spaces from a string. +**trimRight** -Example: +Removes trailing spaces from a string. -`{{trimRight event.value}}` +Example: `{{trimRight event.value}}` -|mid -a|Extracts a substring from a string by start position and number of characters to extract. +**mid** -Example: +Extracts a substring from a string by start position and number of characters to extract. -`{{mid event.value 3 5}}` - extracts five characters starting from a third character. +Example: `{{mid event.value 3 5}}` - extracts five characters starting from a third character. -|left -a|Extracts a number of characters from a string (starting from left). +**left** -Example: +Extracts a number of characters from a string (starting from left). -`{{left event.value 3}}` +Example: `{{left event.value 3}}` -|right -a|Extracts a number of characters from a string (starting from right). +**right** -Example: +Extracts a number of characters from a string (starting from right). -`{{right event.value 3}}` +Example: `{{right event.value 3}}` -|concat -a|Concatenates two or more strings. +**concat** -Example: +Concatenates two or more strings. -`{{concat event.value "," event.key}}` +Example: `{{concat event.value "," event.key}}` -|replace -a|Replaces all substrings within a string. +**replace** -Example: +Replaces all substrings within a string. -`{{replace event.value "stringToReplace" "stringToReplaceWith"}}` +Example: `{{replace event.value "stringToReplace" "stringToReplaceWith"}}` -|split -a|Splits a string using a provided splitter. +**split** -Example: +Splits a string using a provided splitter. + +Example: `{{split event.value ","}}` + +**encodeURIComponent** -`{{split event.value ","}}` +Escapes string using built in `encodeURIComponent` function. -|encodeURIComponent -a|Escapes string using built in `encodeURIComponent` function. +**encodeURIQuery** -|encodeURIQuery -a|Escapes string using built in `encodeURIComponent` function, while keeping "@", ":", "$", ",", and ";" characters as is. +Escapes string using built in `encodeURIComponent` function, while keeping "@", ":", "$", ",", and ";" characters as is. |=== @@ -235,7 +226,7 @@ Example: Note: -`{{event.value}}` is a shorthand for `{{event.points.[0].value}}` + +`{{event.value}}` is a shorthand for `{{event.points.[0].value}}` + `{{event.key}}` is a shorthand for `{{event.points.[0].key}}` | *Row click* diff --git a/docs/user/dashboard/vega-reference.asciidoc b/docs/user/dashboard/vega-reference.asciidoc index 95b1ffb27b476..0e74898bb47ec 100644 --- a/docs/user/dashboard/vega-reference.asciidoc +++ b/docs/user/dashboard/vega-reference.asciidoc @@ -278,7 +278,7 @@ experimental[] To enable *Maps*, the graph must specify `type=map` in the host c "mapStyle": false, // When 'mapStyle' is 'undefined' or 'true', sets the EMS-layer for the map. - // May either be: "road_map", "road_map_desaturated", "dark_map". + // May either be: "road_map", "road_map_desaturated", "dark_map", "road_map_desaturated_v9", "dark_map_v9". // If 'emsTileServiceId' is 'undefined', it falls back to the auto-switch-dark-light behavior. "emsTileServiceId": "road_map", diff --git a/docs/user/dev-tools.asciidoc b/docs/user/dev-tools.asciidoc index c3610d348e0c0..2b949e36f2280 100644 --- a/docs/user/dev-tools.asciidoc +++ b/docs/user/dev-tools.asciidoc @@ -10,21 +10,17 @@ with your data. [cols="2"] |=== -a| <> - +| <> | Interact with the REST APIs of {es} and {kib}, including sending requests and viewing API documentation. -a| <> - +| <> | Inspect and analyze your search queries. -a| <> - +| <> | Build and debug grok patterns before you use them in your data processing pipelines. -a| <> - +| <> | beta:[] Test and debug Painless scripts in real-time. |=== diff --git a/docs/user/discover.asciidoc b/docs/user/discover.asciidoc index 7cab19889f278..640333643d59c 100644 --- a/docs/user/discover.asciidoc +++ b/docs/user/discover.asciidoc @@ -11,7 +11,7 @@ What processes take longer than 500 milliseconds to respond? [[save-your-search]] With *Discover*, you can quickly search and filter your data, get information about the structure of the fields, and display your findings in a visualization. -You can also customize and save your searches and place them on a dashboard. +You can also customize and save your Discover sessions and place them on a dashboard. [role="screenshot"] image::images/hello-field.png[A view of the Discover app] diff --git a/docs/user/management.asciidoc b/docs/user/management.asciidoc index b503dbdc2d0ea..59b1f00c15914 100644 --- a/docs/user/management.asciidoc +++ b/docs/user/management.asciidoc @@ -34,7 +34,7 @@ and enrichments on your data. [cols="50, 50"] |=== -a| {ref}/index-mgmt.html[Index Management] +| {ref}/index-mgmt.html[Index Management] | View index settings, mappings, and statistics and perform operations, such as refreshing, flushing, and clearing the cache. Practicing good index management ensures that your data is stored cost effectively. @@ -109,7 +109,7 @@ above a certain percentage. [cols="50, 50"] |=== -a| <> +| <> |View the users that have been defined on your cluster. Add or delete users and assign roles that give users specific privileges. @@ -136,7 +136,7 @@ Kerberos, PKI, OIDC, and SAML. [cols="50, 50"] |=== -a| <> +| <> |Manage the fields in the data views that retrieve your data from {es}. | <> @@ -157,7 +157,7 @@ for example, when you have a large volume of data or when the performance of you A space is isolated from all other spaces, so you can tailor it to your needs without impacting others. -a| <> +| <> | Customize {kib} to suit your needs. Change the format for displaying dates, turn on dark mode, set the timespan for notification messages, and much more. @@ -210,5 +210,3 @@ include::{kibana-root}/docs/management/managing-tags.asciidoc[] include::{kibana-root}/docs/management/upgrade-assistant.asciidoc[] include::{kibana-root}/docs/management/watcher-ui/index.asciidoc[] - - diff --git a/docs/user/production-considerations/task-manager-health-monitoring.asciidoc b/docs/user/production-considerations/task-manager-health-monitoring.asciidoc index f975816462962..9a6a58908bdd2 100644 --- a/docs/user/production-considerations/task-manager-health-monitoring.asciidoc +++ b/docs/user/production-considerations/task-manager-health-monitoring.asciidoc @@ -29,7 +29,7 @@ Monitoring the `_health` endpoint of each {kib} instance in the cluster is the r The health monitoring API monitors the performance of Task Manager out of the box. However, certain performance considerations are deployment specific and you can configure them. -A health threshold is the threshold for failed task executions. Once a task exceeds this threshold, a status of `warn` or `error` is set on the task type execution. To configure a health threshold, use the <> setting. You can apply this this setting to all task types in the system, or to a custom task type. +A health threshold is the threshold for failed task executions. Once a task exceeds this threshold, a status of `warn` or `error` is set on the task type execution. To configure a health threshold, use the <> setting. You can apply this this setting to all task types in the system, or to a custom task type. By default, this setting marks the health of every task type as `warning` when it exceeds 80% failed executions, and as `error` at 90%. Set this value to a number between 0 to 100. The threshold is hit when the value *exceeds* this number. @@ -99,21 +99,16 @@ The health monitoring API exposes three sections: `configuration`, `workload` an [cols="2"] |=== -a| Configuration - +| Configuration | This section summarizes the current configuration of Task Manager. This includes dynamic configurations that change over time, such as `poll_interval` and `max_workers`, which can adjust in reaction to changing load on the system. -a| Workload - +| Workload | This section summarizes the work load across the cluster, including the tasks in the system, their types, and current status. -a| Runtime - +| Runtime | This section tracks execution performance of Task Manager, tracking task _drift_, worker _load_, and execution stats broken down by type, including duration and execution results. - -a| Capacity Estimation - +| Capacity Estimation | This section provides a rough estimate about the sufficiency of its capacity. As the name suggests, these are estimates based on historical data and should not be used as predictions. Use these estimations when following the Task Manager <>. |=== diff --git a/oas_docs/bundle.json b/oas_docs/bundle.json index 3b284d7786f84..270a4d627b14f 100644 --- a/oas_docs/bundle.json +++ b/oas_docs/bundle.json @@ -1387,6 +1387,25 @@ "nullable": true, "type": "number" }, + "gap_range": { + "additionalProperties": false, + "nullable": true, + "properties": { + "gte": { + "description": "End of the gap range.", + "type": "string" + }, + "lte": { + "description": "Start of the gap range.", + "type": "string" + } + }, + "required": [ + "lte", + "gte" + ], + "type": "object" + }, "total_alerts_created": { "description": "Total number of alerts created during last rule run.", "nullable": true, @@ -2561,6 +2580,25 @@ "nullable": true, "type": "number" }, + "gap_range": { + "additionalProperties": false, + "nullable": true, + "properties": { + "gte": { + "description": "End of the gap range.", + "type": "string" + }, + "lte": { + "description": "Start of the gap range.", + "type": "string" + } + }, + "required": [ + "lte", + "gte" + ], + "type": "object" + }, "total_alerts_created": { "description": "Total number of alerts created during last rule run.", "nullable": true, @@ -3718,6 +3756,25 @@ "nullable": true, "type": "number" }, + "gap_range": { + "additionalProperties": false, + "nullable": true, + "properties": { + "gte": { + "description": "End of the gap range.", + "type": "string" + }, + "lte": { + "description": "Start of the gap range.", + "type": "string" + } + }, + "required": [ + "lte", + "gte" + ], + "type": "object" + }, "total_alerts_created": { "description": "Total number of alerts created during last rule run.", "nullable": true, @@ -5072,6 +5129,25 @@ "nullable": true, "type": "number" }, + "gap_range": { + "additionalProperties": false, + "nullable": true, + "properties": { + "gte": { + "description": "End of the gap range.", + "type": "string" + }, + "lte": { + "description": "Start of the gap range.", + "type": "string" + } + }, + "required": [ + "lte", + "gte" + ], + "type": "object" + }, "total_alerts_created": { "description": "Total number of alerts created during last rule run.", "nullable": true, diff --git a/oas_docs/bundle.serverless.json b/oas_docs/bundle.serverless.json index 4cb2961b2ff70..8f506ce24e99e 100644 --- a/oas_docs/bundle.serverless.json +++ b/oas_docs/bundle.serverless.json @@ -1387,6 +1387,25 @@ "nullable": true, "type": "number" }, + "gap_range": { + "additionalProperties": false, + "nullable": true, + "properties": { + "gte": { + "description": "End of the gap range.", + "type": "string" + }, + "lte": { + "description": "Start of the gap range.", + "type": "string" + } + }, + "required": [ + "lte", + "gte" + ], + "type": "object" + }, "total_alerts_created": { "description": "Total number of alerts created during last rule run.", "nullable": true, @@ -2561,6 +2580,25 @@ "nullable": true, "type": "number" }, + "gap_range": { + "additionalProperties": false, + "nullable": true, + "properties": { + "gte": { + "description": "End of the gap range.", + "type": "string" + }, + "lte": { + "description": "Start of the gap range.", + "type": "string" + } + }, + "required": [ + "lte", + "gte" + ], + "type": "object" + }, "total_alerts_created": { "description": "Total number of alerts created during last rule run.", "nullable": true, @@ -3718,6 +3756,25 @@ "nullable": true, "type": "number" }, + "gap_range": { + "additionalProperties": false, + "nullable": true, + "properties": { + "gte": { + "description": "End of the gap range.", + "type": "string" + }, + "lte": { + "description": "Start of the gap range.", + "type": "string" + } + }, + "required": [ + "lte", + "gte" + ], + "type": "object" + }, "total_alerts_created": { "description": "Total number of alerts created during last rule run.", "nullable": true, @@ -5072,6 +5129,25 @@ "nullable": true, "type": "number" }, + "gap_range": { + "additionalProperties": false, + "nullable": true, + "properties": { + "gte": { + "description": "End of the gap range.", + "type": "string" + }, + "lte": { + "description": "Start of the gap range.", + "type": "string" + } + }, + "required": [ + "lte", + "gte" + ], + "type": "object" + }, "total_alerts_created": { "description": "Total number of alerts created during last rule run.", "nullable": true, diff --git a/oas_docs/output/kibana.serverless.yaml b/oas_docs/output/kibana.serverless.yaml index ba0690d06b502..80f8e51f43745 100644 --- a/oas_docs/output/kibana.serverless.yaml +++ b/oas_docs/output/kibana.serverless.yaml @@ -1159,6 +1159,20 @@ paths: description: Duration in seconds of rule run gap. nullable: true type: number + gap_range: + additionalProperties: false + nullable: true + type: object + properties: + gte: + description: End of the gap range. + type: string + lte: + description: Start of the gap range. + type: string + required: + - lte + - gte total_alerts_created: description: Total number of alerts created during last rule run. nullable: true @@ -2064,6 +2078,20 @@ paths: description: Duration in seconds of rule run gap. nullable: true type: number + gap_range: + additionalProperties: false + nullable: true + type: object + properties: + gte: + description: End of the gap range. + type: string + lte: + description: Start of the gap range. + type: string + required: + - lte + - gte total_alerts_created: description: Total number of alerts created during last rule run. nullable: true @@ -2944,6 +2972,20 @@ paths: description: Duration in seconds of rule run gap. nullable: true type: number + gap_range: + additionalProperties: false + nullable: true + type: object + properties: + gte: + description: End of the gap range. + type: string + lte: + description: Start of the gap range. + type: string + required: + - lte + - gte total_alerts_created: description: Total number of alerts created during last rule run. nullable: true @@ -3928,6 +3970,20 @@ paths: description: Duration in seconds of rule run gap. nullable: true type: number + gap_range: + additionalProperties: false + nullable: true + type: object + properties: + gte: + description: End of the gap range. + type: string + lte: + description: Start of the gap range. + type: string + required: + - lte + - gte total_alerts_created: description: Total number of alerts created during last rule run. nullable: true @@ -47175,6 +47231,19 @@ components: description: Duration in seconds of execution gap minimum: 0 type: integer + gap_range: + description: Range of the execution gap + type: object + properties: + gte: + description: Start date of the execution gap + type: string + lte: + description: End date of the execution gap + type: string + required: + - gte + - lte total_enrichment_duration_ms: description: Total time spent enriching documents during current rule execution cycle minimum: 0 diff --git a/oas_docs/output/kibana.yaml b/oas_docs/output/kibana.yaml index 8039bcd8d4397..5d0f495b3a362 100644 --- a/oas_docs/output/kibana.yaml +++ b/oas_docs/output/kibana.yaml @@ -1512,6 +1512,20 @@ paths: description: Duration in seconds of rule run gap. nullable: true type: number + gap_range: + additionalProperties: false + nullable: true + type: object + properties: + gte: + description: End of the gap range. + type: string + lte: + description: Start of the gap range. + type: string + required: + - lte + - gte total_alerts_created: description: Total number of alerts created during last rule run. nullable: true @@ -2416,6 +2430,20 @@ paths: description: Duration in seconds of rule run gap. nullable: true type: number + gap_range: + additionalProperties: false + nullable: true + type: object + properties: + gte: + description: End of the gap range. + type: string + lte: + description: Start of the gap range. + type: string + required: + - lte + - gte total_alerts_created: description: Total number of alerts created during last rule run. nullable: true @@ -3295,6 +3323,20 @@ paths: description: Duration in seconds of rule run gap. nullable: true type: number + gap_range: + additionalProperties: false + nullable: true + type: object + properties: + gte: + description: End of the gap range. + type: string + lte: + description: Start of the gap range. + type: string + required: + - lte + - gte total_alerts_created: description: Total number of alerts created during last rule run. nullable: true @@ -4271,6 +4313,20 @@ paths: description: Duration in seconds of rule run gap. nullable: true type: number + gap_range: + additionalProperties: false + nullable: true + type: object + properties: + gte: + description: End of the gap range. + type: string + lte: + description: Start of the gap range. + type: string + required: + - lte + - gte total_alerts_created: description: Total number of alerts created during last rule run. nullable: true @@ -5900,32 +5956,6 @@ paths: summary: Attach a file to a case tags: - cases - /api/cases/{caseId}/user_actions: - get: - deprecated: true - description: | - Returns all user activity for a case. Deprecated in 8.1.0. This API is deprecated and will be removed in a future release; use the find user actions API instead. You must have `read` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana feature privileges, depending on the owner of the case you're seeking. - operationId: getCaseActivityDefaultSpace - parameters: - - $ref: '#/components/parameters/Cases_case_id' - responses: - '200': - content: - application/json; Elastic-Api-Version=2023-10-31: - schema: - items: - $ref: '#/components/schemas/Cases_user_actions_response_properties' - type: array - description: Indicates a successful call. - '401': - content: - application/json; Elastic-Api-Version=2023-10-31: - schema: - $ref: '#/components/schemas/Cases_4xx_response' - description: Authorization information is missing or invalid. - summary: Get case activity - tags: - - cases /api/cases/{caseId}/user_actions/_find: get: description: | @@ -6606,37 +6636,6 @@ paths: summary: Get case creators tags: - cases - /api/cases/status: - get: - deprecated: true - description: | - Returns the number of cases that are open, closed, and in progress. Deprecated in 8.1.0. This API is deprecated and will be removed in a future release; use the find cases API instead. You must have `read` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana feature privileges, depending on the owner of the cases you're seeking. - operationId: getCaseStatusDefaultSpace - parameters: - - $ref: '#/components/parameters/Cases_owner_filter' - responses: - '200': - content: - application/json; Elastic-Api-Version=2023-10-31: - schema: - type: object - properties: - count_closed_cases: - type: integer - count_in_progress_cases: - type: integer - count_open_cases: - type: integer - description: Indicates a successful call. - '401': - content: - application/json; Elastic-Api-Version=2023-10-31: - schema: - $ref: '#/components/schemas/Cases_4xx_response' - description: Authorization information is missing or invalid. - summary: Get case status summary - tags: - - cases /api/cases/tags: get: description: | @@ -47242,23 +47241,6 @@ components: type: integer title: Unsuccessful cases API response type: object - Cases_action_types: - description: The type of action. - enum: - - assignees - - create_case - - comment - - connector - - delete_case - - description - - pushed - - tags - - title - - status - - settings - - severity - example: create_case - type: string Cases_actions: enum: - add @@ -49009,76 +48991,6 @@ components: - payload - type - version - Cases_user_actions_response_properties: - type: object - properties: - action: - $ref: '#/components/schemas/Cases_actions' - action_id: - example: 22fd3e30-03b1-11ed-920c-974bfa104448 - type: string - case_id: - example: 22df07d0-03b1-11ed-920c-974bfa104448 - type: string - comment_id: - example: 578608d0-03b1-11ed-920c-974bfa104448 - nullable: true - type: string - created_at: - example: '2022-05-13T09:16:17.416Z' - format: date-time - type: string - created_by: - type: object - properties: - email: - example: null - nullable: true - type: string - full_name: - example: null - nullable: true - type: string - profile_uid: - example: u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0 - type: string - username: - example: elastic - nullable: true - type: string - required: - - email - - full_name - - username - owner: - $ref: '#/components/schemas/Cases_owner' - payload: - oneOf: - - $ref: '#/components/schemas/Cases_payload_alert_comment' - - $ref: '#/components/schemas/Cases_payload_assignees' - - $ref: '#/components/schemas/Cases_payload_connector' - - $ref: '#/components/schemas/Cases_payload_create_case' - - $ref: '#/components/schemas/Cases_payload_delete' - - $ref: '#/components/schemas/Cases_payload_description' - - $ref: '#/components/schemas/Cases_payload_pushed' - - $ref: '#/components/schemas/Cases_payload_settings' - - $ref: '#/components/schemas/Cases_payload_severity' - - $ref: '#/components/schemas/Cases_payload_status' - - $ref: '#/components/schemas/Cases_payload_tags' - - $ref: '#/components/schemas/Cases_payload_title' - - $ref: '#/components/schemas/Cases_payload_user_comment' - type: - $ref: '#/components/schemas/Cases_action_types' - required: - - action - - action_id - - case_id - - comment_id - - created_at - - created_by - - owner - - payload - - type Cases_user_comment_response_properties: title: Case response properties for user comments type: object @@ -54020,6 +53932,19 @@ components: description: Duration in seconds of execution gap minimum: 0 type: integer + gap_range: + description: Range of the execution gap + type: object + properties: + gte: + description: Start date of the execution gap + type: string + lte: + description: End date of the execution gap + type: string + required: + - gte + - lte total_enrichment_duration_ms: description: Total time spent enriching documents during current rule execution cycle minimum: 0 diff --git a/package.json b/package.json index d13941bda9a76..3cf604b68669f 100644 --- a/package.json +++ b/package.json @@ -301,6 +301,7 @@ "@kbn/core-http-common": "link:src/core/packages/http/common", "@kbn/core-http-context-server-internal": "link:src/core/packages/http/context-server-internal", "@kbn/core-http-plugin": "link:test/plugin_functional/plugins/core_http", + "@kbn/core-http-rate-limiter-internal": "link:src/core/packages/http/rate-limiter-internal", "@kbn/core-http-request-handler-context-server": "link:src/core/packages/http/request-handler-context-server", "@kbn/core-http-request-handler-context-server-internal": "link:src/core/packages/http/request-handler-context-server-internal", "@kbn/core-http-resources-server": "link:src/core/packages/http/resources-server", @@ -492,6 +493,7 @@ "@kbn/esql-utils": "link:src/platform/packages/shared/kbn-esql-utils", "@kbn/esql-validation-autocomplete": "link:src/platform/packages/shared/kbn-esql-validation-autocomplete", "@kbn/esql-validation-example-plugin": "link:examples/esql_validation_example", + "@kbn/esql-variables-types": "link:src/platform/packages/shared/kbn-esql-variables-types", "@kbn/eui-provider-dev-warning": "link:test/plugin_functional/plugins/eui_provider_dev_warning", "@kbn/event-annotation-common": "link:src/platform/packages/shared/kbn-event-annotation-common", "@kbn/event-annotation-components": "link:src/platform/packages/shared/kbn-event-annotation-components", @@ -604,7 +606,6 @@ "@kbn/kibana-react-plugin": "link:src/platform/plugins/shared/kibana_react", "@kbn/kibana-usage-collection-plugin": "link:src/platform/plugins/private/kibana_usage_collection", "@kbn/kibana-utils-plugin": "link:src/platform/plugins/shared/kibana_utils", - "@kbn/kubernetes-security-plugin": "link:x-pack/solutions/security/plugins/kubernetes_security", "@kbn/langchain": "link:x-pack/platform/packages/shared/kbn-langchain", "@kbn/language-documentation": "link:src/platform/packages/private/kbn-language-documentation", "@kbn/lens-config-builder-example-plugin": "link:x-pack/examples/lens_config_builder_example", @@ -691,7 +692,7 @@ "@kbn/object-versioning-utils": "link:src/platform/packages/shared/kbn-object-versioning-utils", "@kbn/observability-ai-assistant-app-plugin": "link:x-pack/solutions/observability/plugins/observability_ai_assistant_app", "@kbn/observability-ai-assistant-management-plugin": "link:x-pack/solutions/observability/plugins/observability_ai_assistant_management", - "@kbn/observability-ai-assistant-plugin": "link:x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant", + "@kbn/observability-ai-assistant-plugin": "link:x-pack/platform/plugins/shared/observability_ai_assistant", "@kbn/observability-ai-common": "link:x-pack/solutions/observability/packages/observability_ai/observability_ai_common", "@kbn/observability-ai-server": "link:x-pack/solutions/observability/packages/observability_ai/observability_ai_server", "@kbn/observability-alert-details": "link:x-pack/solutions/observability/packages/alert_details", @@ -808,7 +809,7 @@ "@kbn/search-notebooks": "link:x-pack/solutions/search/plugins/search_notebooks", "@kbn/search-playground": "link:x-pack/solutions/search/plugins/search_playground", "@kbn/search-response-warnings": "link:src/platform/packages/shared/kbn-search-response-warnings", - "@kbn/search-shared-ui": "link:x-pack/solutions/search/packages/search/shared_ui", + "@kbn/search-shared-ui": "link:x-pack/solutions/search/packages/shared_ui", "@kbn/search-synonyms": "link:x-pack/solutions/search/plugins/search_synonyms", "@kbn/search-types": "link:src/platform/packages/shared/kbn-search-types", "@kbn/searchprofiler-plugin": "link:x-pack/platform/plugins/shared/searchprofiler", @@ -1065,7 +1066,7 @@ "@turf/length": "^6.0.2", "@xstate/react": "^3.2.2", "@xstate5/react": "npm:@xstate/react@^4.1.2", - "@xyflow/react": "^12.4.0", + "@xyflow/react": "^12.4.1", "adm-zip": "^0.5.9", "ai": "^4.0.18", "ajv": "^8.17.1", @@ -1080,7 +1081,7 @@ "blurhash": "^2.0.1", "borc": "3.0.0", "brok": "^6.0.0", - "byte-size": "^8.1.0", + "byte-size": "^9.0.1", "cacheable-lookup": "6", "camelcase-keys": "7.0.2", "canvg": "^3.0.9", @@ -1293,7 +1294,7 @@ "xml2js": "^0.5.0", "xstate": "^4.38.2", "xstate5": "npm:xstate@^5.18.1", - "xterm": "^5.1.0", + "xterm": "^5.3.0", "yaml": "^2.5.1", "yauzl": "^2.10.0", "yazl": "^2.5.1", @@ -1526,7 +1527,7 @@ "@kbn/whereis-pkg-cli": "link:packages/kbn-whereis-pkg-cli", "@kbn/yarn-lock-validator": "link:packages/kbn-yarn-lock-validator", "@mapbox/vector-tile": "1.3.1", - "@mswjs/http-middleware": "^0.10.1", + "@mswjs/http-middleware": "0.10.1", "@octokit/rest": "^17.11.2", "@parcel/watcher": "^2.1.0", "@playwright/test": "1.49.0", @@ -1560,7 +1561,7 @@ "@types/async": "^3.2.24", "@types/aws4": "^1.5.0", "@types/base64-js": "^1.2.5", - "@types/byte-size": "^8.1.0", + "@types/byte-size": "^8.1.2", "@types/chance": "^1.0.0", "@types/chroma-js": "^2.1.0", "@types/chromedriver": "^81.0.5", @@ -1795,7 +1796,7 @@ "mochawesome-merge": "^4.3.0", "mock-fs": "^5.1.2", "ms-chromium-edge-driver": "^0.5.1", - "msw": "^2.4.12", + "msw": "~2.5.2", "mutation-observer": "^1.0.3", "native-hdr-histogram": "^1.0.0", "nock": "12.0.3", diff --git a/packages/core/http/core-http-server-mocks/src/http_server.mocks.ts b/packages/core/http/core-http-server-mocks/src/http_server.mocks.ts index ced67ed273d8e..d1db523108667 100644 --- a/packages/core/http/core-http-server-mocks/src/http_server.mocks.ts +++ b/packages/core/http/core-http-server-mocks/src/http_server.mocks.ts @@ -10,6 +10,7 @@ import { hapiMocks } from '@kbn/hapi-mocks'; import type { LifecycleResponseFactory, + OnPreAuthToolkit, OnPreResponseToolkit, OnPostAuthToolkit, OnPreRoutingToolkit, @@ -27,7 +28,9 @@ const createLifecycleResponseFactoryMock = (): jest.Mocked; +type ToolkitMock = jest.Mocked< + OnPreAuthToolkit & OnPreResponseToolkit & OnPostAuthToolkit & OnPreRoutingToolkit +>; const createToolkitMock = (): ToolkitMock => { return { diff --git a/packages/core/http/core-http-server-mocks/src/http_service.mock.ts b/packages/core/http/core-http-server-mocks/src/http_service.mock.ts index 116db3648f120..ef137ff284559 100644 --- a/packages/core/http/core-http-server-mocks/src/http_service.mock.ts +++ b/packages/core/http/core-http-server-mocks/src/http_service.mock.ts @@ -26,7 +26,7 @@ import type { import { AuthStatus } from '@kbn/core-http-server'; import { mockRouter, RouterMock } from '@kbn/core-http-router-server-mocks'; -import { CspConfig, ExternalUrlConfig } from '@kbn/core-http-server-internal'; +import { CspConfig, ExternalUrlConfig, config } from '@kbn/core-http-server-internal'; import type { HttpService, InternalHttpServicePreboot, @@ -188,6 +188,7 @@ const createInternalSetupContractMock = () => { authRequestHeaders: createAuthHeaderStorageMock(), getServerInfo: jest.fn(), registerRouterAfterListening: jest.fn(), + rateLimiter: config.schema.getSchema().extract('rateLimiter').validate({}).value, }; mock.createCookieSessionStorageFactory.mockResolvedValue(sessionStorageMock.createFactory()); mock.createRouter.mockImplementation(() => mockRouter.create()); diff --git a/packages/core/metrics/core-metrics-server-mocks/src/metrics_service.mock.ts b/packages/core/metrics/core-metrics-server-mocks/src/metrics_service.mock.ts index 6812b8011ddd3..2097039c7847c 100644 --- a/packages/core/metrics/core-metrics-server-mocks/src/metrics_service.mock.ts +++ b/packages/core/metrics/core-metrics-server-mocks/src/metrics_service.mock.ts @@ -33,6 +33,7 @@ export const sampleEsClientMetrics: ElasticsearchClientsMetrics = { const createInternalSetupContractMock = () => { const setupContract: jest.Mocked = { collectionInterval: 30000, + getEluMetrics$: jest.fn(), getOpsMetrics$: jest.fn(), }; diff --git a/packages/kbn-es/src/serverless_resources/project_roles/security/roles.yml b/packages/kbn-es/src/serverless_resources/project_roles/security/roles.yml index 0a4bc4878023e..c15b609f1b0f2 100644 --- a/packages/kbn-es/src/serverless_resources/project_roles/security/roles.yml +++ b/packages/kbn-es/src/serverless_resources/project_roles/security/roles.yml @@ -134,6 +134,7 @@ editor: - feature_securitySolutionTimeline.all - feature_securitySolutionNotes.all - feature_actions.read + - feature_actions.endpoint_security_execute - feature_builtInAlerts.all - feature_osquery.all - feature_discover.all @@ -318,6 +319,7 @@ t3_analyst: - feature_securitySolutionTimeline.all - feature_securitySolutionNotes.all - feature_actions.read + - feature_actions.endpoint_security_execute - feature_builtInAlerts.all - feature_osquery.all - feature_discover.all @@ -529,6 +531,7 @@ soc_manager: - feature_securitySolutionTimeline.all - feature_securitySolutionNotes.all - feature_actions.all + - feature_actions.endpoint_security_execute - feature_builtInAlerts.all - feature_osquery.all - feature_indexPatterns.all @@ -729,6 +732,7 @@ endpoint_operations_analyst: - feature_securitySolutionTimeline.all - feature_securitySolutionNotes.all - feature_actions.all + - feature_actions.endpoint_security_execute - feature_builtInAlerts.all - feature_osquery.all - feature_fleet.all diff --git a/packages/kbn-optimizer/limits.yml b/packages/kbn-optimizer/limits.yml index a75d067a9bae7..7ae1d20dcff03 100644 --- a/packages/kbn-optimizer/limits.yml +++ b/packages/kbn-optimizer/limits.yml @@ -93,7 +93,6 @@ pageLoadAssetSize: kibanaReact: 74422 kibanaUsageCollection: 16463 kibanaUtils: 79713 - kubernetesSecurity: 77234 lens: 57135 licenseManagement: 41817 licensing: 29004 diff --git a/packages/kbn-relocate/utils/transforms.ts b/packages/kbn-relocate/utils/transforms.ts index 023c36171e979..5072820cf36d5 100644 --- a/packages/kbn-relocate/utils/transforms.ts +++ b/packages/kbn-relocate/utils/transforms.ts @@ -13,9 +13,9 @@ type TransformFunction = (param: string) => string; const TRANSFORMS: Record = { 'src/platform/packages/shared/chart_expressions/common': 'src/platform/packages/shared/chart-expressions-common', - 'x-pack/solutions/search/packages/search/shared_ui': 'x-pack/solutions/search/packages/shared_ui', + 'x-pack/solutions/search/packages/shared_ui': 'x-pack/solutions/search/packages/shared_ui', 'x-pack/solutions/security/packages/security-solution/': 'x-pack/solutions/security/packages/', - 'x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant': + 'x-pack/platform/plugins/shared/observability_ai_assistant': 'x-pack/platform/plugins/shared/observability_ai_assistant', 'x-pack/solutions/observability/plugins/observability_solution/': 'x-pack/solutions/observability/plugins/', diff --git a/packages/kbn-test/src/auth/saml_auth.test.ts b/packages/kbn-test/src/auth/saml_auth.test.ts index aee096bf141d6..8d5e1e631177d 100644 --- a/packages/kbn-test/src/auth/saml_auth.test.ts +++ b/packages/kbn-test/src/auth/saml_auth.test.ts @@ -230,7 +230,7 @@ describe('saml_auth', () => { }); expect(createSAMLRequest('https://kbn.test.co', '8.12.0', log)).rejects.toThrow( - `Failed to parse 'set-cookie' header` + /Failed to parse cookie from SAML response headers: no 'set-cookie' header, response.data:/ ); }); @@ -332,7 +332,9 @@ https://kbn.test.co in the same window.`); sid: 'Fe26.2**1234567890', log, }) - ).rejects.toThrow(`Failed to parse 'set-cookie' header`); + ).rejects.toThrow( + /Failed to get cookie from SAML callback response: no 'set-cookie' header, response.data:/ + ); }); }); }); diff --git a/packages/kbn-test/src/auth/saml_auth.ts b/packages/kbn-test/src/auth/saml_auth.ts index 831161fccfdbe..3c56b101e3eb1 100644 --- a/packages/kbn-test/src/auth/saml_auth.ts +++ b/packages/kbn-test/src/auth/saml_auth.ts @@ -58,7 +58,9 @@ const cleanException = (url: string, ex: any) => { const getCookieFromResponseHeaders = (response: AxiosResponse, errorMessage: string) => { const setCookieHeader = response?.headers['set-cookie']; if (!setCookieHeader) { - throw new Error(`Failed to parse 'set-cookie' header`); + throw new Error( + `${errorMessage}: no 'set-cookie' header, response.data: ${JSON.stringify(response?.data)}` + ); } const cookie = parseCookie(setCookieHeader![0]); @@ -289,7 +291,7 @@ export const finishSAMLHandshake = async ({ return getCookieFromResponseHeaders( authResponse, - 'Failed to get cookie from SAML callback response headers' + 'Failed to get cookie from SAML callback response' ); }; diff --git a/src/cli/profiler/profiler.js b/src/cli/profiler/profiler.js index ee06c0a377568..7c6b5e5b408db 100644 --- a/src/cli/profiler/profiler.js +++ b/src/cli/profiler/profiler.js @@ -13,16 +13,19 @@ import { join } from 'path'; import { Session } from 'node:inspector'; import { threadId } from 'node:worker_threads'; import { promisify } from 'util'; +import { Logger } from '../logger'; class Profiler { #counter = 0; + #logger; #path; #session; - constructor() { + constructor(logger) { const execOpts = getopts(process.execArgv); const envOpts = getopts(process.env.NODE_OPTIONS ? process.env.NODE_OPTIONS.split(/\s+/) : []); this.#path = execOpts['diagnostic-dir'] || envOpts['diagnostic-dir'] || process.cwd(); + this.#logger = logger; } #getPath() { @@ -51,13 +54,17 @@ class Profiler { await promisify(this.#session.post)('Profiler.enable'); await promisify(this.#session.post)('Profiler.start'); + this.#logger.log(`CPU profiling is started for process '${process.pid}'.`); } async #stop() { try { const { profile } = await promisify(this.#session.post)('Profiler.stop'); + this.#logger.log(`CPU profiling is stopped for process '${process.pid}'.`); + const path = this.#getPath(); await promisify(writeFile)(path, JSON.stringify(profile)); + this.#logger.log(`Saved CPU profile to '${path}'.`); } finally { this.#session.disconnect(); this.#session = undefined; @@ -81,8 +88,10 @@ export default function (program) { return; } - const profiler = new Profiler(); + const logger = new Logger(); + const profiler = new Profiler(logger); process.removeAllListeners(signal); process.on(signal, profiler.toggle.bind(profiler)); + logger.log(`CPU profiling is enabled on '${signal}' for process '${process.pid}'.`); }); } diff --git a/src/core/packages/http/rate-limiter-internal/README.md b/src/core/packages/http/rate-limiter-internal/README.md new file mode 100644 index 0000000000000..dee45a5f34596 --- /dev/null +++ b/src/core/packages/http/rate-limiter-internal/README.md @@ -0,0 +1,3 @@ +# @kbn/core-http-rate-limiter-internal + +This package contains the rate limiter implementation for Core's internal `http` resources service. diff --git a/src/core/packages/http/rate-limiter-internal/index.ts b/src/core/packages/http/rate-limiter-internal/index.ts new file mode 100644 index 0000000000000..a3b8b70028896 --- /dev/null +++ b/src/core/packages/http/rate-limiter-internal/index.ts @@ -0,0 +1,15 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +export { + HttpRateLimiterService, + type SetupDeps, + type InternalRateLimiterSetup, + type InternalRateLimiterStart, +} from './src/service'; diff --git a/src/core/packages/http/rate-limiter-internal/jest.config.js b/src/core/packages/http/rate-limiter-internal/jest.config.js new file mode 100644 index 0000000000000..7803a0cbadb1f --- /dev/null +++ b/src/core/packages/http/rate-limiter-internal/jest.config.js @@ -0,0 +1,14 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +module.exports = { + preset: '@kbn/test/jest_node', + rootDir: '../../../../..', + roots: ['/src/core/packages/http/rate-limiter-internal'], +}; diff --git a/src/core/packages/http/rate-limiter-internal/kibana.jsonc b/src/core/packages/http/rate-limiter-internal/kibana.jsonc new file mode 100644 index 0000000000000..5088a38c698aa --- /dev/null +++ b/src/core/packages/http/rate-limiter-internal/kibana.jsonc @@ -0,0 +1,9 @@ +{ + "type": "shared-server", + "id": "@kbn/core-http-rate-limiter-internal", + "owner": [ + "@elastic/kibana-core" + ], + "group": "platform", + "visibility": "private" +} diff --git a/src/core/packages/http/rate-limiter-internal/package.json b/src/core/packages/http/rate-limiter-internal/package.json new file mode 100644 index 0000000000000..465c01ef8eca7 --- /dev/null +++ b/src/core/packages/http/rate-limiter-internal/package.json @@ -0,0 +1,7 @@ +{ + "name": "@kbn/core-http-rate-limiter-internal", + "private": true, + "version": "1.0.0", + "author": "Kibana Core", + "license": "Elastic License 2.0 OR AGPL-3.0-only OR SSPL-1.0" +} \ No newline at end of file diff --git a/src/core/packages/http/rate-limiter-internal/src/service.test.ts b/src/core/packages/http/rate-limiter-internal/src/service.test.ts new file mode 100644 index 0000000000000..05d46febeb80b --- /dev/null +++ b/src/core/packages/http/rate-limiter-internal/src/service.test.ts @@ -0,0 +1,138 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import { Subject } from 'rxjs'; +import type { OnPreAuthHandler } from '@kbn/core-http-server'; +import { + httpServerMock, + httpServiceMock, + type InternalHttpServiceSetupMock, +} from '@kbn/core-http-server-mocks'; +import { metricsServiceMock } from '@kbn/core-metrics-server-mocks'; +import type { UnwrapObservable } from '@kbn/utility-types'; +import { HttpRateLimiterService } from './service'; + +describe('HttpRateLimiterService', () => { + let service: HttpRateLimiterService; + let http: InternalHttpServiceSetupMock; + let metrics: ReturnType; + let config: typeof http.rateLimiter extends Readonly ? T : never; + let elu$: Subject>>; + + beforeEach(() => { + config = {} as typeof config; + elu$ = new Subject(); + service = new HttpRateLimiterService(); + http = httpServiceMock.createInternalSetupContract(); + metrics = metricsServiceMock.createInternalSetupContract(); + + http.rateLimiter = config as typeof http.rateLimiter; + metrics.getEluMetrics$.mockReturnValue(elu$); + }); + + describe('setup', () => { + describe('when disabled', () => { + it('should not register a handler', () => { + config.enabled = false; + service.setup({ http, metrics }); + + expect(http.registerOnPreAuth).not.toHaveBeenCalled(); + }); + }); + + describe('when enabled', () => { + let handler: OnPreAuthHandler; + let request: ReturnType; + let response: ReturnType; + let toolkit: ReturnType; + const ignored = 'ignored' as unknown as ReturnType; + const throttled = 'throttled' as unknown as ReturnType; + + beforeEach(() => { + config.enabled = true; + config.elu = 0.5; + config.term = 'short'; + request = httpServerMock.createKibanaRequest(); + response = httpServerMock.createResponseFactory(); + toolkit = httpServerMock.createToolkit(); + + toolkit.next.mockReturnValue(ignored); + response.customError.mockReturnValue(throttled); + + service.setup({ http, metrics }); + [handler] = http.registerOnPreAuth.mock.lastCall!; + }); + + it('should register a handler if the rate limiter is enabled', () => { + expect(http.registerOnPreAuth).toHaveBeenCalledWith(expect.any(Function)); + }); + + it('should not throttle until started', () => { + elu$.next({ short: 0.9, medium: 0.9, long: 0.9 }); + expect(handler(request, response, toolkit)).toBe(ignored); + }); + + it('should throttle when started', () => { + service.start(); + elu$.next({ short: 0.9, medium: 0.9, long: 0.9 }); + expect(handler(request, response, toolkit)).toBe(throttled); + }); + + it('should not throttle when stopped', () => { + service.start(); + service.stop(); + elu$.next({ short: 0.9, medium: 0.9, long: 0.9 }); + expect(handler(request, response, toolkit)).toBe(ignored); + }); + + it('should not throttle excluded routes', () => { + service.start(); + elu$.next({ short: 0.9, medium: 0.9, long: 0.9 }); + expect( + handler( + httpServerMock.createKibanaRequest({ + kibanaRouteOptions: { + access: 'internal', + excludeFromRateLimiter: true, + xsrfRequired: true, + }, + }), + response, + toolkit + ) + ).toBe(ignored); + }); + + it.each` + threshold | term | short | medium | long | expected + ${0.6} | ${'short'} | ${0.5} | ${0.5} | ${0.5} | ${ignored} + ${0.4} | ${'short'} | ${0.5} | ${0.5} | ${0.5} | ${throttled} + ${0.6} | ${'medium'} | ${0.4} | ${0.5} | ${0.6} | ${ignored} + ${0.5} | ${'medium'} | ${0.4} | ${0.5} | ${0.6} | ${ignored} + ${0.4} | ${'medium'} | ${0.4} | ${0.5} | ${0.6} | ${throttled} + ${0.7} | ${'long'} | ${0.4} | ${0.5} | ${0.6} | ${ignored} + ${0.6} | ${'long'} | ${0.4} | ${0.5} | ${0.6} | ${ignored} + ${0.5} | ${'long'} | ${0.4} | ${0.5} | ${0.6} | ${ignored} + ${0.4} | ${'long'} | ${0.4} | ${0.5} | ${0.6} | ${throttled} + `( + 'should be $expected when the threshold is $threshold for the $term-term', + ({ threshold, term, short, medium, long, expected }) => { + config.elu = threshold; + config.term = term; + service.setup({ http, metrics }); + [handler] = http.registerOnPreAuth.mock.lastCall!; + + service.start(); + elu$.next({ short, medium, long }); + expect(handler(request, response, toolkit)).toBe(expected); + } + ); + }); + }); +}); diff --git a/src/core/packages/http/rate-limiter-internal/src/service.ts b/src/core/packages/http/rate-limiter-internal/src/service.ts new file mode 100644 index 0000000000000..b4df6c6351bd3 --- /dev/null +++ b/src/core/packages/http/rate-limiter-internal/src/service.ts @@ -0,0 +1,95 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import { + BehaviorSubject, + endWith, + map, + skipUntil, + type Observable, + Subject, + takeUntil, +} from 'rxjs'; +import type { CoreService } from '@kbn/core-base-server-internal'; +import type { KibanaRequest, OnPreAuthHandler } from '@kbn/core-http-server'; +import type { InternalHttpServiceSetup } from '@kbn/core-http-server-internal'; +import type { EluMetrics } from '@kbn/core-metrics-server'; +import type { InternalMetricsServiceSetup } from '@kbn/core-metrics-server-internal'; + +/** @internal */ +export interface SetupDeps { + http: InternalHttpServiceSetup; + metrics: InternalMetricsServiceSetup; +} + +/** @internal */ +export type InternalRateLimiterSetup = void; + +/** @internal */ +export type InternalRateLimiterStart = void; + +/** @internal */ +export class HttpRateLimiterService + implements CoreService +{ + private overloaded$ = new BehaviorSubject(false); + private ready$ = new Subject(); + private stopped$ = new Subject(); + + private handler: OnPreAuthHandler = (request, response, toolkit) => { + if (!this.shouldBeThrottled(request)) { + return toolkit.next(); + } + + return response.customError({ + statusCode: 429, + body: 'Server is overloaded', + }); + }; + + private shouldBeThrottled(request: KibanaRequest): boolean { + return !request.route.options.excludeFromRateLimiter && this.overloaded$.getValue(); + } + + private watch( + metrics$: Observable, + { elu, term }: InternalHttpServiceSetup['rateLimiter'] + ) { + metrics$ + .pipe( + skipUntil(this.ready$), + takeUntil(this.stopped$), + map( + ({ short, medium, long }) => + short >= elu && (term === 'short' || medium >= elu) && (term !== 'long' || long >= elu) + ), + endWith(false) + ) + .subscribe(this.overloaded$); + } + + public setup({ http, metrics }: SetupDeps): InternalRateLimiterSetup { + if (!http.rateLimiter.enabled) { + return; + } + + this.watch(metrics.getEluMetrics$(), http.rateLimiter); + http.registerOnPreAuth(this.handler); + } + + public start(): InternalRateLimiterStart { + this.ready$.next(true); + this.ready$.complete(); + } + + public stop(): void { + this.stopped$.next(true); + this.stopped$.complete(); + } +} diff --git a/src/core/packages/http/rate-limiter-internal/tsconfig.json b/src/core/packages/http/rate-limiter-internal/tsconfig.json new file mode 100644 index 0000000000000..42e57e4b80316 --- /dev/null +++ b/src/core/packages/http/rate-limiter-internal/tsconfig.json @@ -0,0 +1,26 @@ +{ + "extends": "../../../../../tsconfig.base.json", + "compilerOptions": { + "outDir": "target/types", + "types": [ + "jest", + "node" + ] + }, + "include": [ + "**/*.ts", + ], + "kbn_references": [ + "@kbn/core-http-server-internal", + "@kbn/core-http-server", + "@kbn/core-http-server-mocks", + "@kbn/core-metrics-server-mocks", + "@kbn/utility-types", + "@kbn/core-base-server-internal", + "@kbn/core-metrics-server", + "@kbn/core-metrics-server-internal", + ], + "exclude": [ + "target/**/*", + ] +} diff --git a/src/core/packages/http/router-server-internal/src/request.test.ts b/src/core/packages/http/router-server-internal/src/request.test.ts index 10ab084e53535..4b1ad9f02267a 100644 --- a/src/core/packages/http/router-server-internal/src/request.test.ts +++ b/src/core/packages/http/router-server-internal/src/request.test.ts @@ -470,6 +470,28 @@ describe('CoreKibanaRequest', () => { }); }); + describe('route.options.excludeFromRateLimiter property', () => { + it.each` + value | expected + ${true} | ${true} + ${false} | ${false} + ${undefined} | ${undefined} + `('handles excludeFromRateLimiter: ${value}', ({ value, expected }) => { + const request = hapiMocks.createRequest({ + route: { + settings: { + app: { + excludeFromRateLimiter: value, + }, + }, + }, + }); + const kibanaRequest = CoreKibanaRequest.from(request); + + expect(kibanaRequest.route.options.excludeFromRateLimiter).toBe(expected); + }); + }); + describe('RouteSchema type inferring', () => { it('should work with config-schema', () => { const body = Buffer.from('body!'); diff --git a/src/core/packages/http/router-server-internal/src/request.ts b/src/core/packages/http/router-server-internal/src/request.ts index 1eaae21c13259..4153eb8ec378c 100644 --- a/src/core/packages/http/router-server-internal/src/request.ts +++ b/src/core/packages/http/router-server-internal/src/request.ts @@ -13,6 +13,7 @@ import { inspect } from 'util'; import type { Request, RouteOptions } from '@hapi/hapi'; import { fromEvent, NEVER } from 'rxjs'; import { shareReplay, first, filter } from 'rxjs'; +import { isNil, omitBy } from 'lodash'; import { RecursiveReadonly } from '@kbn/utility-types'; import { deepFreeze } from '@kbn/std'; import { @@ -270,6 +271,7 @@ export class CoreKibanaRequest< } const options = { + ...omitBy({ excludeFromRateLimiter: this.isExcludedFromRateLimiter(request) }, isNil), authRequired: this.getAuthRequired(request), // TypeScript note: Casting to `RouterOptions` to fix the following error: // @@ -354,6 +356,11 @@ export class CoreKibanaRequest< }${this.url.search}` ); } + + private isExcludedFromRateLimiter(request: RawRequest): boolean | undefined { + return ((request.route?.settings as RouteOptions)?.app as KibanaRouteOptions) + ?.excludeFromRateLimiter; + } } /** diff --git a/src/core/packages/http/server-internal/src/__snapshots__/http_config.test.ts.snap b/src/core/packages/http/server-internal/src/__snapshots__/http_config.test.ts.snap index 71aedb914b72d..85a8a63cbcfb5 100644 --- a/src/core/packages/http/server-internal/src/__snapshots__/http_config.test.ts.snap +++ b/src/core/packages/http/server-internal/src/__snapshots__/http_config.test.ts.snap @@ -84,6 +84,9 @@ Object { "payloadTimeout": 20000, "port": 5601, "protocol": "http1", + "rateLimiter": Object { + "enabled": false, + }, "requestId": Object { "allowFromAnyIp": false, "ipAllowlist": Array [], diff --git a/src/core/packages/http/server-internal/src/http_config.ts b/src/core/packages/http/server-internal/src/http_config.ts index 6503bd2c87dde..c6b344fac8cdf 100644 --- a/src/core/packages/http/server-internal/src/http_config.ts +++ b/src/core/packages/http/server-internal/src/http_config.ts @@ -26,6 +26,7 @@ import { } from './security_response_headers_config'; import { CdnConfig } from './cdn_config'; import { PermissionsPolicyConfigType } from './permissions_policy'; +import { type RateLimiterConfig, rateLimiterConfigSchema } from './rate_limiter'; const SECOND = 1000; @@ -200,6 +201,7 @@ const configSchema = schema.object( }), }), }), + rateLimiter: rateLimiterConfigSchema, requestId: schema.object( { allowFromAnyIp: schema.boolean({ defaultValue: false }), @@ -362,6 +364,7 @@ export class HttpConfig implements IHttpConfig { }; public shutdownTimeout: Duration; public restrictInternalApis: boolean; + public rateLimiter: RateLimiterConfig; public eluMonitor: IHttpEluMonitorConfig; @@ -409,6 +412,7 @@ export class HttpConfig implements IHttpConfig { this.xsrf = rawHttpConfig.xsrf; this.requestId = rawHttpConfig.requestId; this.shutdownTimeout = rawHttpConfig.shutdownTimeout; + this.rateLimiter = rawHttpConfig.rateLimiter; // defaults to `true` if not set through config. this.restrictInternalApis = rawHttpConfig.restrictInternalApis; diff --git a/src/core/packages/http/server-internal/src/http_server.ts b/src/core/packages/http/server-internal/src/http_server.ts index 3e2e986ed259c..1c7b57fde6e2b 100644 --- a/src/core/packages/http/server-internal/src/http_server.ts +++ b/src/core/packages/http/server-internal/src/http_server.ts @@ -41,7 +41,7 @@ import type { } from '@kbn/core-http-server'; import { performance } from 'perf_hooks'; import { isBoom } from '@hapi/boom'; -import { identity, isObject } from 'lodash'; +import { identity, isNil, isObject, omitBy } from 'lodash'; import { IHttpEluMonitorConfig } from '@kbn/core-http-server/src/elu_monitor'; import { Env } from '@kbn/config'; import { CoreContext } from '@kbn/core-base-server-internal'; @@ -767,6 +767,7 @@ export class HttpServer { access: route.options.access ?? 'internal', deprecated, security: route.security, + ...omitBy({ excludeFromRateLimiter: route.options.excludeFromRateLimiter }, isNil), }; // Log HTTP API target consumer. optionsLogger.debug( diff --git a/src/core/packages/http/server-internal/src/http_service.ts b/src/core/packages/http/server-internal/src/http_service.ts index 5d43a7a203882..5392b61d8bc1f 100644 --- a/src/core/packages/http/server-internal/src/http_service.ts +++ b/src/core/packages/http/server-internal/src/http_service.ts @@ -185,6 +185,7 @@ export class HttpService this.internalSetup = { ...serverContract, + rateLimiter: config.rateLimiter, registerOnPostValidation: (cb) => { Router.on('onPostValidate', cb); }, diff --git a/src/core/packages/http/server-internal/src/rate_limiter/config.ts b/src/core/packages/http/server-internal/src/rate_limiter/config.ts new file mode 100644 index 0000000000000..88b42e7c921f0 --- /dev/null +++ b/src/core/packages/http/server-internal/src/rate_limiter/config.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", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import { schema, type TypeOf } from '@kbn/config-schema'; + +export const rateLimiterConfigSchema = schema.object({ + enabled: schema.boolean({ defaultValue: false }), + elu: schema.conditional( + schema.siblingRef('enabled'), + false, + schema.never(), + schema.number({ min: 0, max: 1 }) + ), + term: schema.conditional( + schema.siblingRef('enabled'), + false, + schema.never(), + schema.oneOf([schema.literal('short'), schema.literal('medium'), schema.literal('long')], { + defaultValue: 'long', + }) + ), +}); + +export type RateLimiterConfig = TypeOf; diff --git a/src/core/packages/http/server-internal/src/rate_limiter/index.ts b/src/core/packages/http/server-internal/src/rate_limiter/index.ts new file mode 100644 index 0000000000000..4747b2e2a1646 --- /dev/null +++ b/src/core/packages/http/server-internal/src/rate_limiter/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", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +export { type RateLimiterConfig, rateLimiterConfigSchema } from './config'; diff --git a/src/core/packages/http/server-internal/src/types.ts b/src/core/packages/http/server-internal/src/types.ts index c0443e5bc049c..0b6e6ad903b23 100644 --- a/src/core/packages/http/server-internal/src/types.ts +++ b/src/core/packages/http/server-internal/src/types.ts @@ -23,6 +23,7 @@ import type { PostValidationMetadata } from '@kbn/core-http-server'; import type { HttpServerSetup } from './http_server'; import type { ExternalUrlConfig } from './external_url'; import type { InternalStaticAssets } from './static_assets'; +import type { RateLimiterConfig } from './rate_limiter'; /** @internal */ export interface InternalHttpServicePreboot @@ -57,6 +58,7 @@ export interface InternalHttpServiceSetup path: string, plugin?: PluginOpaqueId ) => IRouter; + rateLimiter: RateLimiterConfig; registerOnPostValidation( cb: (req: CoreKibanaRequest, metadata: PostValidationMetadata) => void ): void; diff --git a/src/core/packages/http/server/src/router/request.ts b/src/core/packages/http/server/src/router/request.ts index 5019cce51c80d..0283865674414 100644 --- a/src/core/packages/http/server/src/router/request.ts +++ b/src/core/packages/http/server/src/router/request.ts @@ -30,6 +30,7 @@ export interface KibanaRouteOptions extends RouteOptionsApp { xsrfRequired: boolean; access: 'internal' | 'public'; security?: InternalRouteSecurity; + excludeFromRateLimiter?: boolean; } /** diff --git a/src/core/packages/http/server/src/router/route.ts b/src/core/packages/http/server/src/router/route.ts index adce8aae39e39..9e6a8f094a9e5 100644 --- a/src/core/packages/http/server/src/router/route.ts +++ b/src/core/packages/http/server/src/router/route.ts @@ -395,6 +395,13 @@ export interface RouteConfigOptions { */ excludeFromOAS?: boolean; + /** + * Whether the rate limiter should never throttle this route. + * + * @default false + */ + excludeFromRateLimiter?: boolean; + /** * Release version or date that this route will be removed * Use with `deprecated: true` diff --git a/src/core/packages/metrics/server-internal/src/exponential_moving_average.test.ts b/src/core/packages/metrics/server-internal/src/exponential_moving_average.test.ts new file mode 100644 index 0000000000000..7196cd752aa6c --- /dev/null +++ b/src/core/packages/metrics/server-internal/src/exponential_moving_average.test.ts @@ -0,0 +1,63 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import { TestScheduler } from 'rxjs/testing'; +import { exponentialMovingAverage } from './exponential_moving_average'; + +describe('exponentialMovingAverage', () => { + let testScheduler: TestScheduler; + + beforeEach(() => { + testScheduler = new TestScheduler((actual, expected) => { + return expect(actual).toStrictEqual(expected); + }); + }); + + it('should emit the initial value', () => { + testScheduler.run(({ cold, expectObservable }) => { + const observable = cold('a|', { a: 1 }).pipe(exponentialMovingAverage(15, 5)); + + expectObservable(observable).toBe('a|', { a: 1 }); + }); + }); + + it('should emit smoothed values', () => { + testScheduler.run(({ cold, expectObservable }) => { + const observable = cold('abc|', { a: 1, b: 1, c: 2 }).pipe(exponentialMovingAverage(15, 5)); + + expectObservable(observable).toBe('abc|', { + a: 1, + b: 1, + c: expect.closeTo(1.3, 1), + }); + }); + }); + + it('should fade away outdated values', () => { + testScheduler.run(({ cold, expectObservable }) => { + const observable = cold('abcdef|', { + a: 1, + b: 1, + c: 2, + d: 2, + e: 1, + f: 1, + }).pipe(exponentialMovingAverage(15, 5)); + + expectObservable(observable).toBe('abcdef|', { + a: 1, // https://en.wikipedia.org/wiki/Exponential_smoothing#Choosing_the_initial_smoothed_value + b: 1, + c: expect.closeTo(1.3, 1), + d: expect.closeTo(1.5, 1), + e: expect.closeTo(1.3, 1), + f: expect.closeTo(1.2, 1), + }); + }); + }); +}); diff --git a/src/core/packages/metrics/server-internal/src/exponential_moving_average.ts b/src/core/packages/metrics/server-internal/src/exponential_moving_average.ts new file mode 100644 index 0000000000000..4f103df5897f6 --- /dev/null +++ b/src/core/packages/metrics/server-internal/src/exponential_moving_average.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", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import { type OperatorFunction, map, tap } from 'rxjs'; + +/** + * An RxJS operator implementing the exponential moving average function. + * + * @see https://en.wikipedia.org/wiki/Exponential_smoothing + * @param period The period of time. + * @param interval The interval between values. + * @returns An operator emitting smoothed values. + */ +export function exponentialMovingAverage( + period: number, + interval: number +): OperatorFunction { + const alpha = 1 - Math.exp(-interval / period); + + return (inner) => { + let previous: number | undefined; + + return inner.pipe( + map((current) => (previous == null ? current : alpha * current + (1 - alpha) * previous)), + tap((current) => { + previous = current; + }) + ); + }; +} diff --git a/src/core/packages/metrics/server-internal/src/metrics_service.test.ts b/src/core/packages/metrics/server-internal/src/metrics_service.test.ts index 4afae68d96d2b..995bb46e507c4 100644 --- a/src/core/packages/metrics/server-internal/src/metrics_service.test.ts +++ b/src/core/packages/metrics/server-internal/src/metrics_service.test.ts @@ -9,7 +9,8 @@ import moment from 'moment'; import { merge } from 'lodash'; -import { take } from 'rxjs'; +import { set } from '@kbn/safer-lodash-set'; +import { lastValueFrom, take, toArray } from 'rxjs'; import { configServiceMock } from '@kbn/config-mocks'; import { mockCoreContext } from '@kbn/core-base-server-mocks'; import { loggingSystemMock } from '@kbn/core-logging-server-mocks'; @@ -189,6 +190,39 @@ describe('MetricsService', () => { expect(opsLogs[0][1]).not.toEqual(opsLogs[1][1]); }); + it('emits average ELU values on getEluMetrics$ call', async () => { + mockOpsCollector.collect + .mockImplementationOnce(() => set({}, 'process.event_loop_utilization.utilization', 0.1)) + .mockResolvedValueOnce(set({}, 'process.event_loop_utilization.utilization', 0.9)) + .mockResolvedValueOnce(set({}, 'process.event_loop_utilization.utilization', 0.9)); + + await metricsService.setup({ http: httpMock, elasticsearchService: esServiceMock }); + const { getEluMetrics$ } = await metricsService.start(); + const eluMetricsPromise = lastValueFrom(getEluMetrics$().pipe(toArray())); + + jest.advanceTimersByTime(testInterval * 2); + await new Promise((resolve) => process.nextTick(resolve)); + await metricsService.stop(); + + await expect(eluMetricsPromise).resolves.toEqual([ + expect.objectContaining({ + short: expect.closeTo(0.1), + medium: expect.closeTo(0.1), + long: expect.closeTo(0.1), + }), + expect.objectContaining({ + short: expect.closeTo(0.11), + medium: expect.closeTo(0.1), + long: expect.closeTo(0.1), + }), + expect.objectContaining({ + short: expect.closeTo(0.11), + medium: expect.closeTo(0.11), + long: expect.closeTo(0.1), + }), + ]); + }); + it('omits metrics from log message if they are missing or malformed', async () => { const opsLogger = logger.get('metrics', 'ops'); mockOpsCollector.collect.mockResolvedValueOnce( diff --git a/src/core/packages/metrics/server-internal/src/metrics_service.ts b/src/core/packages/metrics/server-internal/src/metrics_service.ts index 5f56051ab9303..efe2d724f9536 100644 --- a/src/core/packages/metrics/server-internal/src/metrics_service.ts +++ b/src/core/packages/metrics/server-internal/src/metrics_service.ts @@ -7,12 +7,13 @@ * License v3.0 only", or the "Server Side Public License, v 1". */ -import { firstValueFrom, ReplaySubject } from 'rxjs'; +import { BehaviorSubject, firstValueFrom, map, ReplaySubject, zip } from 'rxjs'; import type { CoreContext, CoreService } from '@kbn/core-base-server-internal'; import type { Logger } from '@kbn/logging'; import type { InternalHttpServiceSetup } from '@kbn/core-http-server-internal'; import type { InternalElasticsearchServiceSetup } from '@kbn/core-elasticsearch-server-internal'; import type { + EluMetrics, OpsMetrics, MetricsServiceSetup, MetricsServiceStart, @@ -21,6 +22,11 @@ import { OpsMetricsCollector } from './ops_metrics_collector'; import { OPS_CONFIG_PATH, type OpsConfigType } from './ops_config'; import { getEcsOpsMetricsLog } from './logging'; import { registerEluHistoryRoute } from './routes/elu_history'; +import { exponentialMovingAverage } from './exponential_moving_average'; + +const ELU_SHORT = 15000; +const ELU_MEDIUM = 30000; +const ELU_LONG = 60000; export interface MetricsServiceSetupDeps { http: InternalHttpServiceSetup; @@ -42,6 +48,11 @@ export class MetricsService private metricsCollector?: OpsMetricsCollector; private collectInterval?: NodeJS.Timeout; private metrics$ = new ReplaySubject(1); + private elu$ = new BehaviorSubject({ + long: 0, + medium: 0, + short: 0, + }); private service?: InternalMetricsServiceSetup; constructor(private readonly coreContext: CoreContext) { @@ -56,6 +67,7 @@ export class MetricsService const config = await firstValueFrom( this.coreContext.configService.atPath(OPS_CONFIG_PATH) ); + const collectionInterval = config.interval.asMilliseconds(); this.metricsCollector = new OpsMetricsCollector( http.server, @@ -70,15 +82,25 @@ export class MetricsService this.collectInterval = setInterval(() => { this.refreshMetrics(); - }, config.interval.asMilliseconds()); - - const metricsObservable = this.metrics$.asObservable(); - - registerEluHistoryRoute(http.createRouter(''), metricsObservable); + }, collectionInterval); + + this.metrics$ + .pipe( + map((metrics) => metrics.process.event_loop_utilization.utilization), + (elu$) => + zip( + elu$.pipe(exponentialMovingAverage(ELU_SHORT, collectionInterval)), + elu$.pipe(exponentialMovingAverage(ELU_MEDIUM, collectionInterval)), + elu$.pipe(exponentialMovingAverage(ELU_LONG, collectionInterval)) + ).pipe(map(([short, medium, long]) => ({ short, medium, long }))) + ) + .subscribe(this.elu$); + registerEluHistoryRoute(http.createRouter(''), () => this.elu$.value); this.service = { - collectionInterval: config.interval.asMilliseconds(), - getOpsMetrics$: () => metricsObservable, + collectionInterval, + getOpsMetrics$: () => this.metrics$, + getEluMetrics$: () => this.elu$, }; return this.service; diff --git a/src/core/packages/metrics/server-internal/src/routes/elu_history.ts b/src/core/packages/metrics/server-internal/src/routes/elu_history.ts index 8bd44614ae369..b8153ae74d252 100644 --- a/src/core/packages/metrics/server-internal/src/routes/elu_history.ts +++ b/src/core/packages/metrics/server-internal/src/routes/elu_history.ts @@ -8,10 +8,8 @@ */ import type { IRouter } from '@kbn/core-http-server'; -import type { OpsMetrics } from '@kbn/core-metrics-server'; -import type { Observable } from 'rxjs'; import apm from 'elastic-apm-node'; -import { HistoryWindow } from './history_window'; +import { EluMetrics } from '@kbn/core-metrics-server'; interface ELUHistoryResponse { /** @@ -20,40 +18,17 @@ interface ELUHistoryResponse { * actual time range covered is determined by our collection interval (configured via `ops.interval`, default 5s) * and the number of samples held in each window. So by default short: 15s, medium: 30s and long 60s. */ - history: { - /** The history for the short window */ - short: number; - /** The history for the medium window */ - medium: number; - /** The history for the long window */ - long: number; - }; + history: EluMetrics; } -const HISTORY_WINDOW_SIZE_SHORT = 3; -const HISTORY_WINDOW_SIZE_MED = 6; -const HISTORY_WINDOW_SIZE_LONG = 12; - /** * Intended for exposing metrics over HTTP that we do not want to include in the /api/stats endpoint, yet. */ -export function registerEluHistoryRoute(router: IRouter, metrics$: Observable) { - const eluHistoryWindow = new HistoryWindow(HISTORY_WINDOW_SIZE_LONG); - - metrics$.subscribe((metrics) => { - eluHistoryWindow.addObservation(metrics.process.event_loop_utilization.utilization); - }); - +export function registerEluHistoryRoute(router: IRouter, elu: () => EluMetrics) { // Report the same metrics to APM - apm.registerMetric('elu.history.short', () => - eluHistoryWindow.getAverage(HISTORY_WINDOW_SIZE_SHORT) - ); - apm.registerMetric('elu.history.medium', () => - eluHistoryWindow.getAverage(HISTORY_WINDOW_SIZE_MED) - ); - apm.registerMetric('elu.history.long', () => - eluHistoryWindow.getAverage(HISTORY_WINDOW_SIZE_LONG) - ); + apm.registerMetric('elu.history.short', () => elu().short); + apm.registerMetric('elu.history.medium', () => elu().medium); + apm.registerMetric('elu.history.long', () => elu().long); router.versioned .get({ @@ -62,6 +37,7 @@ export function registerEluHistoryRoute(router: IRouter, metrics$: Observable { const body: ELUHistoryResponse = { - history: { - short: eluHistoryWindow.getAverage(HISTORY_WINDOW_SIZE_SHORT), - medium: eluHistoryWindow.getAverage(HISTORY_WINDOW_SIZE_MED), - long: eluHistoryWindow.getAverage(HISTORY_WINDOW_SIZE_LONG), - }, + history: elu(), }; return res.ok({ body }); } diff --git a/src/core/packages/metrics/server-internal/src/routes/history_window.test.ts b/src/core/packages/metrics/server-internal/src/routes/history_window.test.ts deleted file mode 100644 index 72928cc2c3904..0000000000000 --- a/src/core/packages/metrics/server-internal/src/routes/history_window.test.ts +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the "Elastic License - * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import { HistoryWindow } from './history_window'; - -describe('HistoryWindow', () => { - it('#getAverage should work without any observations', () => { - const hw = new HistoryWindow(3); - expect(hw.getAverage(1)).toBe(0); - }); - - it('Window size remains constant', () => { - const hw = new HistoryWindow(7); - for (let i = 0; i < 100; i++) { - hw.addObservation(i); - expect(hw.size).toBe(7); - } - }); - it.each([ - [-1000], - [-1], - [0], - [9999], - // [NaN] assuming this is nonsense input - ])('#getAverage works given bad input: %s', (badInput) => { - const hw = new HistoryWindow(3); - expect(hw.getAverage(badInput)).toBe(0); - }); - - const WINDOW_SIZE = 3; - it.each([ - { name: 'base case', observations: [0.44, 0.55, 0.66], averageLast: 3, expected: 0.55 }, - { - name: 'reverse base case', - observations: [0.44, 0.55, 0.66].reverse(), - averageLast: 3, - expected: 0.55, - }, // should be same as above - { - name: 'include one observation', - observations: [0.44, 0.55, 0.66], - averageLast: 1, - expected: 0.44, - }, - { - name: 'include excess observations', - observations: [0.201, 0.33, 0.44], - averageLast: 4, - expected: 0.33, - }, - { - name: 'subset of observations', - observations: [0.44, 0.55, 0.66], - averageLast: 2, - expected: 0.5, - }, - { - name: 'includes at least one observation', - observations: [0.44, 0.55, 0.66], - averageLast: -1, - expected: 0.44, - }, - { - name: 'excess observations', - observations: [1, 0.99, 0.55, 0.66, 0.44, 0.55, 0.66, 0.77], - averageLast: 1000, - expected: 0.85, - }, - { - name: 'bad observation data', - observations: [-1, -0.99, -0.55, -0.66, -0.44], - averageLast: 10000, - expected: 0, - }, - ])('$name', ({ observations, averageLast, expected }) => { - const lw = new HistoryWindow(WINDOW_SIZE); - // reverse so that our test observations are in the order they appear above - for (const observation of observations.reverse()) { - lw.addObservation(observation); - } - expect(lw.getAverage(averageLast)).toBe(expected); - }); -}); diff --git a/src/core/packages/metrics/server-internal/src/routes/history_window.ts b/src/core/packages/metrics/server-internal/src/routes/history_window.ts deleted file mode 100644 index 0dc9a4fbe2e2b..0000000000000 --- a/src/core/packages/metrics/server-internal/src/routes/history_window.ts +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the "Elastic License - * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -/** We .ceil to rather _slightly_ over-report usage in certain circumstances */ -const twoDeci = (num: number) => Math.ceil(num * 100) / 100; - -export class HistoryWindow { - readonly #window: number[]; - readonly #size: number; - - constructor(size: number) { - this.#size = size; - this.#window = new Array(this.#size).fill(0); - } - - public get size(): number { - return this.#window.length; - } - - addObservation(value: number) { - this.#window.unshift(Math.max(0, value)); - this.#window.pop(); - } - - /** - * @param includeObservations number of observations to include in calculation. Will be normalized to be within the window size. - */ - getAverage(includeObservations: number) { - includeObservations = Math.min(Math.max(1, includeObservations), this.size); - return twoDeci( - this.#window.slice(0, includeObservations).reduce((acc, val) => acc + val, 0) / - includeObservations - ); - } -} diff --git a/src/core/packages/metrics/server-internal/tsconfig.json b/src/core/packages/metrics/server-internal/tsconfig.json index adf1cdbc8b92b..99202b0feeb36 100644 --- a/src/core/packages/metrics/server-internal/tsconfig.json +++ b/src/core/packages/metrics/server-internal/tsconfig.json @@ -27,6 +27,7 @@ "@kbn/core-logging-server-mocks", "@kbn/core-elasticsearch-server-mocks", "@kbn/core-http-server", + "@kbn/safer-lodash-set", ], "exclude": [ "target/**/*", diff --git a/src/core/packages/metrics/server/index.ts b/src/core/packages/metrics/server/index.ts index c6c76f6067b35..f3e43ad308300 100644 --- a/src/core/packages/metrics/server/index.ts +++ b/src/core/packages/metrics/server/index.ts @@ -10,6 +10,7 @@ export type { MetricsServiceSetup, MetricsServiceStart } from './src/contracts'; export type { MetricsCollector, IEventLoopDelaysMonitor } from './src/collectors'; export type { + EluMetrics, OpsMetrics, IntervalHistogram, OpsProcessMetrics, diff --git a/src/core/packages/metrics/server/src/contracts.ts b/src/core/packages/metrics/server/src/contracts.ts index e648e4fda4b6f..bf8d0514ac51e 100644 --- a/src/core/packages/metrics/server/src/contracts.ts +++ b/src/core/packages/metrics/server/src/contracts.ts @@ -8,7 +8,8 @@ */ import type { Observable } from 'rxjs'; -import type { OpsMetrics } from './metrics'; +import type { EluMetrics, OpsMetrics } from './metrics'; + /** * APIs to retrieves metrics gathered and exposed by the core platform. * @@ -18,6 +19,11 @@ export interface MetricsServiceSetup { /** Interval metrics are collected in milliseconds */ readonly collectionInterval: number; + /** + * Retrieve an observable emitting {@link EluMetrics}. + */ + getEluMetrics$(): Observable; + /** * Retrieve an observable emitting the {@link OpsMetrics} gathered. * The observable will emit an initial value during core's `start` phase, and a new value every fixed interval of time, diff --git a/src/core/packages/metrics/server/src/metrics.ts b/src/core/packages/metrics/server/src/metrics.ts index 9af9fc72f9a17..97665a513c525 100644 --- a/src/core/packages/metrics/server/src/metrics.ts +++ b/src/core/packages/metrics/server/src/metrics.ts @@ -222,3 +222,20 @@ export interface OpsMetrics { /** number of current concurrent connections to the server */ concurrent_connections: OpsServerMetrics['concurrent_connections']; } + +export interface EluMetrics { + /** + * The long-term event loop utilization history. + */ + long: number; + + /** + * The medium-term event loop utilization history. + */ + medium: number; + + /** + * The short-term event loop utilization history. + */ + short: number; +} diff --git a/src/core/packages/plugins/server-internal/src/plugin_context.ts b/src/core/packages/plugins/server-internal/src/plugin_context.ts index d7d40c9b792f7..4467daf572e11 100644 --- a/src/core/packages/plugins/server-internal/src/plugin_context.ts +++ b/src/core/packages/plugins/server-internal/src/plugin_context.ts @@ -256,6 +256,7 @@ export function createPluginSetupContext({ }, metrics: { collectionInterval: deps.metrics.collectionInterval, + getEluMetrics$: deps.metrics.getEluMetrics$, getOpsMetrics$: deps.metrics.getOpsMetrics$, }, savedObjects: { @@ -373,6 +374,7 @@ export function createPluginStartContext({ }, metrics: { collectionInterval: deps.metrics.collectionInterval, + getEluMetrics$: deps.metrics.getEluMetrics$, getOpsMetrics$: deps.metrics.getOpsMetrics$, }, uiSettings: { diff --git a/src/core/packages/root/server-internal/src/server.ts b/src/core/packages/root/server-internal/src/server.ts index d38a52b73494b..1fdbae70cb9e6 100644 --- a/src/core/packages/root/server-internal/src/server.ts +++ b/src/core/packages/root/server-internal/src/server.ts @@ -45,6 +45,7 @@ import type { PrebootRequestHandlerContext, } from '@kbn/core-http-request-handler-context-server'; import { RenderingService } from '@kbn/core-rendering-server-internal'; +import { HttpRateLimiterService } from '@kbn/core-http-rate-limiter-internal'; import { HttpResourcesService } from '@kbn/core-http-resources-server-internal'; import type { InternalCorePreboot, @@ -80,6 +81,7 @@ export class Server { private readonly environment: EnvironmentService; private readonly node: NodeService; private readonly metrics: MetricsService; + private readonly httpRateLimiter: HttpRateLimiterService; private readonly httpResources: HttpResourcesService; private readonly status: StatusService; private readonly logging: LoggingService; @@ -133,6 +135,7 @@ export class Server { this.metrics = new MetricsService(core); this.status = new StatusService(core); this.coreApp = new CoreAppsService(core); + this.httpRateLimiter = new HttpRateLimiterService(); this.httpResources = new HttpResourcesService(core); this.logging = new LoggingService(core); this.coreUsageData = new CoreUsageDataService(core); @@ -343,6 +346,10 @@ export class Server { i18n: i18nServiceSetup, }); + this.httpRateLimiter.setup({ + http: httpSetup, + metrics: metricsSetup, + }); const httpResourcesSetup = this.httpResources.setup({ http: httpSetup, rendering: renderingSetup, @@ -442,6 +449,7 @@ export class Server { const featureFlagsStart = this.featureFlags.start(); + this.httpRateLimiter.start(); this.status.start(); this.coreStart = { @@ -484,6 +492,7 @@ export class Server { this.log.debug('stopping server'); this.coreApp.stop(); + this.httpRateLimiter.stop(); await this.analytics.stop(); await this.http.stop(); // HTTP server has to stop before savedObjects and ES clients are closed to be able to gracefully attempt to resolve any pending requests await this.plugins.stop(); diff --git a/src/core/packages/root/server-internal/tsconfig.json b/src/core/packages/root/server-internal/tsconfig.json index 7fbaf2274b6cf..31e0e876eb083 100644 --- a/src/core/packages/root/server-internal/tsconfig.json +++ b/src/core/packages/root/server-internal/tsconfig.json @@ -77,6 +77,7 @@ "@kbn/core-user-profile-server-mocks", "@kbn/core-user-profile-server-internal", "@kbn/core-feature-flags-server-internal", + "@kbn/core-http-rate-limiter-internal", ], "exclude": [ "target/**/*", diff --git a/src/core/packages/status/server-internal/src/routes/status.ts b/src/core/packages/status/server-internal/src/routes/status.ts index bafda87c2b08d..2824129bc759c 100644 --- a/src/core/packages/status/server-internal/src/routes/status.ts +++ b/src/core/packages/status/server-internal/src/routes/status.ts @@ -90,6 +90,7 @@ export const registerStatusRoute = ({ tags: ['api', 'security:acceptJWT', 'oas-tag:system'], access: 'public', // needs to be public to allow access from "system" users like k8s readiness probes. summary: `Get Kibana's current status`, + excludeFromRateLimiter: true, }, validate: { request: { diff --git a/src/core/packages/status/server-internal/src/routes/status_preboot.ts b/src/core/packages/status/server-internal/src/routes/status_preboot.ts index 510d0c4b91828..0256835500d23 100644 --- a/src/core/packages/status/server-internal/src/routes/status_preboot.ts +++ b/src/core/packages/status/server-internal/src/routes/status_preboot.ts @@ -19,6 +19,7 @@ export const registerPrebootStatusRoute = ({ router }: { router: IRouter }) => { authRequired: false, tags: ['api'], access: 'public', // needs to be public to allow access from "system" users like k8s readiness probes. + excludeFromRateLimiter: true, }, validate: false, }, diff --git a/src/core/packages/status/server-internal/src/status_service.test.ts b/src/core/packages/status/server-internal/src/status_service.test.ts index 00f39f88fdd80..132c51e53e2b1 100644 --- a/src/core/packages/status/server-internal/src/status_service.test.ts +++ b/src/core/packages/status/server-internal/src/status_service.test.ts @@ -100,7 +100,12 @@ describe('StatusService', () => { expect(prebootRouterMock.get).toHaveBeenCalledWith( { path: '/api/status', - options: { authRequired: false, tags: ['api'], access: 'public' }, + options: { + authRequired: false, + tags: ['api'], + access: 'public', + excludeFromRateLimiter: true, + }, validate: false, }, expect.any(Function) 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 427fcc06c3c30..187ed884f068d 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 @@ -62,7 +62,7 @@ describe('checking migration metadata changes on all registered SO types', () => "action": "0e6fc0b74c7312a8c11ff6b14437b93a997358b8", "action_task_params": "2e475d8b62e2de50b77f58cda309efb537e1d543", "ad_hoc_run_params": "c7419760e878207231c3c8a25ec4d78360e07bf7", - "alert": "556a03378f5ee1c31593c3a37c66b54555ee14ff", + "alert": "c5a135d2aca71f56103e9ccba00d6675b0586c82", "api_key_pending_invalidation": "8f5554d1984854011b8392d9a6f7ef985bcac03c", "apm-custom-dashboards": "b67128f78160c288bd7efe25b2da6e2afd5e82fc", "apm-indices": "8a2d68d415a4b542b26b0d292034a28ffac6fed4", @@ -111,7 +111,7 @@ describe('checking migration metadata changes on all registered SO types', () => "fleet-agent-policies": "4a5c6477d2a61121e95ea9865ed1403a28c38706", "fleet-fleet-server-host": "69be15f6b6f2a2875ad3c7050ddea7a87f505417", "fleet-message-signing-keys": "93421f43fed2526b59092a4e3c65d64bc2266c0f", - "fleet-package-policies": "0206c20f27286787b91814a2e7872f06dc1e8e47", + "fleet-package-policies": "8173220091e28ff4afa8238bb37749599378f9e5", "fleet-preconfiguration-deletion-record": "c52ea1e13c919afe8a5e8e3adbb7080980ecc08e", "fleet-proxy": "6cb688f0d2dd856400c1dbc998b28704ff70363d", "fleet-setup-lock": "0dc784792c79b5af5a6e6b5dcac06b0dbaa90bde", @@ -127,9 +127,9 @@ describe('checking migration metadata changes on all registered SO types', () => "ingest-agent-policies": "57ebfb047cf0b81c6fa0ceed8586fa7199c7c5e2", "ingest-download-sources": "279a68147e62e4d8858c09ad1cf03bd5551ce58d", "ingest-outputs": "55988d5f778bbe0e76caa7e6468707a0a056bdd8", - "ingest-package-policies": "60d43f475f91417d14d9df05476acf2e63e99435", + "ingest-package-policies": "870f8c21fe3602f31075430a1fdfb052c62d4a14", "ingest_manager_settings": "111a616eb72627c002029c19feb9e6c439a10505", - "inventory-view": "b8683c8e352a286b4aca1ab21003115a4800af83", + "inventory-view": "fd2b7fe713956f261018dded00d8f8c986417763", "kql-telemetry": "93c1d16c1a0dfca9c8842062cf5ef8f62ae401ad", "legacy-url-alias": "9b8cca3fbb2da46fd12823d3cd38fdf1c9f24bc8", "lens": "5cfa2c52b979b4f8df56dd13c477e152183468b9", diff --git a/src/core/server/integration_tests/saved_objects/migrations/group3/actions/actions_test_suite.ts b/src/core/server/integration_tests/saved_objects/migrations/group3/actions/actions_test_suite.ts index c6995c6e2d4ca..1bf2d5d0d7e6a 100644 --- a/src/core/server/integration_tests/saved_objects/migrations/group3/actions/actions_test_suite.ts +++ b/src/core/server/integration_tests/saved_objects/migrations/group3/actions/actions_test_suite.ts @@ -127,17 +127,19 @@ export const runActionTestSuite = ({ properties: {}, }, })(); - const docs100k = new Array(100000).fill({ + const docs10k = new Array(10000).fill({ _source: { title: new Array(1000).fill('a').join(), type: 'large' }, - }) as unknown as SavedObjectsRawDoc[]; // 100k "large" saved objects - - await bulkOverwriteTransformedDocuments({ - client, - index: 'existing_index_with_100k_docs', - operations: docs100k.map((doc) => createBulkIndexOperationTuple(doc)), - refresh: 'wait_for', - })(); + }) as unknown as SavedObjectsRawDoc[]; // 10k "large" saved objects + const operations = docs10k.map((doc) => createBulkIndexOperationTuple(doc)); + for (let i = 0; i < 10; i++) { + await bulkOverwriteTransformedDocuments({ + client, + index: 'existing_index_with_100k_docs', + operations, + refresh: 'wait_for', + })(); + } await createIndex({ client, indexName: 'existing_index_2', diff --git a/src/dev/storybook/aliases.ts b/src/dev/storybook/aliases.ts index 1aea675a39058..82a6706cb9fc9 100644 --- a/src/dev/storybook/aliases.ts +++ b/src/dev/storybook/aliases.ts @@ -58,7 +58,7 @@ export const storybookAliases = { management: 'packages/kbn-management/storybook/config', observability: 'x-pack/solutions/observability/plugins/observability/.storybook', observability_ai_assistant: - 'x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/.storybook', + 'x-pack/platform/plugins/shared/observability_ai_assistant/.storybook', observability_ai_assistant_app: 'x-pack/solutions/observability/plugins/observability_ai_assistant_app/.storybook', observability_inventory: 'x-pack/solutions/observability/plugins/inventory/.storybook', diff --git a/src/platform/packages/private/kbn-esql-editor/src/editor_footer/errors_warnings_popover.tsx b/src/platform/packages/private/kbn-esql-editor/src/editor_footer/errors_warnings_popover.tsx index fd38177ce41e9..b531b79ed909c 100644 --- a/src/platform/packages/private/kbn-esql-editor/src/editor_footer/errors_warnings_popover.tsx +++ b/src/platform/packages/private/kbn-esql-editor/src/editor_footer/errors_warnings_popover.tsx @@ -17,6 +17,7 @@ import { EuiPopover, EuiDescriptionList, EuiDescriptionListDescription, + euiTextBreakWord, } from '@elastic/eui'; import { css } from '@emotion/react'; import { css as classNameCss } from '@emotion/css'; @@ -86,7 +87,7 @@ function ErrorsWarningsContent({ - + {item.message} diff --git a/src/platform/packages/private/kbn-esql-editor/src/esql_editor.tsx b/src/platform/packages/private/kbn-esql-editor/src/esql_editor.tsx index f94dbb1c378e6..8fb01997c4413 100644 --- a/src/platform/packages/private/kbn-esql-editor/src/esql_editor.tsx +++ b/src/platform/packages/private/kbn-esql-editor/src/esql_editor.tsx @@ -19,6 +19,7 @@ import { } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import moment from 'moment'; +import { isEqual } from 'lodash'; import { CodeEditor, CodeEditorProps } from '@kbn/code-editor'; import type { CoreStart } from '@kbn/core/public'; import type { DataViewsPublicPluginStart } from '@kbn/data-views-plugin/public'; @@ -30,8 +31,9 @@ import memoize from 'lodash/memoize'; import React, { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react'; import { createPortal } from 'react-dom'; import { css } from '@emotion/react'; -import { ESQLRealField } from '@kbn/esql-validation-autocomplete'; +import { ESQLRealField, ESQLControlVariable } from '@kbn/esql-validation-autocomplete'; import { FieldType } from '@kbn/esql-validation-autocomplete/src/definitions/types'; +import { ESQLVariableType } from '@kbn/esql-validation-autocomplete'; import { EditorFooter } from './editor_footer'; import { fetchFieldsFromESQL } from './fetch_fields_from_esql'; import { @@ -42,6 +44,7 @@ import { useDebounceWithOptions, onKeyDownResizeHandler, onMouseDownResizeHandler, + getEditorOverwrites, type MonacoMessage, } from './helpers'; import { addQueriesToCache } from './history_local_storage'; @@ -54,11 +57,28 @@ import { } from './esql_editor.styles'; import type { ESQLEditorProps, ESQLEditorDeps } from './types'; -import './overwrite.scss'; - // for editor width smaller than this value we want to start hiding some text const BREAKPOINT_WIDTH = 540; +const triggerControl = async ( + queryString: string, + variableType: ESQLVariableType, + position: monaco.Position | null | undefined, + uiActions: ESQLEditorDeps['uiActions'], + esqlVariables?: ESQLControlVariable[], + onSaveControl?: ESQLEditorProps['onSaveControl'], + onCancelControl?: ESQLEditorProps['onCancelControl'] +) => { + await uiActions.getTrigger('ESQL_CONTROL_TRIGGER').exec({ + queryString, + variableType, + cursorPosition: position, + esqlVariables, + onSaveControl, + onCancelControl, + }); +}; + export const ESQLEditor = memo(function ESQLEditor({ query, onTextLangQueryChange, @@ -78,10 +98,14 @@ export const ESQLEditor = memo(function ESQLEditor({ hasOutline, displayDocumentationAsFlyout, disableAutoFocus, + onSaveControl, + onCancelControl, + supportsControls, + esqlVariables, }: ESQLEditorProps) { const popoverRef = useRef(null); const datePickerOpenStatusRef = useRef(false); - const { euiTheme } = useEuiTheme(); + const theme = useEuiTheme(); const kibana = useKibana(); const { dataViews, @@ -91,8 +115,10 @@ export const ESQLEditor = memo(function ESQLEditor({ core, fieldsMetadata, uiSettings, + uiActions, } = kibana.services; + const variablesService = kibana.services?.esql?.variablesService; const histogramBarTarget = uiSettings?.get('histogram:barTarget') ?? 50; const [code, setCode] = useState(query.esql ?? ''); // To make server side errors less "sticky", register the state of the code when submitting @@ -187,6 +213,23 @@ export const ESQLEditor = memo(function ESQLEditor({ } }, [code, query.esql]); + // Enable the variables service if the feature is supported in the consumer app + useEffect(() => { + if (supportsControls) { + variablesService?.enableSuggestions(); + + const variables = variablesService?.esqlVariables; + if (!isEqual(variables, esqlVariables)) { + variablesService?.clearVariables(); + esqlVariables?.forEach((variable) => { + variablesService?.addVariable(variable); + }); + } + } else { + variablesService?.disableSuggestions(); + } + }, [variablesService, supportsControls, esqlVariables]); + const toggleHistory = useCallback((status: boolean) => { setIsHistoryOpen(status); }, []); @@ -230,8 +273,47 @@ export const ESQLEditor = memo(function ESQLEditor({ openTimePickerPopover(); }); + monaco.editor.registerCommand('esql.control.time_literal.create', async (...args) => { + const position = editor1.current?.getPosition(); + await triggerControl( + query.esql, + ESQLVariableType.TIME_LITERAL, + position, + uiActions, + esqlVariables, + onSaveControl, + onCancelControl + ); + }); + + monaco.editor.registerCommand('esql.control.fields.create', async (...args) => { + const position = editor1.current?.getPosition(); + await triggerControl( + query.esql, + ESQLVariableType.FIELDS, + position, + uiActions, + esqlVariables, + onSaveControl, + onCancelControl + ); + }); + + monaco.editor.registerCommand('esql.control.values.create', async (...args) => { + const position = editor1.current?.getPosition(); + await triggerControl( + query.esql, + ESQLVariableType.VALUES, + position, + uiActions, + esqlVariables, + onSaveControl, + onCancelControl + ); + }); + const styles = esqlEditorStyles( - euiTheme, + theme.euiTheme, editorHeight, Boolean(editorMessages.errors.length), Boolean(editorMessages.warnings.length), @@ -373,13 +455,20 @@ export const ESQLEditor = memo(function ESQLEditor({ }, // @ts-expect-error To prevent circular type import, type defined here is partial of full client getFieldsMetadata: fieldsMetadata?.getClient(), + getVariablesByType: (type: ESQLVariableType) => { + return variablesService?.esqlVariables.filter((variable) => variable.type === type); + }, + canSuggestVariables: () => { + return variablesService?.areSuggestionsEnabled ?? false; + }, getJoinIndices: kibana.services?.esql?.getJoinIndicesAutocomplete, }; return callbacks; }, [ + fieldsMetadata, + dataSourcesCache, query.esql, memoizedSources, - dataSourcesCache, dataViews, core, esqlFieldsCache, @@ -388,7 +477,7 @@ export const ESQLEditor = memo(function ESQLEditor({ abortController, indexManagementApiService, histogramBarTarget, - fieldsMetadata, + variablesService, kibana.services?.esql?.getJoinIndicesAutocomplete, ]); @@ -596,7 +685,7 @@ export const ESQLEditor = memo(function ESQLEditor({ responsive={false} justifyContent="flexEnd" css={css` - padding: ${euiTheme.size.s}; + padding: ${theme.euiTheme.size.s}; `} > @@ -640,6 +729,7 @@ export const ESQLEditor = memo(function ESQLEditor({
) => { + return css` + .monaco-hover { + display: block !important; + } + .margin-view-overlays .line-numbers { + color: ${theme.euiTheme.colors.textDisabled}; + } + .current-line ~ .line-numbers { + color: ${theme.euiTheme.colors.textSubdued}; + } + + .suggest-widget, + .suggest-details-container { + border-radius: ${theme.euiTheme.border.radius.medium}; + ${euiShadow(theme, 'l')} + } + + .suggest-details-container { + background-color: ${theme.euiTheme.colors.backgroundBasePlain}; + line-height: 1.5rem; + } + .suggest-details { + padding-left: ${theme.euiTheme.size.s}; + } + .monaco-list .monaco-scrollable-element .monaco-list-row.focused { + border-radius: ${theme.euiTheme.border.radius.medium}; + } + `; +}; diff --git a/src/platform/packages/private/kbn-esql-editor/src/overwrite.scss b/src/platform/packages/private/kbn-esql-editor/src/overwrite.scss deleted file mode 100644 index 9e716b55f3e2b..0000000000000 --- a/src/platform/packages/private/kbn-esql-editor/src/overwrite.scss +++ /dev/null @@ -1,39 +0,0 @@ -/* Editor styles for any layout mode */ -/* NOTE: Much of this is overriding Monaco styles so the specificity is intentional */ - -.ESQLEditor .monaco-editor .monaco-hover { - display: block !important; -} - -.ESQLEditor .monaco-editor .margin-view-overlays .line-numbers { - color: $euiColorDisabledText; -} - -// Currently focused line(s) -.ESQLEditor .monaco-editor .current-line ~ .line-numbers { - color: $euiTextSubduedColor; -} - -// Suggest (autocomplete) menu -.ESQLEditor .monaco-editor .suggest-widget, .ESQLEditor .monaco-editor .suggest-details-container { - @include euiBottomShadow; - border-radius: $euiBorderRadius; -} - -.ESQLEditor .monaco-editor .suggest-details-container { - background-color: $euiColorEmptyShade; - line-height: 1.5rem; -} - -.ESQLEditor_errorMessage { - @include euiTextBreakWord; -} - -// Space between the autocomplete menu and expanded suggestion details -.ESQLEditor .monaco-editor .suggest-details { - padding-left: $euiSizeS; -} - -.ESQLEditor .monaco-editor .monaco-list .monaco-scrollable-element .monaco-list-row.focused { - border-radius: $euiBorderRadius; -} \ No newline at end of file diff --git a/src/platform/packages/private/kbn-esql-editor/src/types.ts b/src/platform/packages/private/kbn-esql-editor/src/types.ts index 177dc2b398873..df5243bb49193 100644 --- a/src/platform/packages/private/kbn-esql-editor/src/types.ts +++ b/src/platform/packages/private/kbn-esql-editor/src/types.ts @@ -15,6 +15,8 @@ import type { IndexManagementPluginSetup } from '@kbn/index-management-shared-ty import type { FieldsMetadataPublicStart } from '@kbn/fields-metadata-plugin/public'; import type { UsageCollectionStart } from '@kbn/usage-collection-plugin/public'; import type { Storage } from '@kbn/kibana-utils-plugin/public'; +import type { UiActionsStart } from '@kbn/ui-actions-plugin/public'; +import type { ESQLControlVariable } from '@kbn/esql-validation-autocomplete'; export interface ESQLEditorProps { /** The aggregate type query */ @@ -69,6 +71,16 @@ export interface ESQLEditorProps { /** The component by default focuses on the editor when it is mounted, this flag disables it**/ disableAutoFocus?: boolean; + /** The editor supports the creation of controls, + * This flag should be set to true to display the "Create control" suggestion + **/ + supportsControls?: boolean; + /** Function to be called after the control creation **/ + onSaveControl?: (controlState: Record, updatedQuery: string) => Promise; + /** Function to be called after cancelling the control creation **/ + onCancelControl?: () => void; + /** The available ESQL variables from the page context this editor was opened in */ + esqlVariables?: ESQLControlVariable[]; } export interface JoinIndicesAutocompleteResult { @@ -81,8 +93,18 @@ export interface JoinIndexAutocompleteItem { aliases: string[]; } +interface ESQLVariableService { + areSuggestionsEnabled: boolean; + esqlVariables: ESQLControlVariable[]; + enableSuggestions: () => void; + disableSuggestions: () => void; + clearVariables: () => void; + addVariable: (variable: ESQLControlVariable) => void; +} + export interface EsqlPluginStartBase { getJoinIndicesAutocomplete: () => Promise; + variablesService: ESQLVariableService; } export interface ESQLEditorDeps { @@ -90,6 +112,7 @@ export interface ESQLEditorDeps { dataViews: DataViewsPublicPluginStart; expressions: ExpressionsStart; storage: Storage; + uiActions: UiActionsStart; indexManagementApiService?: IndexManagementPluginSetup['apiService']; fieldsMetadata?: FieldsMetadataPublicStart; usageCollection?: UsageCollectionStart; diff --git a/src/platform/packages/private/kbn-esql-editor/tsconfig.json b/src/platform/packages/private/kbn-esql-editor/tsconfig.json index 96c05ba88d600..85dda7f030af0 100644 --- a/src/platform/packages/private/kbn-esql-editor/tsconfig.json +++ b/src/platform/packages/private/kbn-esql-editor/tsconfig.json @@ -32,6 +32,7 @@ "@kbn/usage-collection-plugin", "@kbn/content-management-favorites-common", "@kbn/kibana-utils-plugin", + "@kbn/ui-actions-plugin", "@kbn/shared-ux-table-persist" ], "exclude": [ diff --git a/src/platform/packages/private/kbn-grid-layout/grid/grid_layout.test.tsx b/src/platform/packages/private/kbn-grid-layout/grid/grid_layout.test.tsx index 2d828c9d38c21..240870bd813f2 100644 --- a/src/platform/packages/private/kbn-grid-layout/grid/grid_layout.test.tsx +++ b/src/platform/packages/private/kbn-grid-layout/grid/grid_layout.test.tsx @@ -22,13 +22,15 @@ import { touchStart, } from './test_utils/events'; +const onLayoutChange = jest.fn(); + const renderGridLayout = (propsOverrides: Partial = {}) => { const defaultProps: GridLayoutProps = { accessMode: 'EDIT', layout: getSampleLayout(), gridSettings, renderPanelContents: mockRenderPanelContents, - onLayoutChange: jest.fn(), + onLayoutChange, }; const { rerender, ...rtlRest } = render(); @@ -76,6 +78,41 @@ describe('GridLayout', () => { jest.clearAllMocks(); }); + it('`onLayoutChange` gets called when layout prop changes', () => { + const layoutComponent = renderGridLayout(); + onLayoutChange.mockClear(); + + const layout = getSampleLayout(); + + // if layout hasn't changed, don't call `onLayoutChange` + layoutComponent.rerender({ + layout, + }); + expect(onLayoutChange).not.toBeCalled(); + + // if layout **has** changed, call `onLayoutChange` + const newLayout = cloneDeep(layout); + newLayout[0] = { + ...newLayout[0], + panels: { + ...newLayout[0].panels, + panel1: { + id: 'panel1', + row: 100, + column: 0, + width: 12, + height: 6, + }, + }, + }; + + layoutComponent.rerender({ + layout: newLayout, + }); + + expect(onLayoutChange).toBeCalledTimes(1); + }); + it(`'renderPanelContents' is not called during dragging`, () => { renderGridLayout(); diff --git a/src/platform/packages/private/kbn-grid-layout/grid/grid_panel/grid_panel.tsx b/src/platform/packages/private/kbn-grid-layout/grid/grid_panel/grid_panel.tsx index da5c5ed9dc3f3..a73449fdc3c21 100644 --- a/src/platform/packages/private/kbn-grid-layout/grid/grid_panel/grid_panel.tsx +++ b/src/platform/packages/private/kbn-grid-layout/grid/grid_panel/grid_panel.tsx @@ -57,12 +57,13 @@ export const GridPanel = forwardRef( /** Update the styles of the panel via a subscription to prevent re-renders */ const activePanelStyleSubscription = combineLatest([ gridLayoutStateManager.activePanel$, + gridLayoutStateManager.gridLayout$, gridLayoutStateManager.proposedGridLayout$, ]) .pipe(skip(1)) // skip the first emit because the `initialStyles` will take care of it - .subscribe(([activePanel, proposedGridLayout]) => { + .subscribe(([activePanel, gridLayout, proposedGridLayout]) => { const ref = gridLayoutStateManager.panelRefs.current[rowIndex][panelId]; - const panel = proposedGridLayout?.[rowIndex].panels[panelId]; + const panel = (proposedGridLayout ?? gridLayout)[rowIndex].panels[panelId]; if (!ref || !panel) return; const currentInteractionEvent = gridLayoutStateManager.interactionEvent$.getValue(); diff --git a/src/platform/packages/private/kbn-language-documentation/src/sections/generated/scalar_functions.tsx b/src/platform/packages/private/kbn-language-documentation/src/sections/generated/scalar_functions.tsx index 4336e9f705d35..c372b496a7585 100644 --- a/src/platform/packages/private/kbn-language-documentation/src/sections/generated/scalar_functions.tsx +++ b/src/platform/packages/private/kbn-language-documentation/src/sections/generated/scalar_functions.tsx @@ -1381,7 +1381,8 @@ export const functions = { Use \`MATCH\` to perform a match query on the specified field. Using \`MATCH\` is equivalent to using the \`match\` query in the Elasticsearch Query DSL. - Match can be used on text fields, as well as other field types like boolean, dates, and numeric types. + Match can be used on fields from the text family like text and semantic_text, + as well as other field types like keyword, boolean, dates, and numeric types. For a simplified syntax, you can use the match operator \`:\` operator instead of \`MATCH\`. @@ -3378,7 +3379,7 @@ export const functions = { label: i18n.translate('languageDocumentation.documentationESQL.to_date_nanos', { defaultMessage: 'TO_DATE_NANOS', }), - preview: true, + preview: false, description: ( >; + params?: + | estypes.ScalarValue[] + | Array | undefined>>; } diff --git a/src/platform/packages/shared/kbn-esql-utils/index.ts b/src/platform/packages/shared/kbn-esql-utils/index.ts index 7d75e230389f5..218927f1132d2 100644 --- a/src/platform/packages/shared/kbn-esql-utils/index.ts +++ b/src/platform/packages/shared/kbn-esql-utils/index.ts @@ -25,6 +25,7 @@ export { getTimeFieldFromESQLQuery, getStartEndParams, hasStartEndParams, + getNamedParams, prettifyQuery, isQueryWrappedByPipes, retrieveMetadataColumns, @@ -35,6 +36,7 @@ export { TextBasedLanguages, sanitazeESQLInput, queryCannotBeSampled, + mapVariableToColumn, } from './src'; export { ENABLE_ESQL, FEEDBACK_LINK } from './constants'; diff --git a/src/platform/packages/shared/kbn-esql-utils/src/index.ts b/src/platform/packages/shared/kbn-esql-utils/src/index.ts index a28d9c6244f74..21b91939dcacb 100644 --- a/src/platform/packages/shared/kbn-esql-utils/src/index.ts +++ b/src/platform/packages/shared/kbn-esql-utils/src/index.ts @@ -21,6 +21,7 @@ export { isQueryWrappedByPipes, retrieveMetadataColumns, getQueryColumnsFromESQLQuery, + mapVariableToColumn, } from './utils/query_parsing_helpers'; export { queryCannotBeSampled } from './utils/query_cannot_be_sampled'; export { appendToESQLQuery, appendWhereClauseToESQLQuery } from './utils/append_to_query'; @@ -31,6 +32,7 @@ export { formatESQLColumns, getStartEndParams, hasStartEndParams, + getNamedParams, } from './utils/run_query'; export { isESQLColumnSortable, diff --git a/src/platform/packages/shared/kbn-esql-utils/src/utils/query_parsing_helpers.test.ts b/src/platform/packages/shared/kbn-esql-utils/src/utils/query_parsing_helpers.test.ts index 709d86bbfc924..9f17a98ae62b6 100644 --- a/src/platform/packages/shared/kbn-esql-utils/src/utils/query_parsing_helpers.test.ts +++ b/src/platform/packages/shared/kbn-esql-utils/src/utils/query_parsing_helpers.test.ts @@ -6,7 +6,8 @@ * your election, the "Elastic License 2.0", the "GNU Affero General Public * License v3.0 only", or the "Server Side Public License, v 1". */ - +import type { DatatableColumn } from '@kbn/expressions-plugin/common'; +import { ESQLVariableType, type ESQLControlVariable } from '@kbn/esql-validation-autocomplete'; import { getIndexPatternFromESQLQuery, getLimitFromESQLQuery, @@ -17,6 +18,7 @@ import { isQueryWrappedByPipes, retrieveMetadataColumns, getQueryColumnsFromESQLQuery, + mapVariableToColumn, } from './query_parsing_helpers'; describe('esql query helpers', () => { @@ -273,4 +275,268 @@ describe('esql query helpers', () => { ]); }); }); + + describe('mapVariableToColumn', () => { + it('should return the columns as they are if no variables are defined', () => { + const esql = 'FROM a | EVAL b = 1'; + const variables: ESQLControlVariable[] = []; + const columns = [{ id: 'b', name: 'b', meta: { type: 'number' } }] as DatatableColumn[]; + expect(mapVariableToColumn(esql, variables, columns)).toStrictEqual(columns); + }); + + it('should return the columns as they are if variables do not match', () => { + const esql = 'FROM logstash-* | STATS COUNT(*) BY ?field | LIMIT 10'; + const variables = [ + { + key: 'interval', + value: '5 minutes', + type: ESQLVariableType.TIME_LITERAL, + }, + ]; + const columns = [ + { + id: 'COUNT(*)', + name: 'COUNT(*)', + meta: { + type: 'number', + esType: 'long', + sourceParams: { + indexPattern: 'logstash-*', + }, + }, + isNull: false, + }, + { + id: 'clientip', + name: 'clientip', + meta: { + type: 'ip', + esType: 'ip', + sourceParams: { + indexPattern: 'logstash-*', + }, + }, + isNull: false, + }, + ] as DatatableColumn[]; + expect(mapVariableToColumn(esql, variables, columns)).toStrictEqual(columns); + }); + + it('should return the columns enhanced with the corresponsing variables for a field type variable', () => { + const esql = 'FROM logstash-* | STATS COUNT(*) BY ?field | LIMIT 10 '; + const variables = [ + { + key: 'field', + value: 'clientip', + type: ESQLVariableType.FIELDS, + }, + { + key: 'interval', + value: '5 minutes', + type: ESQLVariableType.TIME_LITERAL, + }, + { + key: 'agent_name', + value: 'go', + type: ESQLVariableType.VALUES, + }, + ]; + const columns = [ + { + id: 'COUNT(*)', + name: 'COUNT(*)', + meta: { + type: 'number', + esType: 'long', + sourceParams: { + indexPattern: 'logstash-*', + }, + }, + isNull: false, + }, + { + id: 'clientip', + name: 'clientip', + meta: { + type: 'ip', + esType: 'ip', + sourceParams: { + indexPattern: 'logstash-*', + }, + }, + isNull: false, + }, + ] as DatatableColumn[]; + const expectedColumns = columns; + expectedColumns[1].variable = 'field'; + expect(mapVariableToColumn(esql, variables, columns)).toStrictEqual(expectedColumns); + }); + + it('should return the columns enhanced with the corresponsing variables for a time_literal type variable', () => { + const esql = 'FROM logs* | STATS COUNT(*) BY BUCKET(@timestamp, ?interval)'; + const variables = [ + { + key: 'field', + value: 'clientip', + type: ESQLVariableType.FIELDS, + }, + { + key: 'interval', + value: '5 minutes', + type: ESQLVariableType.TIME_LITERAL, + }, + { + key: 'agent_name', + value: 'go', + type: ESQLVariableType.VALUES, + }, + ]; + const columns = [ + { + id: 'COUNT(*)', + name: 'COUNT(*)', + meta: { + type: 'number', + esType: 'long', + sourceParams: { + indexPattern: 'logs*', + }, + }, + isNull: false, + }, + { + id: 'BUCKET(@timestamp, ?interval)', + name: 'BUCKET(@timestamp, ?interval)', + meta: { + type: 'date', + esType: 'date', + sourceParams: { + appliedTimeRange: { + from: 'now-30d/d', + to: 'now', + }, + params: {}, + indexPattern: 'logs*', + }, + }, + isNull: false, + }, + ] as DatatableColumn[]; + const expectedColumns = columns; + expectedColumns[1].variable = 'interval'; + expect(mapVariableToColumn(esql, variables, columns)).toStrictEqual(expectedColumns); + }); + + it('should return the columns enhanced with the corresponsing variables for a values type variable', () => { + const esql = 'FROM logs* | WHERE agent.name == ?agent_name'; + const variables = [ + { + key: 'field', + value: 'clientip', + type: ESQLVariableType.FIELDS, + }, + { + key: 'interval', + value: '5 minutes', + type: ESQLVariableType.TIME_LITERAL, + }, + { + key: 'agent_name', + value: 'go', + type: ESQLVariableType.VALUES, + }, + ]; + const columns = [ + { + id: '@timestamp', + isNull: false, + meta: { type: 'date', esType: 'date' }, + name: '@timestamp', + }, + { + id: 'agent.name', + isNull: false, + meta: { type: 'string', esType: 'keyword' }, + name: 'agent.name', + }, + ] as DatatableColumn[]; + const expectedColumns = columns; + expectedColumns[1].variable = 'agent_name'; + expect(mapVariableToColumn(esql, variables, columns)).toStrictEqual(expectedColumns); + }); + + it('should return the columns as they are if the variable field is dropped', () => { + const esql = 'FROM logs* | WHERE agent.name == ?agent_name | DROP agent.name'; + const variables = [ + { + key: 'field', + value: 'clientip', + type: ESQLVariableType.FIELDS, + }, + { + key: 'interval', + value: '5 minutes', + type: ESQLVariableType.TIME_LITERAL, + }, + { + key: 'agent_name', + value: 'go', + type: ESQLVariableType.VALUES, + }, + ]; + const columns = [ + { + id: '@timestamp', + isNull: false, + meta: { type: 'date', esType: 'date' }, + name: '@timestamp', + }, + ] as DatatableColumn[]; + expect(mapVariableToColumn(esql, variables, columns)).toStrictEqual(columns); + }); + + it('should return the columns correctly if variable is used in KEEP', () => { + const esql = 'FROM logstash-* | KEEP bytes, ?field'; + const variables = [ + { + key: 'field', + value: 'clientip', + type: ESQLVariableType.FIELDS, + }, + { + key: 'interval', + value: '5 minutes', + type: ESQLVariableType.TIME_LITERAL, + }, + { + key: 'agent_name', + value: 'go', + type: ESQLVariableType.VALUES, + }, + ]; + const columns = [ + { + id: 'bytes', + isNull: false, + meta: { type: 'number', esType: 'long' }, + name: 'bytes', + }, + { + id: 'clientip', + name: 'clientip', + meta: { + type: 'ip', + esType: 'ip', + sourceParams: { + indexPattern: 'logstash-*', + }, + }, + isNull: false, + }, + ] as DatatableColumn[]; + const expectedColumns = columns; + expectedColumns[1].variable = 'field'; + expect(mapVariableToColumn(esql, variables, columns)).toStrictEqual(expectedColumns); + }); + }); }); diff --git a/src/platform/packages/shared/kbn-esql-utils/src/utils/query_parsing_helpers.ts b/src/platform/packages/shared/kbn-esql-utils/src/utils/query_parsing_helpers.ts index ccad80f064a03..64fc9eabe7836 100644 --- a/src/platform/packages/shared/kbn-esql-utils/src/utils/query_parsing_helpers.ts +++ b/src/platform/packages/shared/kbn-esql-utils/src/utils/query_parsing_helpers.ts @@ -15,6 +15,8 @@ import type { ESQLSingleAstItem, ESQLCommandOption, } from '@kbn/esql-ast'; +import type { ESQLControlVariable } from '@kbn/esql-validation-autocomplete'; +import type { DatatableColumn } from '@kbn/expressions-plugin/common'; const DEFAULT_ESQL_LIMIT = 1000; @@ -147,3 +149,34 @@ export const getQueryColumnsFromESQLQuery = (esql: string): string[] => { return columns.map((column) => column.name); }; +/** + * This function is used to map the variables to the columns in the datatable + * @param esql:string + * @param variables:ESQLControlVariable[] + * @param columns:DatatableColumn[] + * @returns DatatableColumn[] + */ +export const mapVariableToColumn = ( + esql: string, + variables: ESQLControlVariable[], + columns: DatatableColumn[] +): DatatableColumn[] => { + if (!variables.length) { + return columns; + } + const { root } = parse(esql); + const usedVariablesInQuery = Walker.params(root); + + const uniqueVariablesInQyery = new Set( + usedVariablesInQuery.map((v) => v.text.replace('?', '')) + ); + + columns.map((column) => { + if (variables.some((variable) => variable.value === column.id)) { + const potentialColumnVariables = variables.filter((variable) => variable.value === column.id); + const variable = potentialColumnVariables.find((v) => uniqueVariablesInQyery.has(v.key)); + column.variable = variable?.key ?? ''; + } + }); + return columns; +}; diff --git a/src/platform/packages/shared/kbn-esql-utils/src/utils/run_query.test.ts b/src/platform/packages/shared/kbn-esql-utils/src/utils/run_query.test.ts index 8618d078f5e06..9c8c52dae176f 100644 --- a/src/platform/packages/shared/kbn-esql-utils/src/utils/run_query.test.ts +++ b/src/platform/packages/shared/kbn-esql-utils/src/utils/run_query.test.ts @@ -6,39 +6,135 @@ * your election, the "Elastic License 2.0", the "GNU Affero General Public * License v3.0 only", or the "Server Side Public License, v 1". */ +import { ESQLVariableType, type ESQLControlVariable } from '@kbn/esql-validation-autocomplete'; +import { getStartEndParams, getNamedParams } from './run_query'; -import { getStartEndParams } from './run_query'; +describe('run query helpers', () => { + describe('getStartEndParams', () => { + it('should return an empty array if there are no time params', () => { + const time = { from: 'now-15m', to: 'now' }; + const query = 'FROM foo'; + const params = getStartEndParams(query, time); + expect(params).toEqual([]); + }); -describe('getStartEndParams', () => { - it('should return an empty array if there are no time params', () => { - const time = { from: 'now-15m', to: 'now' }; - const query = 'FROM foo'; - const params = getStartEndParams(query, time); - expect(params).toEqual([]); - }); + it('should return an array with the start param if exists at the query', () => { + const time = { from: 'Jul 5, 2024 @ 08:03:56.849', to: 'Jul 5, 2024 @ 10:03:56.849' }; + const query = 'FROM foo | where time > ?_tstart'; + const params = getStartEndParams(query, time); + expect(params).toHaveLength(1); + expect(params[0]).toHaveProperty('_tstart'); + }); - it('should return an array with the start param if exists at the query', () => { - const time = { from: 'Jul 5, 2024 @ 08:03:56.849', to: 'Jul 5, 2024 @ 10:03:56.849' }; - const query = 'FROM foo | where time > ?_tstart'; - const params = getStartEndParams(query, time); - expect(params).toHaveLength(1); - expect(params[0]).toHaveProperty('_tstart'); - }); + it('should return an array with the end param if exists at the query', () => { + const time = { from: 'Jul 5, 2024 @ 08:03:56.849', to: 'Jul 5, 2024 @ 10:03:56.849' }; + const query = 'FROM foo | where time < ?_tend'; + const params = getStartEndParams(query, time); + expect(params).toHaveLength(1); + expect(params[0]).toHaveProperty('_tend'); + }); - it('should return an array with the end param if exists at the query', () => { - const time = { from: 'Jul 5, 2024 @ 08:03:56.849', to: 'Jul 5, 2024 @ 10:03:56.849' }; - const query = 'FROM foo | where time < ?_tend'; - const params = getStartEndParams(query, time); - expect(params).toHaveLength(1); - expect(params[0]).toHaveProperty('_tend'); + it('should return an array with the end and start params if exist at the query', () => { + const time = { from: 'Jul 5, 2024 @ 08:03:56.849', to: 'Jul 5, 2024 @ 10:03:56.849' }; + const query = 'FROM foo | where time < ?_tend amd time > ?_tstart'; + const params = getStartEndParams(query, time); + expect(params).toHaveLength(2); + expect(params[0]).toHaveProperty('_tstart'); + expect(params[1]).toHaveProperty('_tend'); + }); }); - it('should return an array with the end and start params if exist at the query', () => { - const time = { from: 'Jul 5, 2024 @ 08:03:56.849', to: 'Jul 5, 2024 @ 10:03:56.849' }; - const query = 'FROM foo | where time < ?_tend amd time > ?_tstart'; - const params = getStartEndParams(query, time); - expect(params).toHaveLength(2); - expect(params[0]).toHaveProperty('_tstart'); - expect(params[1]).toHaveProperty('_tend'); + describe('getNamedParams', () => { + it('should return an empty array if there are no params', () => { + const time = { from: 'now-15m', to: 'now' }; + const query = 'FROM foo'; + const variables: ESQLControlVariable[] = []; + const params = getNamedParams(query, time, variables); + expect(params).toEqual([]); + }); + + it('should return the time params if given', () => { + const time = { from: 'Jul 5, 2024 @ 08:03:56.849', to: 'Jul 5, 2024 @ 10:03:56.849' }; + const query = 'FROM foo | where time < ?_tend amd time > ?_tstart'; + const variables: ESQLControlVariable[] = []; + const params = getNamedParams(query, time, variables); + expect(params).toHaveLength(2); + expect(params[0]).toHaveProperty('_tstart'); + expect(params[1]).toHaveProperty('_tend'); + }); + + it('should return the variables if given', () => { + const time = { from: 'Jul 5, 2024 @ 08:03:56.849', to: 'Jul 5, 2024 @ 10:03:56.849' }; + const query = 'FROM foo | KEEP ?field | WHERE agent.name = ?agent_name'; + const variables = [ + { + key: 'field', + value: 'clientip', + type: ESQLVariableType.FIELDS, + }, + { + key: 'interval', + value: '5 minutes', + type: ESQLVariableType.TIME_LITERAL, + }, + { + key: 'agent_name', + value: 'go', + type: ESQLVariableType.VALUES, + }, + ]; + const params = getNamedParams(query, time, variables); + expect(params).toStrictEqual([ + { + field: { + identifier: 'clientip', + }, + }, + { + interval: '5 minutes', + }, + { + agent_name: 'go', + }, + ]); + }); + + it('should return the variables and named params if given', () => { + const time = { from: 'Jul 5, 2024 @ 08:03:56.849', to: 'Jul 5, 2024 @ 10:03:56.849' }; + const query = + 'FROM foo | KEEP ?field | WHERE agent.name = ?agent_name AND time < ?_tend amd time > ?_tstart'; + const variables = [ + { + key: 'field', + value: 'clientip', + type: ESQLVariableType.FIELDS, + }, + { + key: 'interval', + value: '5 minutes', + type: ESQLVariableType.TIME_LITERAL, + }, + { + key: 'agent_name', + value: 'go', + type: ESQLVariableType.VALUES, + }, + ]; + const params = getNamedParams(query, time, variables); + expect(params).toHaveLength(5); + expect(params[0]).toHaveProperty('_tstart'); + expect(params[1]).toHaveProperty('_tend'); + expect(params[2]).toStrictEqual({ + field: { + identifier: 'clientip', + }, + }); + expect(params[3]).toStrictEqual({ + interval: '5 minutes', + }); + expect(params[4]).toStrictEqual({ + agent_name: 'go', + }); + }); }); }); diff --git a/src/platform/packages/shared/kbn-esql-utils/src/utils/run_query.ts b/src/platform/packages/shared/kbn-esql-utils/src/utils/run_query.ts index b9b09336a7c20..3a413034e3ab3 100644 --- a/src/platform/packages/shared/kbn-esql-utils/src/utils/run_query.ts +++ b/src/platform/packages/shared/kbn-esql-utils/src/utils/run_query.ts @@ -15,6 +15,7 @@ import type { TimeRange } from '@kbn/es-query'; import { esFieldTypeToKibanaFieldType } from '@kbn/field-types'; import type { ESQLColumn, ESQLSearchResponse, ESQLSearchParams } from '@kbn/es-types'; import { lastValueFrom } from 'rxjs'; +import { type ESQLControlVariable, ESQLVariableType } from '@kbn/esql-validation-autocomplete'; export const hasStartEndParams = (query: string) => /\?_tstart|\?_tend/i.test(query); @@ -38,6 +39,24 @@ export const getStartEndParams = (query: string, time?: TimeRange) => { return []; }; +export const getNamedParams = ( + query: string, + timeRange?: TimeRange, + variables?: ESQLControlVariable[] +) => { + const namedParams: ESQLSearchParams['params'] = getStartEndParams(query, timeRange); + if (variables?.length) { + variables?.forEach(({ key, value, type }) => { + if (type === ESQLVariableType.FIELDS) { + namedParams.push({ [key]: { identifier: value } }); + } else { + namedParams.push({ [key]: value }); + } + }); + } + return namedParams; +}; + export function formatESQLColumns(columns: ESQLColumn[]): DatatableColumn[] { return columns.map(({ name, type }) => { const kibanaType = esFieldTypeToKibanaFieldType(type); @@ -126,6 +145,7 @@ export async function getESQLResults({ filter, dropNullColumns, timeRange, + variables, }: { esqlQuery: string; search: ISearchGeneric; @@ -133,11 +153,12 @@ export async function getESQLResults({ filter?: unknown; dropNullColumns?: boolean; timeRange?: TimeRange; + variables?: ESQLControlVariable[]; }): Promise<{ response: ESQLSearchResponse; params: ESQLSearchParams; }> { - const namedParams = getStartEndParams(esqlQuery, timeRange); + const namedParams = getNamedParams(esqlQuery, timeRange, variables); const result = await lastValueFrom( search( { diff --git a/src/platform/packages/shared/kbn-esql-utils/tsconfig.json b/src/platform/packages/shared/kbn-esql-utils/tsconfig.json index c57e474c9a248..3c45073c44be8 100644 --- a/src/platform/packages/shared/kbn-esql-utils/tsconfig.json +++ b/src/platform/packages/shared/kbn-esql-utils/tsconfig.json @@ -26,6 +26,7 @@ "@kbn/es-types", "@kbn/i18n", "@kbn/datemath", - "@kbn/es-query" + "@kbn/es-query", + "@kbn/esql-validation-autocomplete" ] } diff --git a/src/platform/packages/shared/kbn-esql-validation-autocomplete/index.ts b/src/platform/packages/shared/kbn-esql-validation-autocomplete/index.ts index 67fdd72880150..1ce5be2e69ffa 100644 --- a/src/platform/packages/shared/kbn-esql-validation-autocomplete/index.ts +++ b/src/platform/packages/shared/kbn-esql-validation-autocomplete/index.ts @@ -8,6 +8,8 @@ */ export type { SuggestionRawDefinition, ItemKind } from './src/autocomplete/types'; +export { ESQLVariableType, type ESQLControlVariable } from './src/shared/types'; +export { inKnownTimeInterval } from './src/shared/helpers'; export type { CodeAction } from './src/code_actions/types'; export type { FunctionDefinition, diff --git a/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/__tests__/autocomplete.command.stats.test.ts b/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/__tests__/autocomplete.command.stats.test.ts index 5234e93c159e2..8ae8e5ecb9832 100644 --- a/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/__tests__/autocomplete.command.stats.test.ts +++ b/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/__tests__/autocomplete.command.stats.test.ts @@ -9,6 +9,7 @@ import { FieldType, FunctionReturnType } from '../../definitions/types'; import { ESQL_COMMON_NUMERIC_TYPES, ESQL_NUMBER_TYPES } from '../../shared/esql_types'; +import { ESQLVariableType } from '../../shared/types'; import { getDateHistogramCompletionItem } from '../commands/stats/util'; import { allStarConstant } from '../complete_items'; import { roundParameterTypes } from './constants'; @@ -357,6 +358,83 @@ describe('autocomplete.suggest', () => { expect(suggestions).toContainEqual(expectedCompletionItem); }); }); + + describe('create control suggestion', () => { + test('suggests `Create control` option', async () => { + const { suggest } = await setup(); + + const suggestions = await suggest('FROM a | STATS BY /', { + callbacks: { + canSuggestVariables: () => true, + getVariablesByType: () => [], + getColumnsFor: () => Promise.resolve([{ name: 'clientip', type: 'ip' }]), + }, + }); + + expect(suggestions).toContainEqual({ + label: 'Create control', + text: '', + kind: 'Issue', + detail: 'Click to create', + command: { id: 'esql.control.fields.create', title: 'Click to create' }, + sortText: '11A', + }); + }); + + test('suggests `?field` option', async () => { + const { suggest } = await setup(); + + const suggestions = await suggest('FROM a | STATS BY /', { + callbacks: { + canSuggestVariables: () => true, + getVariablesByType: () => [ + { + key: 'field', + value: 'clientip', + type: ESQLVariableType.FIELDS, + }, + ], + getColumnsFor: () => Promise.resolve([{ name: 'clientip', type: 'ip' }]), + }, + }); + + expect(suggestions).toContainEqual({ + label: '?field', + text: '?field', + kind: 'Constant', + detail: 'Named parameter', + command: undefined, + sortText: '11A', + }); + }); + + test('suggests `?interval` option', async () => { + const { suggest } = await setup(); + + const suggestions = await suggest('FROM a | STATS BY BUCKET(@timestamp, /)', { + callbacks: { + canSuggestVariables: () => true, + getVariablesByType: () => [ + { + key: 'interval', + value: '1 hour', + type: ESQLVariableType.TIME_LITERAL, + }, + ], + getColumnsFor: () => Promise.resolve([{ name: '@timestamp', type: 'date' }]), + }, + }); + + expect(suggestions).toContainEqual({ + label: '?interval', + text: '?interval', + kind: 'Constant', + detail: 'Named parameter', + command: undefined, + sortText: '1A', + }); + }); + }); }); }); }); diff --git a/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/__tests__/autocomplete.command.where.test.ts b/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/__tests__/autocomplete.command.where.test.ts index 3931480d739a4..30a6b0b9498db 100644 --- a/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/__tests__/autocomplete.command.where.test.ts +++ b/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/__tests__/autocomplete.command.where.test.ts @@ -8,6 +8,7 @@ */ import { ESQL_COMMON_NUMERIC_TYPES } from '../../shared/esql_types'; +import { ESQLVariableType } from '../../shared/types'; import { pipeCompleteItem } from '../complete_items'; import { getDateLiterals } from '../factories'; import { log10ParameterTypes, powParameterTypes } from './constants'; @@ -330,5 +331,57 @@ describe('WHERE ', () => { }) ); }); + + describe('create control suggestion', () => { + test('suggests `Create control` option', async () => { + const { suggest } = await setup(); + + const suggestions = await suggest('FROM a | WHERE agent.name == /', { + callbacks: { + canSuggestVariables: () => true, + getVariablesByType: () => [], + getColumnsFor: () => Promise.resolve([{ name: 'agent.name', type: 'keyword' }]), + }, + }); + + expect(suggestions).toContainEqual({ + label: 'Create control', + text: '', + kind: 'Issue', + detail: 'Click to create', + command: { id: 'esql.control.values.create', title: 'Click to create' }, + sortText: '11A', + rangeToReplace: { start: 31, end: 31 }, + }); + }); + + test('suggests `?value` option', async () => { + const { suggest } = await setup(); + + const suggestions = await suggest('FROM a | WHERE agent.name == /', { + callbacks: { + canSuggestVariables: () => true, + getVariablesByType: () => [ + { + key: 'value', + value: 'java', + type: ESQLVariableType.VALUES, + }, + ], + getColumnsFor: () => Promise.resolve([{ name: 'agent.name', type: 'keyword' }]), + }, + }); + + expect(suggestions).toContainEqual({ + label: '?value', + text: '?value', + kind: 'Constant', + detail: 'Named parameter', + command: undefined, + sortText: '11A', + rangeToReplace: { start: 31, end: 31 }, + }); + }); + }); }); }); diff --git a/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/__tests__/autocomplete.suggest.eval.test.ts b/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/__tests__/autocomplete.suggest.eval.test.ts index e81e74427b721..42ce93571c19a 100644 --- a/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/__tests__/autocomplete.suggest.eval.test.ts +++ b/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/__tests__/autocomplete.suggest.eval.test.ts @@ -147,25 +147,37 @@ describe('autocomplete.suggest', () => { '| ', ...getFunctionSignaturesByReturnType('eval', 'any', { builtin: true, skipAssign: true }, [ 'double', + 'long', ]), + 'IN $0', + 'IS NOT NULL', + 'IS NULL', ]); await assertSuggestions( 'from a | eval a=round(doubleField, /', [ - ...getFieldNamesByType('integer'), - ...getFunctionSignaturesByReturnType('eval', 'integer', { scalar: true }, undefined, [ - 'round', - ]), + ...getFieldNamesByType(['integer', 'long']), + ...getFunctionSignaturesByReturnType( + 'eval', + ['integer', 'long'], + { scalar: true }, + undefined, + ['round'] + ), ], { triggerCharacter: '(' } ); await assertSuggestions( 'from a | eval round(doubleField, /', [ - ...getFieldNamesByType('integer'), - ...getFunctionSignaturesByReturnType('eval', 'integer', { scalar: true }, undefined, [ - 'round', - ]), + ...getFieldNamesByType(['integer', 'long']), + ...getFunctionSignaturesByReturnType( + 'eval', + ['integer', 'long'], + { scalar: true }, + undefined, + ['round'] + ), ], { triggerCharacter: '(' } ); diff --git a/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/autocomplete.test.ts b/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/autocomplete.test.ts index 1e714091eeefe..22b3c8bee9107 100644 --- a/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/autocomplete.test.ts +++ b/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/autocomplete.test.ts @@ -472,11 +472,13 @@ describe('autocomplete', () => { const expectedDateDiff2ndArgSuggestions = [ TIME_PICKER_SUGGESTION, ...TIME_SYSTEM_PARAMS.map((t) => `${t}, `), - ...getFieldNamesByType('date').map((name) => `${name}, `), - ...getFunctionSignaturesByReturnType('eval', 'date', { scalar: true }).map((s) => ({ - ...s, - text: `${s.text},`, - })), + ...getFieldNamesByType(['date', 'date_nanos']).map((name) => `${name}, `), + ...getFunctionSignaturesByReturnType('eval', ['date', 'date_nanos'], { scalar: true }).map( + (s) => ({ + ...s, + text: `${s.text},`, + }) + ), ]; testSuggestions('FROM a | EVAL DATE_DIFF("day", /)', expectedDateDiff2ndArgSuggestions); diff --git a/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/autocomplete.ts b/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/autocomplete.ts index 5e4140e407c9a..596efa7fb8677 100644 --- a/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/autocomplete.ts +++ b/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/autocomplete.ts @@ -89,7 +89,12 @@ import { getPolicyHelper, getSourcesHelper, } from '../shared/resources_helpers'; -import { ESQLCallbacks, ESQLSourceResult } from '../shared/types'; +import type { + ESQLCallbacks, + ESQLSourceResult, + ESQLControlVariable, + ESQLVariableType, +} from '../shared/types'; import { getFunctionsToIgnoreForStats, getQueryForFields, @@ -176,6 +181,8 @@ export async function suggest( queryForFields.replace(EDITOR_MARKER, ''), resourceRetriever ); + const supportsControls = resourceRetriever?.canSuggestVariables?.() ?? false; + const getVariablesByType = resourceRetriever?.getVariablesByType; const getSources = getSourcesHelper(resourceRetriever); const { getPolicies, getPolicyMetadata } = getPolicyRetriever(resourceRetriever); @@ -258,9 +265,10 @@ export async function suggest( astContext, getFieldsByType, getFieldsMap, - getPolicyMetadata, fullText, - offset + offset, + getVariablesByType, + supportsControls ); } if (astContext.type === 'list') { @@ -281,14 +289,20 @@ export function getFieldsByTypeRetriever( resourceRetriever?: ESQLCallbacks ): { getFieldsByType: GetColumnsByTypeFn; getFieldsMap: GetFieldsMapFn } { const helpers = getFieldsByTypeHelper(queryString, resourceRetriever); + const getVariablesByType = resourceRetriever?.getVariablesByType; + const supportsControls = resourceRetriever?.canSuggestVariables?.() ?? false; return { getFieldsByType: async ( expectedType: string | string[] = 'any', ignored: string[] = [], options ) => { + const updatedOptions = { + ...options, + supportsControls, + }; const fields = await helpers.getFieldsByType(expectedType, ignored); - return buildFieldsDefinitionsWithMetadata(fields, options); + return buildFieldsDefinitionsWithMetadata(fields, updatedOptions, getVariablesByType); }, getFieldsMap: helpers.getFieldsMap, }; @@ -1041,9 +1055,10 @@ async function getFunctionArgsSuggestions( }, getFieldsByType: GetColumnsByTypeFn, getFieldsMap: GetFieldsMapFn, - getPolicyMetadata: GetPolicyMetadataFn, fullText: string, - offset: number + offset: number, + getVariablesByType?: (type: ESQLVariableType) => ESQLControlVariable[] | undefined, + supportsControls?: boolean ): Promise { const fnDefinition = getFunctionDefinition(node.name); // early exit on no hit @@ -1165,7 +1180,12 @@ async function getFunctionArgsSuggestions( command.name, getTypesFromParamDefs(constantOnlyParamDefs) as string[], undefined, - { addComma: shouldAddComma, advanceCursorAndOpenSuggestions: hasMoreMandatoryArgs } + { + addComma: shouldAddComma, + advanceCursorAndOpenSuggestions: hasMoreMandatoryArgs, + supportsControls, + }, + getVariablesByType ) ); diff --git a/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/factories.ts b/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/factories.ts index 030c02ad1b81a..6df06d613d206 100644 --- a/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/factories.ts +++ b/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/factories.ts @@ -26,8 +26,10 @@ import { buildFunctionDocumentation } from './documentation_util'; import { DOUBLE_BACKTICK, SINGLE_TICK_REGEX } from '../shared/constants'; import { ESQLRealField } from '../validation/types'; import { isNumericType } from '../shared/esql_types'; +import type { ESQLControlVariable } from '../shared/types'; import { getTestFunctions } from '../shared/test_functions'; import { builtinFunctions } from '../definitions/builtin'; +import { ESQLVariableType } from '../shared/types'; const techPreviewLabel = i18n.translate( 'kbn-esql-validation-autocomplete.esql.autocomplete.techPreviewLabel', @@ -194,9 +196,16 @@ export const getSuggestionsAfterNot = (): SuggestionRawDefinition[] => { export const buildFieldsDefinitionsWithMetadata = ( fields: ESQLRealField[], - options?: { advanceCursor?: boolean; openSuggestions?: boolean; addComma?: boolean } + options?: { + advanceCursor?: boolean; + openSuggestions?: boolean; + addComma?: boolean; + variableType?: ESQLVariableType; + supportsControls?: boolean; + }, + getVariablesByType?: (type: ESQLVariableType) => ESQLControlVariable[] | undefined ): SuggestionRawDefinition[] => { - return fields.map((field) => { + const fieldsSuggestions = fields.map((field) => { const titleCaseType = field.type.charAt(0).toUpperCase() + field.type.slice(1); return { label: field.name, @@ -210,7 +219,23 @@ export const buildFieldsDefinitionsWithMetadata = ( sortText: field.isEcs ? '1D' : 'D', command: options?.openSuggestions ? TRIGGER_SUGGESTION_COMMAND : undefined, }; - }); + }) as SuggestionRawDefinition[]; + + const suggestions = [...fieldsSuggestions]; + if (options?.supportsControls) { + const variableType = options?.variableType ?? ESQLVariableType.FIELDS; + const variables = getVariablesByType?.(variableType) ?? []; + + const controlSuggestions = fields.length + ? getControlSuggestion( + variableType, + variables?.map((v) => `?${v.key}`) + ) + : []; + suggestions.push(...controlSuggestions); + } + + return [...suggestions]; }; export const buildFieldsDefinitions = (fields: string[]): SuggestionRawDefinition[] => { @@ -436,7 +461,12 @@ export function getCompatibleLiterals( commandName: string, types: string[], names?: string[], - options?: { advanceCursorAndOpenSuggestions?: boolean; addComma?: boolean } + options?: { + advanceCursorAndOpenSuggestions?: boolean; + addComma?: boolean; + supportsControls?: boolean; + }, + getVariablesByType?: (type: ESQLVariableType) => ESQLControlVariable[] | undefined ) { const suggestions: SuggestionRawDefinition[] = []; if (types.some(isNumericType)) { @@ -450,10 +480,20 @@ export function getCompatibleLiterals( } } if (types.includes('time_literal')) { + const timeLiteralSuggestions = [ + ...buildConstantsDefinitions(getUnitDuration(1), undefined, undefined, options), + ]; + if (options?.supportsControls) { + const variables = getVariablesByType?.(ESQLVariableType.TIME_LITERAL) ?? []; + timeLiteralSuggestions.push( + ...getControlSuggestion( + ESQLVariableType.TIME_LITERAL, + variables.map((v) => `?${v.key}`) + ) + ); + } // filter plural for now and suggest only unit + singular - suggestions.push( - ...buildConstantsDefinitions(getUnitDuration(1), undefined, undefined, options) - ); // i.e. 1 year + suggestions.push(...timeLiteralSuggestions); // i.e. 1 year } // this is a special type built from the suggestion system, not inherited from the AST if (types.includes('time_literal_unit')) { @@ -543,3 +583,49 @@ export function getDateLiterals(options?: { } as SuggestionRawDefinition, ]; } + +export function getControlSuggestion( + type: ESQLVariableType, + variables?: string[] +): SuggestionRawDefinition[] { + return [ + { + label: i18n.translate( + 'kbn-esql-validation-autocomplete.esql.autocomplete.createControlLabel', + { + defaultMessage: 'Create control', + } + ), + text: '', + kind: 'Issue', + detail: i18n.translate( + 'kbn-esql-validation-autocomplete.esql.autocomplete.createControlDetailLabel', + { + defaultMessage: 'Click to create', + } + ), + sortText: '1A', + command: { + id: `esql.control.${type}.create`, + title: i18n.translate( + 'kbn-esql-validation-autocomplete.esql.autocomplete.createControlDetailLabel', + { + defaultMessage: 'Click to create', + } + ), + }, + } as SuggestionRawDefinition, + ...(variables?.length + ? buildConstantsDefinitions( + variables, + i18n.translate( + 'kbn-esql-validation-autocomplete.esql.autocomplete.namedParamDefinition', + { + defaultMessage: 'Named parameter', + } + ), + '1A' + ) + : []), + ]; +} diff --git a/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/helper.ts b/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/helper.ts index 2fa1ce943cd33..716d3d8bb3250 100644 --- a/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/helper.ts +++ b/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/helper.ts @@ -48,6 +48,7 @@ import { EDITOR_MARKER } from '../shared/constants'; import { ESQLRealField, ESQLVariable, ReferenceMaps } from '../validation/types'; import { listCompleteItem } from './complete_items'; import { removeMarkerArgFromArgsList } from '../shared/context'; +import { ESQLVariableType } from '../shared/types'; function extractFunctionArgs(args: ESQLAstItem[]): ESQLFunction[] { return args.flatMap((arg) => (isAssignment(arg) ? arg.args[1] : arg)).filter(isFunctionItem); @@ -367,12 +368,14 @@ export async function getFieldsOrFunctionsSuggestions( functions, fields, variables, + values = false, literals = false, }: { functions: boolean; fields: boolean; variables?: Map; literals?: boolean; + values?: boolean; }, { ignoreFn = [], @@ -387,6 +390,7 @@ export async function getFieldsOrFunctionsSuggestions( ? getFieldsByType(types, ignoreColumns, { advanceCursor: commandName === 'sort', openSuggestions: commandName === 'sort', + variableType: values ? ESQLVariableType.VALUES : ESQLVariableType.FIELDS, }) : [])) as SuggestionRawDefinition[], functions @@ -617,6 +621,7 @@ export async function getSuggestionsToRightOfOperatorExpression({ { functions: true, fields: true, + values: Boolean(operator.subtype === 'binary-expression'), } )) ); diff --git a/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/types.ts b/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/types.ts index cbd6ead535932..c7b8396beaf6e 100644 --- a/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/types.ts +++ b/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/autocomplete/types.ts @@ -6,6 +6,7 @@ * your election, the "Elastic License 2.0", the "GNU Affero General Public * License v3.0 only", or the "Server Side Public License, v 1". */ +import type { ESQLVariableType } from '../shared/types'; // This is a subset of the Monaco's editor CompletitionItemKind type export type ItemKind = @@ -84,5 +85,10 @@ export interface EditorContext { export type GetColumnsByTypeFn = ( type: string | string[], ignored?: string[], - options?: { advanceCursor?: boolean; openSuggestions?: boolean; addComma?: boolean } + options?: { + advanceCursor?: boolean; + openSuggestions?: boolean; + addComma?: boolean; + variableType?: ESQLVariableType; + } ) => Promise; diff --git a/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/definitions/generated/scalar_functions.ts b/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/definitions/generated/scalar_functions.ts index 87623f9bb0917..365be18528456 100644 --- a/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/definitions/generated/scalar_functions.ts +++ b/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/definitions/generated/scalar_functions.ts @@ -1374,6 +1374,66 @@ const dateDiffDefinition: FunctionDefinition = { ], returnType: 'integer', }, + { + params: [ + { + name: 'unit', + type: 'keyword', + optional: false, + }, + { + name: 'startTimestamp', + type: 'date', + optional: false, + }, + { + name: 'endTimestamp', + type: 'date_nanos', + optional: false, + }, + ], + returnType: 'integer', + }, + { + params: [ + { + name: 'unit', + type: 'keyword', + optional: false, + }, + { + name: 'startTimestamp', + type: 'date_nanos', + optional: false, + }, + { + name: 'endTimestamp', + type: 'date', + optional: false, + }, + ], + returnType: 'integer', + }, + { + params: [ + { + name: 'unit', + type: 'keyword', + optional: false, + }, + { + name: 'startTimestamp', + type: 'date_nanos', + optional: false, + }, + { + name: 'endTimestamp', + type: 'date_nanos', + optional: false, + }, + ], + returnType: 'integer', + }, { params: [ { @@ -1394,6 +1454,66 @@ const dateDiffDefinition: FunctionDefinition = { ], returnType: 'integer', }, + { + params: [ + { + name: 'unit', + type: 'text', + optional: false, + }, + { + name: 'startTimestamp', + type: 'date', + optional: false, + }, + { + name: 'endTimestamp', + type: 'date_nanos', + optional: false, + }, + ], + returnType: 'integer', + }, + { + params: [ + { + name: 'unit', + type: 'text', + optional: false, + }, + { + name: 'startTimestamp', + type: 'date_nanos', + optional: false, + }, + { + name: 'endTimestamp', + type: 'date', + optional: false, + }, + ], + returnType: 'integer', + }, + { + params: [ + { + name: 'unit', + type: 'text', + optional: false, + }, + { + name: 'startTimestamp', + type: 'date_nanos', + optional: false, + }, + { + name: 'endTimestamp', + type: 'date_nanos', + optional: false, + }, + ], + returnType: 'integer', + }, ], supportedCommands: ['stats', 'inlinestats', 'metrics', 'eval', 'where', 'row', 'sort'], supportedOptions: ['by'], @@ -1496,6 +1616,26 @@ const dateFormatDefinition: FunctionDefinition = { preview: false, alias: undefined, signatures: [ + { + params: [ + { + name: 'dateFormat', + type: 'date', + optional: true, + }, + ], + returnType: 'keyword', + }, + { + params: [ + { + name: 'dateFormat', + type: 'date_nanos', + optional: true, + }, + ], + returnType: 'keyword', + }, { params: [ { @@ -1511,6 +1651,21 @@ const dateFormatDefinition: FunctionDefinition = { ], returnType: 'keyword', }, + { + params: [ + { + name: 'dateFormat', + type: 'keyword', + optional: true, + }, + { + name: 'date', + type: 'date_nanos', + optional: false, + }, + ], + returnType: 'keyword', + }, { params: [ { @@ -1526,6 +1681,21 @@ const dateFormatDefinition: FunctionDefinition = { ], returnType: 'keyword', }, + { + params: [ + { + name: 'dateFormat', + type: 'text', + optional: true, + }, + { + name: 'date', + type: 'date_nanos', + optional: false, + }, + ], + returnType: 'keyword', + }, ], supportedCommands: ['stats', 'inlinestats', 'metrics', 'eval', 'where', 'row', 'sort'], supportedOptions: ['by'], @@ -3524,7 +3694,7 @@ const matchDefinition: FunctionDefinition = { name: 'match', description: i18n.translate('kbn-esql-validation-autocomplete.esql.definitions.match', { defaultMessage: - 'Use `MATCH` to perform a match query on the specified field.\nUsing `MATCH` is equivalent to using the `match` query in the Elasticsearch Query DSL.\n\nMatch can be used on text fields, as well as other field types like boolean, dates, and numeric types.\n\nFor a simplified syntax, you can use the match operator `:` operator instead of `MATCH`.\n\n`MATCH` returns true if the provided query matches the row.', + 'Use `MATCH` to perform a match query on the specified field.\nUsing `MATCH` is equivalent to using the `match` query in the Elasticsearch Query DSL.\n\nMatch can be used on fields from the text family like text and semantic_text,\nas well as other field types like keyword, boolean, dates, and numeric types.\n\nFor a simplified syntax, you can use the match operator `:` operator instead of `MATCH`.\n\n`MATCH` returns true if the provided query matches the row.', }), preview: true, alias: undefined, @@ -4111,6 +4281,21 @@ const mvAppendDefinition: FunctionDefinition = { ], returnType: 'date', }, + { + params: [ + { + name: 'field1', + type: 'date_nanos', + optional: false, + }, + { + name: 'field2', + type: 'date_nanos', + optional: false, + }, + ], + returnType: 'date_nanos', + }, { params: [ { @@ -4201,6 +4386,21 @@ const mvAppendDefinition: FunctionDefinition = { ], returnType: 'keyword', }, + { + params: [ + { + name: 'field1', + type: 'keyword', + optional: false, + }, + { + name: 'field2', + type: 'text', + optional: false, + }, + ], + returnType: 'keyword', + }, { params: [ { @@ -4216,6 +4416,21 @@ const mvAppendDefinition: FunctionDefinition = { ], returnType: 'long', }, + { + params: [ + { + name: 'field1', + type: 'text', + optional: false, + }, + { + name: 'field2', + type: 'keyword', + optional: false, + }, + ], + returnType: 'keyword', + }, { params: [ { @@ -4231,6 +4446,21 @@ const mvAppendDefinition: FunctionDefinition = { ], returnType: 'keyword', }, + { + params: [ + { + name: 'field1', + type: 'unsigned_long', + optional: false, + }, + { + name: 'field2', + type: 'unsigned_long', + optional: false, + }, + ], + returnType: 'unsigned_long', + }, { params: [ { @@ -4700,6 +4930,16 @@ const mvDedupeDefinition: FunctionDefinition = { ], returnType: 'keyword', }, + { + params: [ + { + name: 'field', + type: 'unsigned_long', + optional: false, + }, + ], + returnType: 'unsigned_long', + }, { params: [ { @@ -5903,6 +6143,26 @@ const mvSliceDefinition: FunctionDefinition = { ], returnType: 'keyword', }, + { + params: [ + { + name: 'field', + type: 'unsigned_long', + optional: false, + }, + { + name: 'start', + type: 'integer', + optional: false, + }, + { + name: 'end', + type: 'integer', + optional: true, + }, + ], + returnType: 'unsigned_long', + }, { params: [ { @@ -7104,6 +7364,21 @@ const roundDefinition: FunctionDefinition = { ], returnType: 'double', }, + { + params: [ + { + name: 'number', + type: 'double', + optional: false, + }, + { + name: 'decimals', + type: 'long', + optional: true, + }, + ], + returnType: 'double', + }, { params: [ { @@ -7129,6 +7404,21 @@ const roundDefinition: FunctionDefinition = { ], returnType: 'integer', }, + { + params: [ + { + name: 'number', + type: 'integer', + optional: false, + }, + { + name: 'decimals', + type: 'long', + optional: true, + }, + ], + returnType: 'integer', + }, { params: [ { @@ -7154,6 +7444,46 @@ const roundDefinition: FunctionDefinition = { ], returnType: 'long', }, + { + params: [ + { + name: 'number', + type: 'long', + optional: false, + }, + { + name: 'decimals', + type: 'long', + optional: true, + }, + ], + returnType: 'long', + }, + { + params: [ + { + name: 'number', + type: 'unsigned_long', + optional: false, + }, + ], + returnType: 'unsigned_long', + }, + { + params: [ + { + name: 'number', + type: 'unsigned_long', + optional: false, + }, + { + name: 'decimals', + type: 'integer', + optional: true, + }, + ], + returnType: 'unsigned_long', + }, { params: [ { @@ -7161,6 +7491,11 @@ const roundDefinition: FunctionDefinition = { type: 'unsigned_long', optional: false, }, + { + name: 'decimals', + type: 'long', + optional: true, + }, ], returnType: 'unsigned_long', }, @@ -9216,7 +9551,7 @@ const toDateNanosDefinition: FunctionDefinition = { description: i18n.translate('kbn-esql-validation-autocomplete.esql.definitions.to_date_nanos', { defaultMessage: 'Converts an input to a nanosecond-resolution date value (aka date_nanos).', }), - preview: true, + preview: false, alias: undefined, signatures: [ { diff --git a/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/shared/helpers.ts b/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/shared/helpers.ts index 92ac10cb1c456..b877839fab42d 100644 --- a/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/shared/helpers.ts +++ b/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/shared/helpers.ts @@ -414,8 +414,8 @@ export function getAllArrayTypes( return types; } -export function inKnownTimeInterval(item: ESQLTimeInterval): boolean { - return timeUnits.some((unit) => unit === item.unit.toLowerCase()); +export function inKnownTimeInterval(timeIntervalUnit: string): boolean { + return timeUnits.some((unit) => unit === timeIntervalUnit.toLowerCase()); } /** @@ -464,7 +464,7 @@ export function checkFunctionArgMatchesDefinition( } } if (arg.type === 'timeInterval') { - return argType === 'time_literal' && inKnownTimeInterval(arg); + return argType === 'time_literal' && inKnownTimeInterval(arg.unit); } if (arg.type === 'column') { const hit = getColumnForASTNode(arg, references); diff --git a/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/shared/types.ts b/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/shared/types.ts index 5ff9285517b07..ca91a5df2996a 100644 --- a/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/shared/types.ts +++ b/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/shared/types.ts @@ -6,7 +6,6 @@ * your election, the "Elastic License 2.0", the "GNU Affero General Public * License v3.0 only", or the "Server Side Public License, v 1". */ - import type { ESQLRealField, JoinIndexAutocompleteItem } from '../validation/types'; /** @internal **/ @@ -37,6 +36,18 @@ export interface ESQLSourceResult { type?: string; } +export interface ESQLControlVariable { + key: string; + value: string | number; + type: ESQLVariableType; +} + +export enum ESQLVariableType { + TIME_LITERAL = 'time_literal', + FIELDS = 'fields', + VALUES = 'values', +} + export interface ESQLCallbacks { getSources?: CallbackFn<{}, ESQLSourceResult>; getColumnsFor?: CallbackFn<{ query: string }, ESQLRealField>; @@ -46,6 +57,8 @@ export interface ESQLCallbacks { >; getPreferences?: () => Promise<{ histogramBarTarget: number }>; getFieldsMetadata?: Promise; + getVariablesByType?: (type: ESQLVariableType) => ESQLControlVariable[] | undefined; + canSuggestVariables?: () => boolean; getJoinIndices?: () => Promise<{ indices: JoinIndexAutocompleteItem[] }>; } diff --git a/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/validation/validation.test.ts b/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/validation/validation.test.ts index 7da2d74a29fc6..c83ae10a8d3e7 100644 --- a/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/validation/validation.test.ts +++ b/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/validation/validation.test.ts @@ -1730,6 +1730,8 @@ describe('validation logic', () => { getColumnsFor: /Unknown column|Argument of|it is unsupported or not indexed/, getPreferences: /Unknown/, getFieldsMetadata: /Unknown/, + getVariablesByType: /Unknown/, + canSuggestVariables: /Unknown/, }; return excludedCallback.map((callback) => (contentByCallback as any)[callback]) || []; } diff --git a/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/validation/validation.ts b/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/validation/validation.ts index 1c3491b308cf7..423e85e297251 100644 --- a/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/validation/validation.ts +++ b/src/platform/packages/shared/kbn-esql-validation-autocomplete/src/validation/validation.ts @@ -138,7 +138,7 @@ function validateFunctionLiteralArg( } if (isTimeIntervalItem(actualArg)) { // check first if it's a valid interval string - if (!inKnownTimeInterval(actualArg)) { + if (!inKnownTimeInterval(actualArg.unit)) { messages.push( getMessageFromId({ messageId: 'unknownInterval', @@ -1327,6 +1327,8 @@ export const ignoreErrorsMap: Record = { getPolicies: ['unknownPolicy'], getPreferences: [], getFieldsMetadata: [], + getVariablesByType: [], + canSuggestVariables: [], getJoinIndices: [], }; diff --git a/src/platform/packages/shared/kbn-esql-variables-types/README.md b/src/platform/packages/shared/kbn-esql-variables-types/README.md new file mode 100644 index 0000000000000..681bab7815a07 --- /dev/null +++ b/src/platform/packages/shared/kbn-esql-variables-types/README.md @@ -0,0 +1,3 @@ +# @kbn/esql-variables-types + +This package contains types important for the ES|QL variables. diff --git a/src/platform/packages/shared/kbn-esql-variables-types/index.ts b/src/platform/packages/shared/kbn-esql-variables-types/index.ts new file mode 100644 index 0000000000000..d43582602e0fe --- /dev/null +++ b/src/platform/packages/shared/kbn-esql-variables-types/index.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", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import { ESQLControlVariable } from '@kbn/esql-validation-autocomplete'; +import { PublishingSubject } from '@kbn/presentation-publishing'; + +/** + * This should all be moved into a package and reorganized into separate files etc + */ + +export interface PublishesESQLVariable { + esqlVariable$: PublishingSubject; +} + +export const apiPublishesESQLVariable = ( + unknownApi: unknown +): unknownApi is PublishesESQLVariable => { + return Boolean(unknownApi && (unknownApi as PublishesESQLVariable)?.esqlVariable$ !== undefined); +}; + +export interface PublishesESQLVariables { + esqlVariables$: PublishingSubject; +} + +export const apiPublishesESQLVariables = ( + unknownApi: unknown +): unknownApi is PublishesESQLVariables => { + return Boolean( + unknownApi && (unknownApi as PublishesESQLVariables)?.esqlVariables$ !== undefined + ); +}; diff --git a/src/platform/packages/shared/kbn-esql-variables-types/kibana.jsonc b/src/platform/packages/shared/kbn-esql-variables-types/kibana.jsonc new file mode 100644 index 0000000000000..7bbcf074645c1 --- /dev/null +++ b/src/platform/packages/shared/kbn-esql-variables-types/kibana.jsonc @@ -0,0 +1,9 @@ +{ + "type": "shared-browser", + "id": "@kbn/esql-variables-types", + "owner": [ + "@elastic/kibana-esql", + ], + "group": "platform", + "visibility": "shared" +} \ No newline at end of file diff --git a/src/platform/packages/shared/kbn-esql-variables-types/package.json b/src/platform/packages/shared/kbn-esql-variables-types/package.json new file mode 100644 index 0000000000000..743099b750ff3 --- /dev/null +++ b/src/platform/packages/shared/kbn-esql-variables-types/package.json @@ -0,0 +1,7 @@ +{ + "name": "@kbn/esql-variables-types", + "private": true, + "version": "1.0.0", + "author": "Kibana ES|QL", + "license": "Elastic License 2.0 OR AGPL-3.0-only OR SSPL-1.0" +} \ No newline at end of file diff --git a/src/platform/packages/shared/kbn-esql-variables-types/tsconfig.json b/src/platform/packages/shared/kbn-esql-variables-types/tsconfig.json new file mode 100644 index 0000000000000..242fd33180e6a --- /dev/null +++ b/src/platform/packages/shared/kbn-esql-variables-types/tsconfig.json @@ -0,0 +1,20 @@ +{ + "extends": "../../../../../tsconfig.base.json", + "compilerOptions": { + "outDir": "target/types", + "types": [ + "jest", + "node" + ] + }, + "include": [ + "**/*.ts", + ], + "exclude": [ + "target/**/*", + ], + "kbn_references": [ + "@kbn/esql-validation-autocomplete", + "@kbn/presentation-publishing", + ] +} diff --git a/src/platform/packages/shared/response-ops/rule_params/common/constants.ts b/src/platform/packages/shared/response-ops/rule_params/common/constants.ts new file mode 100644 index 0000000000000..adf8b309664ce --- /dev/null +++ b/src/platform/packages/shared/response-ops/rule_params/common/constants.ts @@ -0,0 +1,38 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +/** + * Max length for the custom field description + */ +export const MAX_DATA_VIEW_FIELD_DESCRIPTION_LENGTH = 300; + +/** + * All runtime field types. + * @public + */ +export const RUNTIME_FIELD_TYPES = [ + 'keyword', + 'long', + 'double', + 'date', + 'ip', + 'boolean', + 'geo_point', + 'composite', +] as const; + +export const RUNTIME_FIELD_TYPES2 = [ + 'keyword', + 'long', + 'double', + 'date', + 'ip', + 'boolean', + 'geo_point', +] as const; diff --git a/src/platform/packages/shared/response-ops/rule_params/common/data_view_spec_schema.ts b/src/platform/packages/shared/response-ops/rule_params/common/data_view_spec_schema.ts new file mode 100644 index 0000000000000..88fd0ff91e417 --- /dev/null +++ b/src/platform/packages/shared/response-ops/rule_params/common/data_view_spec_schema.ts @@ -0,0 +1,184 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import { schema, Type } from '@kbn/config-schema'; +import { + MAX_DATA_VIEW_FIELD_DESCRIPTION_LENGTH, + RUNTIME_FIELD_TYPES, + RUNTIME_FIELD_TYPES2, +} from './constants'; + +/** + * Runtime field types + */ +type RuntimeType = (typeof RUNTIME_FIELD_TYPES)[number]; + +const serializedFieldFormatSchema = schema.object({ + id: schema.maybe(schema.string()), + params: schema.maybe(schema.any()), +}); + +const runtimeFieldNonCompositeFieldsSpecTypeSchema = schema.oneOf( + RUNTIME_FIELD_TYPES2.map((runtimeFieldType) => schema.literal(runtimeFieldType)) as [ + Type + ] +); + +const primitiveRuntimeFieldSchemaShared = { + script: schema.maybe( + schema.object({ + source: schema.string(), + }) + ), + format: schema.maybe(serializedFieldFormatSchema), + customLabel: schema.maybe(schema.string()), + customDescription: schema.maybe( + schema.string({ + maxLength: MAX_DATA_VIEW_FIELD_DESCRIPTION_LENGTH, + }) + ), + popularity: schema.maybe( + schema.number({ + min: 0, + }) + ), +}; + +const primitiveRuntimeFieldSchema = schema.object({ + type: runtimeFieldNonCompositeFieldsSpecTypeSchema, + ...primitiveRuntimeFieldSchemaShared, +}); + +const compositeRuntimeFieldSchemaShared = { + script: schema.maybe( + schema.object({ + source: schema.string(), + }) + ), + fields: schema.maybe( + schema.recordOf( + schema.string(), + schema.object({ + type: runtimeFieldNonCompositeFieldsSpecTypeSchema, + format: schema.maybe(serializedFieldFormatSchema), + customLabel: schema.maybe(schema.string()), + customDescription: schema.maybe( + schema.string({ + maxLength: MAX_DATA_VIEW_FIELD_DESCRIPTION_LENGTH, + }) + ), + popularity: schema.maybe( + schema.number({ + min: 0, + }) + ), + }) + ) + ), +}; + +const compositeRuntimeFieldSchema = schema.object({ + type: schema.literal('composite') as Type, + ...compositeRuntimeFieldSchemaShared, +}); + +const runtimeFieldSchema = schema.oneOf([primitiveRuntimeFieldSchema, compositeRuntimeFieldSchema]); + +const fieldSpecSchemaFields = { + name: schema.string({ + maxLength: 1000, + }), + type: schema.string({ + defaultValue: 'string', + maxLength: 1000, + }), + count: schema.maybe( + schema.number({ + min: 0, + }) + ), + script: schema.maybe( + schema.string({ + maxLength: 1000000, + }) + ), + format: schema.maybe(serializedFieldFormatSchema), + esTypes: schema.maybe(schema.arrayOf(schema.string())), + scripted: schema.maybe(schema.boolean()), + subType: schema.maybe( + schema.object({ + multi: schema.maybe( + schema.object({ + parent: schema.string(), + }) + ), + nested: schema.maybe( + schema.object({ + path: schema.string(), + }) + ), + }) + ), + customLabel: schema.maybe(schema.string()), + customDescription: schema.maybe( + schema.string({ + maxLength: MAX_DATA_VIEW_FIELD_DESCRIPTION_LENGTH, + }) + ), + shortDotsEnable: schema.maybe(schema.boolean()), + searchable: schema.maybe(schema.boolean()), + aggregatable: schema.maybe(schema.boolean()), + readFromDocValues: schema.maybe(schema.boolean()), + runtimeField: schema.maybe(runtimeFieldSchema), +}; + +const fieldSpecSchema = schema.object(fieldSpecSchemaFields, { + // Allow and ignore unknowns to make fields transient. + // Because `fields` have a bunch of calculated fields + // this allows to retrieve an index pattern and then to re-create by using the retrieved payload + unknowns: 'ignore', +}); + +export const dataViewSpecSchema = schema.object({ + title: schema.string(), + version: schema.maybe(schema.string()), + id: schema.maybe(schema.string()), + type: schema.maybe(schema.string()), + timeFieldName: schema.maybe(schema.string()), + sourceFilters: schema.maybe( + schema.arrayOf( + schema.object({ + value: schema.string(), + clientId: schema.maybe(schema.oneOf([schema.string(), schema.number()])), + }) + ) + ), + fields: schema.maybe(schema.recordOf(schema.string(), fieldSpecSchema)), + typeMeta: schema.maybe(schema.object({}, { unknowns: 'allow' })), + fieldFormats: schema.maybe(schema.recordOf(schema.string(), serializedFieldFormatSchema)), + fieldAttrs: schema.maybe( + schema.recordOf( + schema.string(), + schema.object({ + customLabel: schema.maybe(schema.string()), + customDescription: schema.maybe( + schema.string({ + maxLength: MAX_DATA_VIEW_FIELD_DESCRIPTION_LENGTH, + }) + ), + count: schema.maybe(schema.number()), + }) + ) + ), + allowNoIndex: schema.maybe(schema.boolean()), + runtimeFieldMap: schema.maybe(schema.recordOf(schema.string(), runtimeFieldSchema)), + name: schema.maybe(schema.string()), + namespaces: schema.maybe(schema.arrayOf(schema.string())), + allowHidden: schema.maybe(schema.boolean()), +}); diff --git a/src/platform/packages/shared/response-ops/rule_params/common/index.ts b/src/platform/packages/shared/response-ops/rule_params/common/index.ts index 4eaa2806a1a10..f4b7fd9166c0e 100644 --- a/src/platform/packages/shared/response-ops/rule_params/common/index.ts +++ b/src/platform/packages/shared/response-ops/rule_params/common/index.ts @@ -8,3 +8,4 @@ */ export * from './search_configuration_schema'; +export { dataViewSpecSchema } from './data_view_spec_schema'; diff --git a/src/platform/packages/shared/shared-ux/code_editor/impl/code_editor.tsx b/src/platform/packages/shared/shared-ux/code_editor/impl/code_editor.tsx index e051de07eb47c..fb4e891261426 100644 --- a/src/platform/packages/shared/shared-ux/code_editor/impl/code_editor.tsx +++ b/src/platform/packages/shared/shared-ux/code_editor/impl/code_editor.tsx @@ -28,7 +28,7 @@ import { } from '@kbn/monaco'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; -import { css } from '@emotion/react'; +import { css, Interpolation, Theme } from '@emotion/react'; import { MonacoEditor as ReactMonacoEditor, type MonacoEditorProps as ReactMonacoEditorProps, @@ -157,6 +157,11 @@ export interface CodeEditorProps { enableFindAction?: boolean; dataTestSubj?: string; + + /** + * Custom CSS class to apply to the container + */ + classNameCss?: Interpolation; } export const CodeEditor: React.FC = ({ @@ -189,6 +194,7 @@ export const CodeEditor: React.FC = ({ accessibilityOverlayEnabled = true, enableFindAction, dataTestSubj, + classNameCss, }) => { const { euiTheme } = useEuiTheme(); @@ -490,7 +496,7 @@ export const CodeEditor: React.FC = ({ return (
{ }); const session = inspector.open(adapters, { title: panelTitle, + flyoutType: 'push', options: { fileName: panelTitle, }, @@ -71,6 +73,12 @@ export class InspectPanelAction implements Action { }); // send the overlay ref to the parent API if it is capable of tracking overlays - if (tracksOverlays(embeddable.parentApi)) embeddable.parentApi?.openOverlay(session); + if (tracksOverlays(embeddable.parentApi)) { + const openOverlayOptions = apiHasUniqueId(embeddable) + ? { focusedPanelId: embeddable.uuid } + : undefined; + + embeddable.parentApi?.openOverlay(session, openOverlayOptions); + } } } diff --git a/src/platform/plugins/private/vis_default_editor/public/components/sidebar/sidebar_title.tsx b/src/platform/plugins/private/vis_default_editor/public/components/sidebar/sidebar_title.tsx index 41199116837cb..9d6feb62939c2 100644 --- a/src/platform/plugins/private/vis_default_editor/public/components/sidebar/sidebar_title.tsx +++ b/src/platform/plugins/private/vis_default_editor/public/components/sidebar/sidebar_title.tsx @@ -127,7 +127,7 @@ export function LinkedSearch({ savedSearch, eventEmitter }: LinkedSearchProps) { >

diff --git a/src/platform/plugins/private/vis_types/vega/public/data_model/vega_parser.test.js b/src/platform/plugins/private/vis_types/vega/public/data_model/vega_parser.test.js index 09799f8bac6f4..9fdf08503c4e0 100644 --- a/src/platform/plugins/private/vis_types/vega/public/data_model/vega_parser.test.js +++ b/src/platform/plugins/private/vis_types/vega/public/data_model/vega_parser.test.js @@ -14,6 +14,7 @@ import { TimeCache } from './time_cache'; import { VegaParser } from './vega_parser'; import { bypassExternalUrlCheck } from '../vega_view/vega_base_view'; import { VegaThemeColors } from './utils'; +import { DEFAULT_EMS_DARKMAP_ID } from '@kbn/maps-ems-plugin/common'; jest.mock('../services'); @@ -404,14 +405,14 @@ describe('VegaParser._parseMapConfig', () => { check( { mapStyle: true, - emsTileServiceId: 'dark_map', + emsTileServiceId: DEFAULT_EMS_DARKMAP_ID, }, { delayRepaint: true, latitude: 0, longitude: 0, mapStyle: true, - emsTileServiceId: 'dark_map', + emsTileServiceId: DEFAULT_EMS_DARKMAP_ID, zoomControl: true, scrollWheelZoom: false, }, diff --git a/src/platform/plugins/private/vis_types/vega/public/vega_view/vega_map_view/service_settings/service_settings.test.js b/src/platform/plugins/private/vis_types/vega/public/vega_view/vega_map_view/service_settings/service_settings.test.js index 88d4ef57f84b6..f56670519e843 100644 --- a/src/platform/plugins/private/vis_types/vega/public/vega_view/vega_map_view/service_settings/service_settings.test.js +++ b/src/platform/plugins/private/vis_types/vega/public/vega_view/vega_map_view/service_settings/service_settings.test.js @@ -7,6 +7,11 @@ * License v3.0 only", or the "Server Side Public License, v 1". */ +import { + DEFAULT_EMS_DARKMAP_ID, + DEFAULT_EMS_ROADMAP_DESATURATED_ID, + DEFAULT_EMS_ROADMAP_ID, +} from '@kbn/maps-ems-plugin/common'; import { ServiceSettings } from './service_settings'; function makeMockLayer({ id, min, max, attributions, url }) { @@ -62,21 +67,21 @@ function createMockEMSClient() { getTMSServices() { return [ makeMockLayer({ - id: 'road_map', + id: DEFAULT_EMS_ROADMAP_ID, min: 0, max: 10, attributions: [{ url: 'https://foobar.com', label: 'foobar' }], url: 'https://tiles.foobar/raster/styles/osm-bright/{z}/{x}/{y}.png?elastic_tile_service_tos=agree&my_app_name=kibana&my_app_version=1.2.3&license=sspl', }), makeMockLayer({ - id: 'road_map_desaturated', + id: DEFAULT_EMS_ROADMAP_DESATURATED_ID, min: 0, max: 18, attributions: [{ url: 'https://foobar.com', label: 'foobar' }], url: 'https://tiles.foobar/raster/styles/osm-bright-desaturated/{z}/{x}/{y}.png?elastic_tile_service_tos=agree&my_app_name=kibana&my_app_version=1.2.3&license=sspl', }), makeMockLayer({ - id: 'dark_map', + id: DEFAULT_EMS_DARKMAP_ID, min: 0, max: 22, attributions: [{ url: 'https://foobar.com', label: 'foobar' }], @@ -96,9 +101,9 @@ describe('service_settings (FKA tile_map test)', function () { emsTileApiUrl, includeElasticMapsService: true, emsTileLayerId: { - bright: 'road_map', - desaturated: 'road_map_desaturated', - dark: 'dark_map', + bright: DEFAULT_EMS_ROADMAP_ID, + desaturated: DEFAULT_EMS_ROADMAP_DESATURATED_ID, + dark: DEFAULT_EMS_DARKMAP_ID, }, }; @@ -134,7 +139,7 @@ describe('service_settings (FKA tile_map test)', function () { id: 'TMS in config/kibana.yml', }, { - id: 'road_map', + id: DEFAULT_EMS_ROADMAP_ID, name: 'Road Map - Bright', url: 'https://tiles.foobar/raster/styles/osm-bright/{z}/{x}/{y}.png?elastic_tile_service_tos=agree&my_app_name=kibana&my_app_version=1.2.3&license=sspl', minZoom: 0, @@ -160,7 +165,9 @@ describe('service_settings (FKA tile_map test)', function () { it('should load appropriate EMS attributes for desaturated and dark theme', async () => { serviceSettings = makeServiceSettings(); const tilemapServices = await serviceSettings.getTMSServices(); - const roadMapService = tilemapServices.find((service) => service.id === 'road_map'); + const roadMapService = tilemapServices.find( + (service) => service.id === DEFAULT_EMS_ROADMAP_ID + ); const desaturationFalse = await serviceSettings.getAttributesForTMSLayer( roadMapService, diff --git a/src/platform/plugins/private/vis_types/vega/public/vega_view/vega_map_view/service_settings/service_settings.ts b/src/platform/plugins/private/vis_types/vega/public/vega_view/vega_map_view/service_settings/service_settings.ts index 9cfb4103677bf..13f548d295c5b 100644 --- a/src/platform/plugins/private/vis_types/vega/public/vega_view/vega_map_view/service_settings/service_settings.ts +++ b/src/platform/plugins/private/vis_types/vega/public/vega_view/vega_map_view/service_settings/service_settings.ts @@ -11,6 +11,10 @@ import _ from 'lodash'; import MarkdownIt from 'markdown-it'; import type { EMSClient, FileLayer as EMSFileLayer, TMSService } from '@elastic/ems-client'; import type { MapConfig, TileMapConfig } from '@kbn/maps-ems-plugin/public'; +import { + EMS_DARKMAP_BOREALIS_ID, + EMS_ROADMAP_BOREALIS_DESATURATED_ID, +} from '@kbn/maps-ems-plugin/common'; import type { FileLayer, IServiceSettings, TmsLayer } from './service_settings_types'; import { ORIGIN_LEGACY, TMS_IN_YML_ID } from './service_settings_types'; /** @@ -120,13 +124,18 @@ export class ServiceSettings implements IServiceSettings { return this._emsClient.findTMSServiceById(id); } - async getDefaultTmsLayer(isDarkMode: boolean): Promise { + async getDefaultTmsLayer(isDarkMode: boolean, themeName: string): Promise { const { dark, desaturated } = this._mapConfig.emsTileLayerId; if (hasUserConfiguredTmsLayer(this._mapConfig)) { return TMS_IN_YML_ID; } + // To be removed once Borealis is the only theme available + if (themeName === 'borealis') { + return isDarkMode ? EMS_DARKMAP_BOREALIS_ID : EMS_ROADMAP_BOREALIS_DESATURATED_ID; + } + return isDarkMode ? dark : desaturated; } diff --git a/src/platform/plugins/private/vis_types/vega/public/vega_view/vega_map_view/service_settings/service_settings_types.ts b/src/platform/plugins/private/vis_types/vega/public/vega_view/vega_map_view/service_settings/service_settings_types.ts index b6886bfe92bdd..f4758ed50b802 100644 --- a/src/platform/plugins/private/vis_types/vega/public/vega_view/vega_map_view/service_settings/service_settings_types.ts +++ b/src/platform/plugins/private/vis_types/vega/public/vega_view/vega_map_view/service_settings/service_settings_types.ts @@ -61,7 +61,7 @@ export interface IServiceSettings { isDarkMode: boolean ): any; - getDefaultTmsLayer(isDarkMode: boolean): Promise; + getDefaultTmsLayer(isDarkMode: boolean, themeName: string): Promise; getTmsService(id: string): Promise; getMapConfig(): MapConfig; getTileMapConfig(): TileMapConfig; diff --git a/src/platform/plugins/private/vis_types/vega/public/vega_view/vega_map_view/view.test.ts b/src/platform/plugins/private/vis_types/vega/public/vega_view/vega_map_view/view.test.ts index cf958085bd9fd..da3dd944d537b 100644 --- a/src/platform/plugins/private/vis_types/vega/public/vega_view/vega_map_view/view.test.ts +++ b/src/platform/plugins/private/vis_types/vega/public/vega_view/vega_map_view/view.test.ts @@ -31,6 +31,7 @@ import { import { initVegaLayer, initTmsRasterLayer } from './layers'; import { maplibregl } from '@kbn/mapbox-gl'; +import { DEFAULT_EMS_ROADMAP_DESATURATED_ID } from '@kbn/maps-ems-plugin/common'; jest.mock('@kbn/mapbox-gl', () => { const zoomTo = jest.fn(); @@ -110,7 +111,7 @@ describe('vega_map_view/view', () => { }; }, getDefaultTmsLayer() { - return isUserProvided ? 'TMS in config/kibana.yml' : 'road_map_desaturated'; + return isUserProvided ? 'TMS in config/kibana.yml' : DEFAULT_EMS_ROADMAP_DESATURATED_ID; }, } as unknown as IServiceSettings; }; diff --git a/src/platform/plugins/private/vis_types/vega/public/vega_view/vega_map_view/view.ts b/src/platform/plugins/private/vis_types/vega/public/vega_view/vega_map_view/view.ts index e586427dee14d..d1f0f67174354 100644 --- a/src/platform/plugins/private/vis_types/vega/public/vega_view/vega_map_view/view.ts +++ b/src/platform/plugins/private/vis_types/vega/public/vega_view/vega_map_view/view.ts @@ -99,10 +99,10 @@ export class VegaMapView extends VegaBaseView { const { mapStyle, emsTileServiceId } = this._parser.mapConfig; // if (mapStyle) { - const isDarkMode: boolean = getThemeService().getTheme().darkMode; + const { darkMode, name } = getThemeService().getTheme(); return emsTileServiceId ? emsTileServiceId - : await this._serviceSettings.getDefaultTmsLayer(isDarkMode); + : await this._serviceSettings.getDefaultTmsLayer(darkMode, name); } } diff --git a/src/platform/plugins/shared/controls/common/constants.ts b/src/platform/plugins/shared/controls/common/constants.ts index afd6fe66f0df1..d1f88567a3c6e 100644 --- a/src/platform/plugins/shared/controls/common/constants.ts +++ b/src/platform/plugins/shared/controls/common/constants.ts @@ -30,3 +30,5 @@ export const DEFAULT_AUTO_APPLY_SELECTIONS = true; export const TIME_SLIDER_CONTROL = 'timeSlider'; export const RANGE_SLIDER_CONTROL = 'rangeSliderControl'; export const OPTIONS_LIST_CONTROL = 'optionsListControl'; + +export const ESQL_CONTROL = 'esqlControl'; diff --git a/src/platform/plugins/shared/controls/common/index.ts b/src/platform/plugins/shared/controls/common/index.ts index 031d3b348272f..1fd51fd92be9b 100644 --- a/src/platform/plugins/shared/controls/common/index.ts +++ b/src/platform/plugins/shared/controls/common/index.ts @@ -29,6 +29,7 @@ export { OPTIONS_LIST_CONTROL, RANGE_SLIDER_CONTROL, TIME_SLIDER_CONTROL, + ESQL_CONTROL, } from './constants'; export { CONTROL_GROUP_TYPE } from './control_group'; diff --git a/src/platform/plugins/shared/controls/kibana.jsonc b/src/platform/plugins/shared/controls/kibana.jsonc index 76fb9f7960412..17e6e7c6b55a3 100644 --- a/src/platform/plugins/shared/controls/kibana.jsonc +++ b/src/platform/plugins/shared/controls/kibana.jsonc @@ -17,9 +17,8 @@ "dataViews", "data", "unifiedSearch", - "uiActions" + "uiActions", ], - "requiredBundles": [], "extraPublicDirs": [ "common" ] diff --git a/src/platform/plugins/shared/controls/public/control_group/get_control_group_factory.tsx b/src/platform/plugins/shared/controls/public/control_group/get_control_group_factory.tsx index eea50462ddc11..fa943d2504c44 100644 --- a/src/platform/plugins/shared/controls/public/control_group/get_control_group_factory.tsx +++ b/src/platform/plugins/shared/controls/public/control_group/get_control_group_factory.tsx @@ -7,12 +7,10 @@ * License v3.0 only", or the "Server Side Public License, v 1". */ -import fastIsEqual from 'fast-deep-equal'; -import React, { useEffect } from 'react'; -import { BehaviorSubject } from 'rxjs'; - import { DataView } from '@kbn/data-views-plugin/common'; import { ReactEmbeddableFactory } from '@kbn/embeddable-plugin/public'; +import { ESQLControlVariable } from '@kbn/esql-validation-autocomplete'; +import { PublishesESQLVariable, apiPublishesESQLVariable } from '@kbn/esql-variables-types'; import { i18n } from '@kbn/i18n'; import { apiHasSaveNotification, @@ -24,7 +22,9 @@ import { useBatchedPublishingSubjects, } from '@kbn/presentation-publishing'; import { apiPublishesReload } from '@kbn/presentation-publishing/interfaces/fetch/publishes_reload'; - +import fastIsEqual from 'fast-deep-equal'; +import React, { useEffect } from 'react'; +import { BehaviorSubject } from 'rxjs'; import type { ControlGroupChainingSystem, ControlGroupRuntimeState, @@ -85,6 +85,7 @@ export const getControlGroupEmbeddableFactory = () => { ...controlsManager.api, autoApplySelections$, }); + const esqlVariables$ = new BehaviorSubject([]); const dataViews$ = new BehaviorSubject(undefined); const chainingSystem$ = new BehaviorSubject( chainingSystem ?? DEFAULT_CONTROL_CHAINING @@ -130,6 +131,7 @@ export const getControlGroupEmbeddableFactory = () => { const api = setApi({ ...controlsManager.api, + esqlVariables$, disabledActionIds$, ...unsavedChanges.api, ...selectionsManager.api, @@ -231,6 +233,14 @@ export const getControlGroupEmbeddableFactory = () => { dataViews$.next(newDataViews) ); + /** Combine ESQL variables from all children that publish them. */ + const childrenESQLVariablesSubscription = combineCompatibleChildrenApis< + PublishesESQLVariable, + ESQLControlVariable[] + >(api, 'esqlVariable$', apiPublishesESQLVariable, []).subscribe((newESQLVariables) => { + esqlVariables$.next(newESQLVariables); + }); + const saveNotificationSubscription = apiHasSaveNotification(parentApi) ? parentApi.saveNotification$.subscribe(() => { lastSavedControlsState$.next(controlsManager.snapshotControlsRuntimeState()); @@ -275,6 +285,7 @@ export const getControlGroupEmbeddableFactory = () => { return () => { selectionsManager.cleanup(); childrenDataViewsSubscription.unsubscribe(); + childrenESQLVariablesSubscription.unsubscribe(); saveNotificationSubscription?.unsubscribe(); }; }, []); diff --git a/src/platform/plugins/shared/controls/public/control_group/types.ts b/src/platform/plugins/shared/controls/public/control_group/types.ts index 6453e8b6d4a64..d2c7dafc971d7 100644 --- a/src/platform/plugins/shared/controls/public/control_group/types.ts +++ b/src/platform/plugins/shared/controls/public/control_group/types.ts @@ -10,6 +10,7 @@ import type { Observable } from 'rxjs'; import { DefaultEmbeddableApi } from '@kbn/embeddable-plugin/public'; +import { PublishesESQLVariables } from '@kbn/esql-variables-types'; import { Filter } from '@kbn/es-query'; import { HasSaveNotification, @@ -51,6 +52,7 @@ export type ControlGroupApi = PresentationContainer & DefaultEmbeddableApi & PublishesFilters & PublishesDataViews & + PublishesESQLVariables & HasSerializedChildState & HasEditCapabilities & Pick, 'unsavedChanges$'> & diff --git a/src/platform/plugins/shared/controls/public/controls/esql_control/esql_control_selections.ts b/src/platform/plugins/shared/controls/public/controls/esql_control/esql_control_selections.ts new file mode 100644 index 0000000000000..f30ed60492318 --- /dev/null +++ b/src/platform/plugins/shared/controls/public/controls/esql_control/esql_control_selections.ts @@ -0,0 +1,83 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ +import deepEqual from 'react-fast-compare'; +import { BehaviorSubject, combineLatest } from 'rxjs'; +import { PublishingSubject, StateComparators } from '@kbn/presentation-publishing'; +import { ESQLControlVariable, ESQLVariableType } from '@kbn/esql-validation-autocomplete'; +import type { ESQLControlState } from '@kbn/esql/public'; + +export function initializeESQLControlSelections(initialState: ESQLControlState) { + const availableOptions$ = new BehaviorSubject(initialState.availableOptions ?? []); + const selectedOptions$ = new BehaviorSubject(initialState.selectedOptions ?? []); + const hasSelections$ = new BehaviorSubject(false); // hardcoded to false to prevent clear action from appearing. + const variableName$ = new BehaviorSubject(initialState.variableName ?? ''); + const variableType$ = new BehaviorSubject( + initialState.variableType ?? ESQLVariableType.VALUES + ); + const controlType$ = new BehaviorSubject(initialState.controlType ?? ''); + const esqlQuery$ = new BehaviorSubject(initialState.esqlQuery ?? ''); + const title$ = new BehaviorSubject(initialState.title); + + const selectedOptionsComparatorFunction = (a: string[], b: string[]) => + deepEqual(a ?? [], b ?? []); + + function setSelectedOptions(next: string[]) { + if (!selectedOptionsComparatorFunction(selectedOptions$.value, next)) { + selectedOptions$.next(next); + } + } + + // derive ESQL control variable from state. + const getEsqlVariable = () => ({ + key: variableName$.value, + value: selectedOptions$.value[0], + type: variableType$.value, + }); + const esqlVariable$ = new BehaviorSubject(getEsqlVariable()); + const subscriptions = combineLatest([variableName$, variableType$, selectedOptions$]).subscribe( + () => esqlVariable$.next(getEsqlVariable()) + ); + + return { + cleanup: () => subscriptions.unsubscribe(), + api: { + hasSelections$: hasSelections$ as PublishingSubject, + esqlVariable$: esqlVariable$ as PublishingSubject, + }, + comparators: { + selectedOptions: [selectedOptions$, setSelectedOptions, selectedOptionsComparatorFunction], + availableOptions: [availableOptions$, (next) => availableOptions$.next(next)], + variableName: [variableName$, (next) => variableName$.next(next)], + variableType: [variableType$, (next) => variableType$.next(next)], + controlType: [controlType$, (next) => controlType$.next(next)], + esqlQuery: [esqlQuery$, (next) => esqlQuery$.next(next)], + title: [title$, (next) => title$.next(next)], + } as StateComparators< + Pick< + ESQLControlState, + | 'selectedOptions' + | 'availableOptions' + | 'variableName' + | 'variableType' + | 'controlType' + | 'esqlQuery' + | 'title' + > + >, + hasInitialSelections: initialState.selectedOptions?.length, + selectedOptions$: selectedOptions$ as PublishingSubject, + availableOptions$: availableOptions$ as PublishingSubject, + variableName$: variableName$ as PublishingSubject, + variableType$: variableType$ as PublishingSubject, + controlType$: controlType$ as PublishingSubject, + esqlQuery$: esqlQuery$ as PublishingSubject, + title$: title$ as PublishingSubject, + setSelectedOptions, + }; +} diff --git a/src/platform/plugins/shared/controls/public/controls/esql_control/get_esql_control_factory.test.tsx b/src/platform/plugins/shared/controls/public/controls/esql_control/get_esql_control_factory.test.tsx new file mode 100644 index 0000000000000..a63ba69c823e4 --- /dev/null +++ b/src/platform/plugins/shared/controls/public/controls/esql_control/get_esql_control_factory.test.tsx @@ -0,0 +1,120 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import React from 'react'; +import { BehaviorSubject } from 'rxjs'; +import { StateComparators } from '@kbn/presentation-publishing'; +import { fireEvent, render, waitFor } from '@testing-library/react'; +import type { ESQLControlState } from '@kbn/esql/public'; +import { getMockedControlGroupApi } from '../mocks/control_mocks'; +import type { ControlApiRegistration } from '../types'; +import { getESQLControlFactory } from './get_esql_control_factory'; +import type { ESQLControlApi } from './types'; + +describe('ESQLControlApi', () => { + const uuid = 'myESQLControl'; + + const dashboardApi = {}; + const controlGroupApi = getMockedControlGroupApi(dashboardApi); + + const factory = getESQLControlFactory(); + function buildApiMock( + api: ControlApiRegistration, + nextComparators: StateComparators + ) { + return { + ...api, + uuid, + parentApi: controlGroupApi, + unsavedChanges$: new BehaviorSubject | undefined>(undefined), + resetUnsavedChanges: () => { + return true; + }, + type: factory.type, + }; + } + + test('Should publish ES|QL variable', async () => { + const initialState = { + selectedOptions: ['option1'], + availableOptions: ['option1', 'option2'], + variableName: 'variable1', + variableType: 'values', + esqlQuery: 'FROM foo | WHERE column = ?variable1', + controlType: 'STATIC_VALUES', + } as ESQLControlState; + const { api } = await factory.buildControl(initialState, buildApiMock, uuid, controlGroupApi); + expect(api.esqlVariable$.value).toStrictEqual({ + key: 'variable1', + type: 'values', + value: 'option1', + }); + }); + + test('Should serialize state', async () => { + const initialState = { + selectedOptions: ['option1'], + availableOptions: ['option1', 'option2'], + variableName: 'variable1', + variableType: 'values', + esqlQuery: 'FROM foo | WHERE column = ?variable1', + controlType: 'STATIC_VALUES', + } as ESQLControlState; + const { api } = await factory.buildControl(initialState, buildApiMock, uuid, controlGroupApi); + expect(api.serializeState()).toStrictEqual({ + rawState: { + availableOptions: ['option1', 'option2'], + controlType: 'STATIC_VALUES', + esqlQuery: 'FROM foo | WHERE column = ?variable1', + grow: undefined, + selectedOptions: ['option1'], + title: undefined, + variableName: 'variable1', + variableType: 'values', + width: undefined, + }, + references: [], + }); + }); + + test('changing the dropdown should publish new ES|QL variable', async () => { + const initialState = { + selectedOptions: ['option1'], + availableOptions: ['option1', 'option2'], + variableName: 'variable1', + variableType: 'values', + esqlQuery: 'FROM foo | WHERE column = ?variable1', + controlType: 'STATIC_VALUES', + } as ESQLControlState; + const { Component, api } = await factory.buildControl( + initialState, + buildApiMock, + uuid, + controlGroupApi + ); + + expect(api.esqlVariable$.value).toStrictEqual({ + key: 'variable1', + type: 'values', + value: 'option1', + }); + + const { findByTestId, findByTitle } = render(); + fireEvent.click(await findByTestId('comboBoxSearchInput')); + fireEvent.click(await findByTitle('option2')); + + await waitFor(() => { + expect(api.esqlVariable$.value).toStrictEqual({ + key: 'variable1', + type: 'values', + value: 'option2', + }); + }); + }); +}); diff --git a/src/platform/plugins/shared/controls/public/controls/esql_control/get_esql_control_factory.tsx b/src/platform/plugins/shared/controls/public/controls/esql_control/get_esql_control_factory.tsx new file mode 100644 index 0000000000000..22fd8ccdb9c43 --- /dev/null +++ b/src/platform/plugins/shared/controls/public/controls/esql_control/get_esql_control_factory.tsx @@ -0,0 +1,148 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import React from 'react'; +import { i18n } from '@kbn/i18n'; +import { BehaviorSubject } from 'rxjs'; +import { css } from '@emotion/react'; +import { EuiComboBox } from '@elastic/eui'; +import { apiPublishesESQLVariables } from '@kbn/esql-variables-types'; +import { useBatchedPublishingSubjects } from '@kbn/presentation-publishing'; +import type { ESQLControlState } from '@kbn/esql/public'; +import { ESQL_CONTROL } from '../../../common'; +import type { ESQLControlApi } from './types'; +import { ControlFactory } from '../types'; +import { uiActionsService } from '../../services/kibana_services'; +import { initializeDefaultControlApi } from '../initialize_default_control_api'; +import { initializeESQLControlSelections } from './esql_control_selections'; + +const displayName = i18n.translate('controls.esqlValuesControl.displayName', { + defaultMessage: 'Static values list', +}); + +export const getESQLControlFactory = (): ControlFactory => { + return { + type: ESQL_CONTROL, + order: 3, + getIconType: () => 'editorChecklist', + getDisplayName: () => displayName, + buildControl: async (initialState, buildApi, uuid, controlGroupApi) => { + const defaultControl = initializeDefaultControlApi(initialState); + const selections = initializeESQLControlSelections(initialState); + + const onSaveControl = (updatedState: ESQLControlState) => { + controlGroupApi?.replacePanel(uuid, { + panelType: 'esqlControl', + initialState: updatedState, + }); + }; + + const api = buildApi( + { + ...defaultControl.api, + ...selections.api, + defaultTitle$: new BehaviorSubject(initialState.title), + isEditingEnabled: () => true, + getTypeDisplayName: () => displayName, + onEdit: async () => { + const state = { + ...initialState, + ...defaultControl.serialize().rawState, + }; + const variablesInParent = apiPublishesESQLVariables(api.parentApi) + ? api.parentApi.esqlVariables$.value + : []; + try { + await uiActionsService.getTrigger('ESQL_CONTROL_TRIGGER').exec({ + queryString: initialState.esqlQuery, + variableType: initialState.variableType, + controlType: initialState.controlType, + esqlVariables: variablesInParent, + onSaveControl, + initialState: state, + }); + } catch (e) { + // eslint-disable-next-line no-console + console.error('Error getting ESQL control trigger', e); + } + }, + serializeState: () => { + const { rawState: defaultControlState } = defaultControl.serialize(); + return { + rawState: { + ...defaultControlState, + selectedOptions: selections.selectedOptions$.getValue(), + availableOptions: selections.availableOptions$.getValue(), + variableName: selections.variableName$.getValue(), + variableType: selections.variableType$.getValue(), + controlType: selections.controlType$.getValue(), + esqlQuery: selections.esqlQuery$.getValue(), + title: selections.title$.getValue(), + }, + references: [], + }; + }, + clearSelections: () => { + // do nothing, not allowed for now; + }, + }, + { + ...defaultControl.comparators, + ...selections.comparators, + } + ); + + const inputCss = css` + .euiComboBox__inputWrap { + box-shadow: none; + } + `; + return { + api, + Component: ({ className: controlPanelClassName }) => { + const [availableOptions, selectedOptions] = useBatchedPublishingSubjects( + selections.availableOptions$, + selections.selectedOptions$ + ); + + return ( +
+ ({ label: option }))} + selectedOptions={selectedOptions.map((option) => ({ label: option }))} + compressed + fullWidth + isClearable={false} + onChange={(options) => { + const selectedValues = options.map((option) => option.label); + selections.setSelectedOptions(selectedValues); + }} + /> +
+ ); + }, + }; + }, + }; +}; diff --git a/src/platform/plugins/shared/controls/public/controls/esql_control/register_esql_control.ts b/src/platform/plugins/shared/controls/public/controls/esql_control/register_esql_control.ts new file mode 100644 index 0000000000000..8c1649ba10fae --- /dev/null +++ b/src/platform/plugins/shared/controls/public/controls/esql_control/register_esql_control.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", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import { ESQL_CONTROL } from '../../../common'; +import { untilPluginStartServicesReady } from '../../services/kibana_services'; +import { registerControlFactory } from '../../control_factory_registry'; + +export function registerESQLControl() { + registerControlFactory(ESQL_CONTROL, async () => { + const [{ getESQLControlFactory }] = await Promise.all([ + import('../../controls_module'), + untilPluginStartServicesReady(), + ]); + return getESQLControlFactory(); + }); +} diff --git a/src/platform/plugins/shared/controls/public/controls/esql_control/types.ts b/src/platform/plugins/shared/controls/public/controls/esql_control/types.ts new file mode 100644 index 0000000000000..fe79a25f6b81e --- /dev/null +++ b/src/platform/plugins/shared/controls/public/controls/esql_control/types.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", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ +import { PublishesESQLVariable } from '@kbn/esql-variables-types'; +import type { HasEditCapabilities, PublishesTitle } from '@kbn/presentation-publishing'; +import type { DefaultControlApi } from '../types'; + +export type ESQLControlApi = DefaultControlApi & + PublishesESQLVariable & + HasEditCapabilities & + Pick; diff --git a/src/platform/plugins/shared/controls/public/controls_module.ts b/src/platform/plugins/shared/controls/public/controls_module.ts index 3dbcdf910cccb..2fad0f13aad70 100644 --- a/src/platform/plugins/shared/controls/public/controls_module.ts +++ b/src/platform/plugins/shared/controls/public/controls_module.ts @@ -16,5 +16,6 @@ export { getControlGroupEmbeddableFactory } from './control_group/get_control_gr export { getOptionsListControlFactory } from './controls/data_controls/options_list_control/get_options_list_control_factory'; export { getRangesliderControlFactory } from './controls/data_controls/range_slider/get_range_slider_control_factory'; export { getTimesliderControlFactory } from './controls/timeslider_control/get_timeslider_control_factory'; +export { getESQLControlFactory } from './controls/esql_control/get_esql_control_factory'; export { ControlGroupRenderer } from './control_group/control_group_renderer/control_group_renderer'; diff --git a/src/platform/plugins/shared/controls/public/index.ts b/src/platform/plugins/shared/controls/public/index.ts index 6455c71e7b5f6..9b99f81693c6a 100644 --- a/src/platform/plugins/shared/controls/public/index.ts +++ b/src/platform/plugins/shared/controls/public/index.ts @@ -36,6 +36,7 @@ export { OPTIONS_LIST_CONTROL, RANGE_SLIDER_CONTROL, TIME_SLIDER_CONTROL, + ESQL_CONTROL, } from '../common'; export type { ControlGroupRuntimeState, diff --git a/src/platform/plugins/shared/controls/public/plugin.ts b/src/platform/plugins/shared/controls/public/plugin.ts index 7c6d1ae91ab6a..78356ac7ba157 100644 --- a/src/platform/plugins/shared/controls/public/plugin.ts +++ b/src/platform/plugins/shared/controls/public/plugin.ts @@ -12,7 +12,10 @@ import { registerControlGroupEmbeddable } from './control_group/register_control import { registerOptionsListControl } from './controls/data_controls/options_list_control/register_options_list_control'; import { registerRangeSliderControl } from './controls/data_controls/range_slider/register_range_slider_control'; import { registerTimeSliderControl } from './controls/timeslider_control/register_timeslider_control'; +import { registerESQLControl } from './controls/esql_control/register_esql_control'; + import { setKibanaServices } from './services/kibana_services'; + import type { ControlsPluginSetupDeps, ControlsPluginStartDeps } from './types'; import { registerActions } from './actions/register_actions'; @@ -29,6 +32,7 @@ export class ControlsPlugin registerOptionsListControl(); registerRangeSliderControl(); registerTimeSliderControl(); + registerESQLControl(); } public start(coreStart: CoreStart, startPlugins: ControlsPluginStartDeps) { diff --git a/src/platform/plugins/shared/controls/server/esql_control/esql_control_factory.ts b/src/platform/plugins/shared/controls/server/esql_control/esql_control_factory.ts new file mode 100644 index 0000000000000..aa94cd9b8d6e9 --- /dev/null +++ b/src/platform/plugins/shared/controls/server/esql_control/esql_control_factory.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", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import { EmbeddableRegistryDefinition } from '@kbn/embeddable-plugin/server'; +import { ESQL_CONTROL } from '../../common'; +import { + createEsqlControlInject, + createEsqlControlExtract, +} from './esql_control_persistable_state'; + +export const esqlStaticControlPersistableStateServiceFactory = (): EmbeddableRegistryDefinition => { + return { + id: ESQL_CONTROL, + extract: createEsqlControlExtract(), + inject: createEsqlControlInject(), + }; +}; diff --git a/src/platform/plugins/shared/controls/server/esql_control/esql_control_persistable_state.ts b/src/platform/plugins/shared/controls/server/esql_control/esql_control_persistable_state.ts new file mode 100644 index 0000000000000..2124867a75609 --- /dev/null +++ b/src/platform/plugins/shared/controls/server/esql_control/esql_control_persistable_state.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", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import { + EmbeddableStateWithType, + EmbeddablePersistableStateService, +} from '@kbn/embeddable-plugin/common'; +import { SavedObjectReference } from '@kbn/core/types'; + +export const createEsqlControlInject = (): EmbeddablePersistableStateService['inject'] => { + return (state: EmbeddableStateWithType, references: SavedObjectReference[]) => { + const workingState = { ...state } as EmbeddableStateWithType; + return workingState as EmbeddableStateWithType; + }; +}; + +export const createEsqlControlExtract = (): EmbeddablePersistableStateService['extract'] => { + return (state: EmbeddableStateWithType) => { + const workingState = { ...state } as EmbeddableStateWithType; + const references: SavedObjectReference[] = []; + + return { state: workingState as EmbeddableStateWithType, references }; + }; +}; diff --git a/src/platform/plugins/shared/controls/server/plugin.ts b/src/platform/plugins/shared/controls/server/plugin.ts index 78617d2a81dbd..3dd7e33fe3cba 100644 --- a/src/platform/plugins/shared/controls/server/plugin.ts +++ b/src/platform/plugins/shared/controls/server/plugin.ts @@ -16,6 +16,7 @@ import { controlGroupContainerPersistableStateServiceFactory } from './control_g import { optionsListPersistableStateServiceFactory } from './options_list/options_list_embeddable_factory'; import { rangeSliderPersistableStateServiceFactory } from './range_slider/range_slider_embeddable_factory'; import { timeSliderPersistableStateServiceFactory } from './time_slider/time_slider_embeddable_factory'; +import { esqlStaticControlPersistableStateServiceFactory } from './esql_control/esql_control_factory'; import { setupOptionsListClusterSettingsRoute } from './options_list/options_list_cluster_settings_route'; interface SetupDeps { @@ -32,6 +33,7 @@ export class ControlsPlugin implements Plugin { embeddable.registerEmbeddableFactory(optionsListPersistableStateServiceFactory()); embeddable.registerEmbeddableFactory(rangeSliderPersistableStateServiceFactory()); embeddable.registerEmbeddableFactory(timeSliderPersistableStateServiceFactory()); + embeddable.registerEmbeddableFactory(esqlStaticControlPersistableStateServiceFactory()); setupOptionsListClusterSettingsRoute(core); setupOptionsListSuggestionsRoute(core, unifiedSearch.autocomplete.getAutocompleteSettings); return {}; diff --git a/src/platform/plugins/shared/controls/tsconfig.json b/src/platform/plugins/shared/controls/tsconfig.json index 6ca631c6886e3..4a3cef45061f8 100644 --- a/src/platform/plugins/shared/controls/tsconfig.json +++ b/src/platform/plugins/shared/controls/tsconfig.json @@ -39,6 +39,9 @@ "@kbn/shared-ux-utility", "@kbn/std", "@kbn/react-hooks", + "@kbn/esql-validation-autocomplete", + "@kbn/esql-variables-types", + "@kbn/esql", ], "exclude": ["target/**/*"] } diff --git a/src/platform/plugins/shared/dashboard/kibana.jsonc b/src/platform/plugins/shared/dashboard/kibana.jsonc index d5ba75b11db10..2f610dc71dc17 100644 --- a/src/platform/plugins/shared/dashboard/kibana.jsonc +++ b/src/platform/plugins/shared/dashboard/kibana.jsonc @@ -1,9 +1,7 @@ { "type": "plugin", "id": "@kbn/dashboard-plugin", - "owner": [ - "@elastic/kibana-presentation" - ], + "owner": ["@elastic/kibana-presentation"], "group": "platform", "visibility": "shared", "description": "Adds the Dashboard app to Kibana", @@ -29,7 +27,7 @@ "urlForwarding", "presentationUtil", "visualizations", - "unifiedSearch", + "unifiedSearch" ], "optionalPlugins": [ "home", diff --git a/src/platform/plugins/shared/dashboard/public/dashboard_api/types.ts b/src/platform/plugins/shared/dashboard/public/dashboard_api/types.ts index ac0c477e98595..094ebbe62c73b 100644 --- a/src/platform/plugins/shared/dashboard/public/dashboard_api/types.ts +++ b/src/platform/plugins/shared/dashboard/public/dashboard_api/types.ts @@ -16,6 +16,7 @@ import { import { RefreshInterval, SearchSessionInfoProvider } from '@kbn/data-plugin/public'; import type { DefaultEmbeddableApi, EmbeddablePackageState } from '@kbn/embeddable-plugin/public'; import { Filter, Query, TimeRange } from '@kbn/es-query'; +import { PublishesESQLVariables } from '@kbn/esql-variables-types'; import { IKbnUrlStateStorage } from '@kbn/kibana-utils-plugin/public'; import { CanExpandPanels, @@ -135,6 +136,7 @@ export type DashboardApi = CanExpandPanels & Pick & PublishesReload & PublishesSavedObjectId & + PublishesESQLVariables & PublishesSearchSession & PublishesSettings & PublishesUnifiedSearch & diff --git a/src/platform/plugins/shared/dashboard/public/dashboard_api/unified_search_manager.ts b/src/platform/plugins/shared/dashboard/public/dashboard_api/unified_search_manager.ts index 5cb7a40dcc52c..e5a7c902cb6d7 100644 --- a/src/platform/plugins/shared/dashboard/public/dashboard_api/unified_search_manager.ts +++ b/src/platform/plugins/shared/dashboard/public/dashboard_api/unified_search_manager.ts @@ -7,6 +7,15 @@ * License v3.0 only", or the "Server Side Public License, v 1". */ +import { ControlGroupApi } from '@kbn/controls-plugin/public'; +import type { SavedObjectReference } from '@kbn/core-saved-objects-api-server'; +import { + GlobalQueryStateFromUrl, + RefreshInterval, + connectToQueryState, + extractSearchSourceReferences, + syncGlobalQueryStateWithUrl, +} from '@kbn/data-plugin/public'; import { COMPARE_ALL_OPTIONS, Filter, @@ -15,6 +24,11 @@ import { compareFilters, isFilterPinned, } from '@kbn/es-query'; +import { ESQLControlVariable } from '@kbn/esql-validation-autocomplete'; +import { PublishingSubject, StateComparators } from '@kbn/presentation-publishing'; +import fastIsEqual from 'fast-deep-equal'; +import { cloneDeep } from 'lodash'; +import moment, { Moment } from 'moment'; import { BehaviorSubject, Observable, @@ -29,24 +43,11 @@ import { switchMap, tap, } from 'rxjs'; -import fastIsEqual from 'fast-deep-equal'; -import { PublishingSubject, StateComparators } from '@kbn/presentation-publishing'; -import { ControlGroupApi } from '@kbn/controls-plugin/public'; -import { cloneDeep } from 'lodash'; -import type { SavedObjectReference } from '@kbn/core-saved-objects-api-server'; -import { - GlobalQueryStateFromUrl, - RefreshInterval, - connectToQueryState, - extractSearchSourceReferences, - syncGlobalQueryStateWithUrl, -} from '@kbn/data-plugin/public'; -import moment, { Moment } from 'moment'; -import { cleanFiltersForSerialize } from '../utils/clean_filters_for_serialize'; import { dataService } from '../services/kibana_services'; -import { DashboardCreationOptions, DashboardState } from './types'; -import { DEFAULT_DASHBOARD_INPUT } from './default_dashboard_input'; +import { cleanFiltersForSerialize } from '../utils/clean_filters_for_serialize'; import { GLOBAL_STATE_STORAGE_KEY } from '../utils/urls'; +import { DEFAULT_DASHBOARD_INPUT } from './default_dashboard_input'; +import { DashboardCreationOptions, DashboardState } from './types'; export function initializeUnifiedSearchManager( initialState: DashboardState, @@ -120,6 +121,19 @@ export function initializeUnifiedSearchManager( const controlGroupTimeslice$ = controlGroupApi$.pipe( switchMap((controlGroupApi) => (controlGroupApi ? controlGroupApi.timeslice$ : of(undefined))) ); + + // forward ESQL variables from the control group. TODO, this is overcomplicated by the fact that + // the control group API is a publishing subject. Instead, the control group API should be a constant + const esqlVariables$ = new BehaviorSubject([]); + const controlGroupEsqlVariables$ = controlGroupApi$.pipe( + switchMap((controlGroupApi) => + controlGroupApi ? controlGroupApi.esqlVariables$ : of([] as ESQLControlVariable[]) + ) + ); + controlGroupSubscriptions.add( + controlGroupEsqlVariables$.subscribe((latestVariables) => esqlVariables$.next(latestVariables)) + ); + controlGroupSubscriptions.add( combineLatest([unifiedSearchFilters$, controlGroupFilters$]).subscribe( ([unifiedSearchFilters, controlGroupFilters]) => { @@ -263,6 +277,7 @@ export function initializeUnifiedSearchManager( return { api: { filters$, + esqlVariables$, forceRefresh: () => { controlGroupReload$.next(); panelsReload$.next(); diff --git a/src/platform/plugins/shared/dashboard/public/dashboard_app/dashboard_app.tsx b/src/platform/plugins/shared/dashboard/public/dashboard_app/dashboard_app.tsx index dce6b62d88026..21a7b2d5ac881 100644 --- a/src/platform/plugins/shared/dashboard/public/dashboard_app/dashboard_app.tsx +++ b/src/platform/plugins/shared/dashboard/public/dashboard_app/dashboard_app.tsx @@ -16,7 +16,6 @@ import { v4 as uuidv4 } from 'uuid'; import { DASHBOARD_APP_LOCATOR } from '@kbn/deeplinks-analytics'; import { useExecutionContext } from '@kbn/kibana-react-plugin/public'; import { createKbnUrlStateStorage, withNotifyOnErrors } from '@kbn/kibana-utils-plugin/public'; - import { ViewMode } from '@kbn/presentation-publishing'; import { DashboardApi, DashboardCreationOptions } from '..'; import { SharedDashboardState } from '../../common'; diff --git a/src/platform/plugins/shared/dashboard/public/mocks.tsx b/src/platform/plugins/shared/dashboard/public/mocks.tsx index b10e91d810ab8..1b54ecf8af273 100644 --- a/src/platform/plugins/shared/dashboard/public/mocks.tsx +++ b/src/platform/plugins/shared/dashboard/public/mocks.tsx @@ -73,6 +73,7 @@ export const mockControlGroupApi = { filters$: new BehaviorSubject(undefined), query$: new BehaviorSubject(undefined), timeslice$: new BehaviorSubject(undefined), + esqlVariables$: new BehaviorSubject(undefined), dataViews$: new BehaviorSubject(undefined), unsavedChanges$: new BehaviorSubject(undefined), } as unknown as ControlGroupApi; diff --git a/src/platform/plugins/shared/dashboard/tsconfig.json b/src/platform/plugins/shared/dashboard/tsconfig.json index ed1555fb069c3..e1bcc5fae059f 100644 --- a/src/platform/plugins/shared/dashboard/tsconfig.json +++ b/src/platform/plugins/shared/dashboard/tsconfig.json @@ -83,7 +83,9 @@ "@kbn/visualization-utils", "@kbn/std", "@kbn/core-rendering-browser", - "@kbn/grid-layout" + "@kbn/esql-variables-types", + "@kbn/grid-layout", + "@kbn/esql-validation-autocomplete" ], "exclude": ["target/**/*"] } diff --git a/src/platform/plugins/shared/data/common/search/expressions/__snapshots__/kibana.test.ts.snap b/src/platform/plugins/shared/data/common/search/expressions/__snapshots__/kibana.test.ts.snap index 7bcf782fbbbc2..5774c69819f50 100644 --- a/src/platform/plugins/shared/data/common/search/expressions/__snapshots__/kibana.test.ts.snap +++ b/src/platform/plugins/shared/data/common/search/expressions/__snapshots__/kibana.test.ts.snap @@ -2,6 +2,7 @@ exports[`interpreter/functions#kibana returns an object with the correct structure 1`] = ` Object { + "esqlVariables": undefined, "filters": Array [ Object { "meta": Object { diff --git a/src/platform/plugins/shared/data/common/search/expressions/esql.ts b/src/platform/plugins/shared/data/common/search/expressions/esql.ts index 59f5d2a642fbf..14e4b857556f0 100644 --- a/src/platform/plugins/shared/data/common/search/expressions/esql.ts +++ b/src/platform/plugins/shared/data/common/search/expressions/esql.ts @@ -15,9 +15,14 @@ import type { IKibanaSearchResponse, ISearchGeneric, } from '@kbn/search-types'; -import type { Datatable, ExpressionFunctionDefinition } from '@kbn/expressions-plugin/common'; +import type { + Datatable, + DatatableColumn, + ExpressionFunctionDefinition, +} from '@kbn/expressions-plugin/common'; import { RequestAdapter } from '@kbn/inspector-plugin/common'; -import { getIndexPatternFromESQLQuery, getStartEndParams } from '@kbn/esql-utils'; +import { getNamedParams, mapVariableToColumn } from '@kbn/esql-utils'; +import { getIndexPatternFromESQLQuery } from '@kbn/esql-utils'; import { zipObject } from 'lodash'; import { catchError, defer, map, Observable, switchMap, tap, throwError } from 'rxjs'; import { buildEsQuery, type Filter } from '@kbn/es-query'; @@ -186,7 +191,7 @@ export const getEsqlFn = ({ getStartDependencies }: EsqlFnArguments) => { uiSettings as Parameters[0] ); - const namedParams = getStartEndParams(query, input.timeRange); + const namedParams = getNamedParams(query, input.timeRange, input.esqlVariables); if (namedParams.length) { params.params = namedParams; @@ -349,11 +354,17 @@ export const getEsqlFn = ({ getStartDependencies }: EsqlFnArguments) => { isNull: hasEmptyColumns ? !lookup.has(name) : false, })) ?? []; + const updatedWithVariablesColumns = mapVariableToColumn( + query, + input?.esqlVariables ?? [], + allColumns as DatatableColumn[] + ); + // sort only in case of empty columns to correctly align columns to items in values array if (hasEmptyColumns) { - allColumns.sort((a, b) => Number(a.isNull) - Number(b.isNull)); + updatedWithVariablesColumns.sort((a, b) => Number(a.isNull) - Number(b.isNull)); } - const columnNames = allColumns?.map(({ name }) => name); + const columnNames = updatedWithVariablesColumns?.map(({ name }) => name); const rows = body.values.map((row) => zipObject(columnNames, row)); @@ -366,7 +377,7 @@ export const getEsqlFn = ({ getStartDependencies }: EsqlFnArguments) => { totalCount: body.values.length, }, }, - columns: allColumns, + columns: updatedWithVariablesColumns, rows, warning, } as Datatable; diff --git a/src/platform/plugins/shared/data/common/search/expressions/kibana.ts b/src/platform/plugins/shared/data/common/search/expressions/kibana.ts index 77580f8f124f5..f6b85a934db06 100644 --- a/src/platform/plugins/shared/data/common/search/expressions/kibana.ts +++ b/src/platform/plugins/shared/data/common/search/expressions/kibana.ts @@ -46,6 +46,7 @@ export const kibana: ExpressionFunctionKibana = { query: [...toArray(getSearchContext().query), ...toArray((input || {}).query)], filters: [...(getSearchContext().filters || []), ...((input || {}).filters || [])], timeRange: getSearchContext().timeRange || (input ? input.timeRange : undefined), + esqlVariables: getSearchContext().esqlVariables || (input ? input.esqlVariables : undefined), }; return output; diff --git a/src/platform/plugins/shared/data/tsconfig.json b/src/platform/plugins/shared/data/tsconfig.json index 1edc83a23e05e..007bc3aecd16a 100644 --- a/src/platform/plugins/shared/data/tsconfig.json +++ b/src/platform/plugins/shared/data/tsconfig.json @@ -53,7 +53,7 @@ "@kbn/search-types", "@kbn/safer-lodash-set", "@kbn/esql-utils", - "@kbn/shared-ux-table-persist" + "@kbn/shared-ux-table-persist", ], "exclude": [ "target/**/*", diff --git a/src/platform/plugins/shared/discover/public/application/discover_router.tsx b/src/platform/plugins/shared/discover/public/application/discover_router.tsx index d74da192c8f48..40c1f5883e39b 100644 --- a/src/platform/plugins/shared/discover/public/application/discover_router.tsx +++ b/src/platform/plugins/shared/discover/public/application/discover_router.tsx @@ -13,8 +13,6 @@ import React from 'react'; import { History } from 'history'; import { EuiErrorBoundary } from '@elastic/eui'; import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public'; -import useObservable from 'react-use/lib/useObservable'; -import type { Observable } from 'rxjs'; import type { ExperimentalFeatures } from '../../server/config'; import { ContextAppRoute } from './context'; import { SingleDocRoute } from './doc'; @@ -25,33 +23,15 @@ import { ViewAlertRoute } from './view_alert'; import type { DiscoverCustomizationContext } from '../customizations'; export type DiscoverRouterProps = Omit & { - customizationContext$: Observable; + customizationContext: DiscoverCustomizationContext; }; -export const DiscoverRouter = ({ - customizationContext$, - services, - history, - ...routeProps -}: DiscoverRouterProps) => { - const customizationContext = useObservable(customizationContext$); - - // The Discover state is not reactive, so we must avoid initialization before - // the first value is emitted - if (customizationContext == null) { - return null; - } - +export const DiscoverRouter = ({ services, history, ...routeProps }: DiscoverRouterProps) => { return ( - + diff --git a/src/platform/plugins/shared/discover/public/application/index.tsx b/src/platform/plugins/shared/discover/public/application/index.tsx index 99fc03170a9bb..8f946c20daaf5 100644 --- a/src/platform/plugins/shared/discover/public/application/index.tsx +++ b/src/platform/plugins/shared/discover/public/application/index.tsx @@ -10,7 +10,6 @@ import React from 'react'; import { i18n } from '@kbn/i18n'; import { toMountPoint } from '@kbn/react-kibana-mount'; -import type { Observable } from 'rxjs'; import type { ExperimentalFeatures } from '../../server/config'; import { DiscoverRouter } from './discover_router'; import { DiscoverServices } from '../build_services'; @@ -19,14 +18,14 @@ import type { DiscoverCustomizationContext } from '../customizations'; export interface RenderAppProps { element: HTMLElement; services: DiscoverServices; - customizationContext$: Observable; + customizationContext: DiscoverCustomizationContext; experimentalFeatures: ExperimentalFeatures; } export const renderApp = ({ element, services, - customizationContext$, + customizationContext, experimentalFeatures, }: RenderAppProps) => { const { history, capabilities, chrome, data, core } = services; @@ -45,7 +44,7 @@ export const renderApp = ({ const unmount = toMountPoint( , diff --git a/src/platform/plugins/shared/discover/public/application/main/components/layout/discover_layout.scss b/src/platform/plugins/shared/discover/public/application/main/components/layout/discover_layout.scss index edfea7a231d13..3b4d4fbeda2ca 100644 --- a/src/platform/plugins/shared/discover/public/application/main/components/layout/discover_layout.scss +++ b/src/platform/plugins/shared/discover/public/application/main/components/layout/discover_layout.scss @@ -15,10 +15,6 @@ discover-app { @include euiBreakpoint('m', 'l', 'xl') { @include kibanaFullBodyHeight(); - - &.dscPage--topNavInline { - @include kibanaFullBodyHeight($euiSize * 3); - } } } diff --git a/src/platform/plugins/shared/discover/public/application/main/components/layout/discover_layout.tsx b/src/platform/plugins/shared/discover/public/application/main/components/layout/discover_layout.tsx index 33c202c1f8be6..f0b9baa29f764 100644 --- a/src/platform/plugins/shared/discover/public/application/main/components/layout/discover_layout.tsx +++ b/src/platform/plugins/shared/discover/public/application/main/components/layout/discover_layout.tsx @@ -375,9 +375,7 @@ export function DiscoverLayout({ stateContainer }: DiscoverLayoutProps) { return ( { expect(topNav.prop('dataViewPickerComponentProps')).toBeUndefined(); }); }); - - describe('inline top nav', () => { - it('should render top nav when inline top nav is not enabled', () => { - const props = getProps(); - const component = mountWithIntl( - - - - ); - const searchBar = component.find(mockDiscoverService.navigation.ui.AggregateQueryTopNavMenu); - expect(searchBar.prop('badges')).toBeDefined(); - expect(searchBar.prop('config')).toBeDefined(); - expect(searchBar.prop('setMenuMountPoint')).toBeDefined(); - }); - - it('should not render top nav when inline top nav is enabled', () => { - const props = getProps(); - props.stateContainer.customizationContext.inlineTopNav.enabled = true; - const component = mountWithIntl( - - - - ); - const searchBar = component.find(mockDiscoverService.navigation.ui.AggregateQueryTopNavMenu); - expect(searchBar.prop('badges')).toBeUndefined(); - expect(searchBar.prop('config')).toBeUndefined(); - expect(searchBar.prop('setMenuMountPoint')).toBeUndefined(); - }); - }); }); diff --git a/src/platform/plugins/shared/discover/public/application/main/components/top_nav/discover_topnav.tsx b/src/platform/plugins/shared/discover/public/application/main/components/top_nav/discover_topnav.tsx index a09284f2519b7..577b93245cb33 100644 --- a/src/platform/plugins/shared/discover/public/application/main/components/top_nav/discover_topnav.tsx +++ b/src/platform/plugins/shared/discover/public/application/main/components/top_nav/discover_topnav.tsx @@ -163,23 +163,15 @@ export const DiscoverTopNav = ({ ); const { topNavBadges, topNavMenu } = useDiscoverTopNav({ stateContainer }); - const topNavProps = useMemo(() => { - if (stateContainer.customizationContext.inlineTopNav.enabled) { - return undefined; - } - - return { + const topNavProps = useMemo( + () => ({ badges: topNavBadges, config: topNavMenu, setMenuMountPoint: setHeaderActionMenu, className: 'dscTopNav', // FIXME: Delete the scss file and pass `gutterSize="xxs"` instead (after next Eui release) - }; - }, [ - setHeaderActionMenu, - stateContainer.customizationContext.inlineTopNav.enabled, - topNavBadges, - topNavMenu, - ]); + }), + [setHeaderActionMenu, topNavBadges, topNavMenu] + ); const dataViewPickerProps: DataViewPickerProps = useMemo(() => { const isESQLModeEnabled = uiSettings.get(ENABLE_ESQL); diff --git a/src/platform/plugins/shared/discover/public/application/main/components/top_nav/discover_topnav_inline.test.tsx b/src/platform/plugins/shared/discover/public/application/main/components/top_nav/discover_topnav_inline.test.tsx deleted file mode 100644 index 7b2cfde82a9cb..0000000000000 --- a/src/platform/plugins/shared/discover/public/application/main/components/top_nav/discover_topnav_inline.test.tsx +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the "Elastic License - * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import React from 'react'; -import { DiscoverMainProvider } from '../../state_management/discover_state_provider'; -import { DiscoverTopNavInline } from './discover_topnav_inline'; -import { getDiscoverStateMock } from '../../../../__mocks__/discover_state.mock'; -import { dataViewMock } from '@kbn/discover-utils/src/__mocks__'; -import { discoverServiceMock as mockDiscoverService } from '../../../../__mocks__/services'; -import { useKibana } from '@kbn/kibana-react-plugin/public'; -import { render, screen, waitFor } from '@testing-library/react'; - -jest.mock('@kbn/kibana-react-plugin/public', () => ({ - ...jest.requireActual('@kbn/kibana-react-plugin/public'), - useKibana: jest.fn(), -})); - -function getProps({ hideNavMenuItems }: { hideNavMenuItems?: boolean } = {}) { - const stateContainer = getDiscoverStateMock({ isTimeBased: true }); - stateContainer.internalState.transitions.setDataView(dataViewMock); - stateContainer.customizationContext.displayMode = 'standalone'; - stateContainer.customizationContext.inlineTopNav.enabled = true; - stateContainer.customizationContext.inlineTopNav.showLogsExplorerTabs = false; - - return { - stateContainer, - hideNavMenuItems, - }; -} - -const mockUseKibana = useKibana as jest.Mock; - -describe('DiscoverTopNavInline', () => { - beforeEach(() => { - jest.clearAllMocks(); - mockUseKibana.mockReturnValue({ - services: mockDiscoverService, - }); - }); - - it('should not render when top nav inline is not enabled', async () => { - const props = getProps(); - props.stateContainer.customizationContext.inlineTopNav.enabled = false; - render( - - - - ); - const topNav = screen.queryByTestId('discoverTopNavInline'); - expect(topNav).toBeNull(); - }); - - it('should render when top nav inline is enabled and displayMode is "standalone"', async () => { - const props = getProps(); - render( - - - - ); - const topNav = screen.queryByTestId('discoverTopNavInline'); - expect(topNav).not.toBeNull(); - }); - - it('should not render when top nav inline is enabled and displayMode is not "standalone"', async () => { - const props = getProps(); - props.stateContainer.customizationContext.displayMode = 'embedded'; - render( - - - - ); - const topNav = screen.queryByTestId('discoverTopNavInline'); - expect(topNav).toBeNull(); - }); - - describe('nav menu items', () => { - it('should show nav menu items when hideNavMenuItems is false', async () => { - const props = getProps(); - render( - - - - ); - const topNav = screen.queryByTestId('discoverTopNavInline'); - expect(topNav).not.toBeNull(); - await waitFor(() => { - const topNavMenuItems = screen.queryByTestId('topNavMenuItems'); - expect(topNavMenuItems).not.toBeNull(); - }); - }); - - it('should hide nav menu items when hideNavMenuItems is true', async () => { - const props = getProps({ hideNavMenuItems: true }); - render( - - - - ); - const topNav = screen.queryByTestId('discoverTopNavInline'); - expect(topNav).not.toBeNull(); - await waitFor(() => { - const topNavMenuItems = screen.queryByTestId('topNavMenuItems'); - expect(topNavMenuItems).toBeNull(); - }); - }); - }); -}); diff --git a/src/platform/plugins/shared/discover/public/application/main/components/top_nav/discover_topnav_inline.tsx b/src/platform/plugins/shared/discover/public/application/main/components/top_nav/discover_topnav_inline.tsx deleted file mode 100644 index 6db06ee830427..0000000000000 --- a/src/platform/plugins/shared/discover/public/application/main/components/top_nav/discover_topnav_inline.tsx +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the "Elastic License - * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ - -import React from 'react'; -import { EuiHeader, EuiHeaderSection, EuiHeaderSectionItem, useEuiTheme } from '@elastic/eui'; -import { TopNavMenuBadges, TopNavMenuItems } from '@kbn/navigation-plugin/public'; -import { useDiscoverTopNav } from './use_discover_topnav'; -import type { DiscoverStateContainer } from '../../state_management/discover_state'; - -export const DiscoverTopNavInline = ({ - stateContainer, - hideNavMenuItems, -}: { - stateContainer: DiscoverStateContainer; - hideNavMenuItems?: boolean; -}) => { - const { euiTheme } = useEuiTheme(); - const { customizationContext } = stateContainer; - const { topNavBadges, topNavMenu } = useDiscoverTopNav({ stateContainer }); - - if ( - !customizationContext.inlineTopNav.enabled || - customizationContext.displayMode !== 'standalone' - ) { - return null; - } - - return ( - - {!hideNavMenuItems && ( - - - - - - - - - )} - - ); -}; diff --git a/src/platform/plugins/shared/discover/public/application/main/components/top_nav/on_save_search.tsx b/src/platform/plugins/shared/discover/public/application/main/components/top_nav/on_save_search.tsx index f1a2eff160db9..63edc5cd36fdd 100644 --- a/src/platform/plugins/shared/discover/public/application/main/components/top_nav/on_save_search.tsx +++ b/src/platform/plugins/shared/discover/public/application/main/components/top_nav/on_save_search.tsx @@ -255,7 +255,7 @@ const SaveSearchObjectModal: React.FC<{ helpText={ } > diff --git a/src/platform/plugins/shared/discover/public/application/main/discover_main_route.test.tsx b/src/platform/plugins/shared/discover/public/application/main/discover_main_route.test.tsx index dec1a9af162a0..066d2362c68d1 100644 --- a/src/platform/plugins/shared/discover/public/application/main/discover_main_route.test.tsx +++ b/src/platform/plugins/shared/discover/public/application/main/discover_main_route.test.tsx @@ -20,7 +20,6 @@ import { createCustomizationService, DiscoverCustomizationService, } from '../../customizations/customization_service'; -import { DiscoverTopNavInline } from './components/top_nav/discover_topnav_inline'; import { mockCustomizationContext } from '../../customizations/__mocks__/customization_context'; import { DataViewSpec } from '@kbn/data-views-plugin/common'; import { MainHistoryLocationState } from '../../../common'; @@ -151,14 +150,6 @@ describe('DiscoverMainRoute', () => { expect(component.find(DiscoverMainApp).exists()).toBe(true); }); }); - - test('should pass hideNavMenuItems=true to DiscoverTopNavInline while loading', async () => { - const component = mountComponent(true, true); - expect(component.find(DiscoverTopNavInline).prop('hideNavMenuItems')).toBe(true); - await waitFor(() => { - expect(component.update().find(DiscoverTopNavInline).prop('hideNavMenuItems')).toBe(false); - }); - }); }); const mountComponent = ( diff --git a/src/platform/plugins/shared/discover/public/application/main/discover_main_route.tsx b/src/platform/plugins/shared/discover/public/application/main/discover_main_route.tsx index ee2aefe955b68..99b290fc25ae7 100644 --- a/src/platform/plugins/shared/discover/public/application/main/discover_main_route.tsx +++ b/src/platform/plugins/shared/discover/public/application/main/discover_main_route.tsx @@ -38,7 +38,6 @@ import { DiscoverCustomizationProvider, useDiscoverCustomizationService, } from '../../customizations'; -import { DiscoverTopNavInline } from './components/top_nav/discover_topnav_inline'; import { DiscoverStateContainer, LoadParams } from './state_management/discover_state'; import { DataSourceType, isDataSourceType } from '../../../common/data_sources'; import { useDefaultAdHocDataViews, useRootProfile } from '../../context_awareness'; @@ -383,13 +382,7 @@ export function DiscoverMainRoute({ return ( - - - {mainContent} - + {mainContent} ); diff --git a/src/platform/plugins/shared/discover/public/components/discover_container/discover_container.tsx b/src/platform/plugins/shared/discover/public/components/discover_container/discover_container.tsx index 92ae1b7c0f4cb..f6a1e40485e5d 100644 --- a/src/platform/plugins/shared/discover/public/components/discover_container/discover_container.tsx +++ b/src/platform/plugins/shared/discover/public/components/discover_container/discover_container.tsx @@ -44,13 +44,7 @@ const discoverContainerWrapperCss = css` } `; -const customizationContext: DiscoverCustomizationContext = { - displayMode: 'embedded', - inlineTopNav: { - enabled: false, - showLogsExplorerTabs: false, - }, -}; +const customizationContext: DiscoverCustomizationContext = { displayMode: 'embedded' }; export const DiscoverContainerInternal = ({ overrideServices, diff --git a/src/platform/plugins/shared/discover/public/customizations/defaults.ts b/src/platform/plugins/shared/discover/public/customizations/defaults.ts index d44b6527b3909..09be30870148d 100644 --- a/src/platform/plugins/shared/discover/public/customizations/defaults.ts +++ b/src/platform/plugins/shared/discover/public/customizations/defaults.ts @@ -11,8 +11,4 @@ import { DiscoverCustomizationContext } from './types'; export const defaultCustomizationContext: DiscoverCustomizationContext = { displayMode: 'standalone', - inlineTopNav: { - enabled: false, - showLogsExplorerTabs: false, - }, }; diff --git a/src/platform/plugins/shared/discover/public/customizations/types.ts b/src/platform/plugins/shared/discover/public/customizations/types.ts index bf71fa80148ec..0979ea1914d24 100644 --- a/src/platform/plugins/shared/discover/public/customizations/types.ts +++ b/src/platform/plugins/shared/discover/public/customizations/types.ts @@ -26,17 +26,4 @@ export interface DiscoverCustomizationContext { * Display mode in which discover is running */ displayMode: DiscoverDisplayMode; - /** - * Inline top nav configuration - */ - inlineTopNav: { - /** - * Whether or not to show the inline top nav - */ - enabled: boolean; - /** - * Whether or not to show the Logs Explorer tabs - */ - showLogsExplorerTabs: boolean; - }; } diff --git a/src/platform/plugins/shared/discover/public/mocks.tsx b/src/platform/plugins/shared/discover/public/mocks.tsx index ec3421f605369..35522568bbd5b 100644 --- a/src/platform/plugins/shared/discover/public/mocks.tsx +++ b/src/platform/plugins/shared/discover/public/mocks.tsx @@ -18,8 +18,6 @@ export type Start = jest.Mocked; const createSetupContract = (): Setup => { const setupContract: Setup = { locator: sharePluginMock.createLocator(), - showInlineTopNav: jest.fn(), - configureInlineTopNav: jest.fn(), }; return setupContract; }; diff --git a/src/platform/plugins/shared/discover/public/plugin.tsx b/src/platform/plugins/shared/discover/public/plugin.tsx index 08d6f9f6c741a..9845091e018a2 100644 --- a/src/platform/plugins/shared/discover/public/plugin.tsx +++ b/src/platform/plugins/shared/discover/public/plugin.tsx @@ -8,7 +8,7 @@ */ import React from 'react'; -import { BehaviorSubject, map, Observable } from 'rxjs'; +import { BehaviorSubject } from 'rxjs'; import { AppMountParameters, AppUpdater, @@ -42,7 +42,7 @@ import { DiscoverAppLocatorDefinition, DiscoverESQLLocatorDefinition, } from '../common'; -import { defaultCustomizationContext, DiscoverCustomizationContext } from './customizations'; +import { defaultCustomizationContext } from './customizations'; import { SEARCH_EMBEDDABLE_CELL_ACTIONS_TRIGGER } from './embeddable/constants'; import { DiscoverContainerInternal, @@ -69,8 +69,6 @@ export class DiscoverPlugin { private readonly appStateUpdater = new BehaviorSubject(() => ({})); private readonly historyService = new HistoryService(); - private readonly inlineTopNav: Map = - new Map([[null, defaultCustomizationContext.inlineTopNav]]); private readonly experimentalFeatures: ExperimentalFeatures; private scopedHistory?: ScopedHistory; @@ -207,23 +205,11 @@ export class DiscoverPlugin // due to EUI bug https://github.com/elastic/eui/pull/5152 params.element.classList.add('dscAppWrapper'); - const customizationContext$: Observable = services.chrome - .getActiveSolutionNavId$() - .pipe( - map((solutionNavId) => ({ - ...defaultCustomizationContext, - inlineTopNav: - this.inlineTopNav.get(solutionNavId) ?? - this.inlineTopNav.get(null) ?? - defaultCustomizationContext.inlineTopNav, - })) - ); - const { renderApp } = await import('./application'); const unmount = renderApp({ element: params.element, services, - customizationContext$, + customizationContext: defaultCustomizationContext, experimentalFeatures: this.experimentalFeatures, }); @@ -264,18 +250,7 @@ export class DiscoverPlugin this.registerEmbeddable(core, plugins); - return { - locator: this.locator, - showInlineTopNav: () => { - this.inlineTopNav.set(null, { - enabled: true, - showLogsExplorerTabs: false, - }); - }, - configureInlineTopNav: (projectNavId, options) => { - this.inlineTopNav.set(projectNavId, options); - }, - }; + return { locator: this.locator }; } start(core: CoreStart, plugins: DiscoverStartPlugins): DiscoverStart { diff --git a/src/platform/plugins/shared/discover/public/types.ts b/src/platform/plugins/shared/discover/public/types.ts index 4b16e3e58df7c..588be70a5baba 100644 --- a/src/platform/plugins/shared/discover/public/types.ts +++ b/src/platform/plugins/shared/discover/public/types.ts @@ -7,26 +7,26 @@ * License v3.0 only", or the "Server Side Public License, v 1". */ -import { ComponentType } from 'react'; -import { UiActionsSetup, UiActionsStart } from '@kbn/ui-actions-plugin/public'; -import { ExpressionsSetup, ExpressionsStart } from '@kbn/expressions-plugin/public'; -import { EmbeddableSetup, EmbeddableStart } from '@kbn/embeddable-plugin/public'; -import { ChartsPluginStart } from '@kbn/charts-plugin/public'; +import type { ComponentType } from 'react'; +import type { UiActionsSetup, UiActionsStart } from '@kbn/ui-actions-plugin/public'; +import type { ExpressionsSetup, ExpressionsStart } from '@kbn/expressions-plugin/public'; +import type { EmbeddableSetup, EmbeddableStart } from '@kbn/embeddable-plugin/public'; +import type { ChartsPluginStart } from '@kbn/charts-plugin/public'; import type { GlobalSearchPluginSetup } from '@kbn/global-search-plugin/public'; -import { NavigationPublicPluginStart as NavigationStart } from '@kbn/navigation-plugin/public'; -import { SharePluginStart, SharePluginSetup } from '@kbn/share-plugin/public'; -import { UrlForwardingSetup, UrlForwardingStart } from '@kbn/url-forwarding-plugin/public'; -import { HomePublicPluginSetup } from '@kbn/home-plugin/public'; -import { Start as InspectorPublicPluginStart } from '@kbn/inspector-plugin/public'; -import { DataPublicPluginSetup, DataPublicPluginStart } from '@kbn/data-plugin/public'; -import { UsageCollectionSetup } from '@kbn/usage-collection-plugin/public'; -import { IndexPatternFieldEditorStart } from '@kbn/data-view-field-editor-plugin/public'; -import { DataViewsServicePublic } from '@kbn/data-views-plugin/public'; +import type { NavigationPublicPluginStart as NavigationStart } from '@kbn/navigation-plugin/public'; +import type { SharePluginStart, SharePluginSetup } from '@kbn/share-plugin/public'; +import type { UrlForwardingSetup, UrlForwardingStart } from '@kbn/url-forwarding-plugin/public'; +import type { HomePublicPluginSetup } from '@kbn/home-plugin/public'; +import type { Start as InspectorPublicPluginStart } from '@kbn/inspector-plugin/public'; +import type { DataPublicPluginSetup, DataPublicPluginStart } from '@kbn/data-plugin/public'; +import type { UsageCollectionSetup } from '@kbn/usage-collection-plugin/public'; +import type { IndexPatternFieldEditorStart } from '@kbn/data-view-field-editor-plugin/public'; +import type { DataViewsServicePublic } from '@kbn/data-views-plugin/public'; import type { SpacesPluginStart } from '@kbn/spaces-plugin/public'; -import { FieldFormatsStart } from '@kbn/field-formats-plugin/public'; -import { DataViewEditorStart } from '@kbn/data-view-editor-plugin/public'; -import { ContentManagementPublicStart } from '@kbn/content-management-plugin/public'; -import { TriggersAndActionsUIPublicPluginStart } from '@kbn/triggers-actions-ui-plugin/public'; +import type { FieldFormatsStart } from '@kbn/field-formats-plugin/public'; +import type { DataViewEditorStart } from '@kbn/data-view-editor-plugin/public'; +import type { ContentManagementPublicStart } from '@kbn/content-management-plugin/public'; +import type { TriggersAndActionsUIPublicPluginStart } from '@kbn/triggers-actions-ui-plugin/public'; import type { SavedObjectTaggingOssPluginStart } from '@kbn/saved-objects-tagging-oss-plugin/public'; import type { SavedObjectsManagementPluginStart } from '@kbn/saved-objects-management-plugin/public'; import type { SavedSearchPublicPluginStart } from '@kbn/saved-search-plugin/public'; @@ -43,8 +43,7 @@ import type { DataVisualizerPluginStart } from '@kbn/data-visualizer-plugin/publ import type { FieldsMetadataPublicStart } from '@kbn/fields-metadata-plugin/public'; import type { LogsDataAccessPluginStart } from '@kbn/logs-data-access-plugin/public'; import type { DiscoverSharedPublicStart } from '@kbn/discover-shared-plugin/public'; -import { DiscoverAppLocator } from '../common'; -import { DiscoverCustomizationContext } from './customizations'; +import type { DiscoverAppLocator } from '../common'; import { type DiscoverContainerProps } from './components/discover_container'; /** @@ -82,11 +81,6 @@ export interface DiscoverSetup { * ``` */ readonly locator: undefined | DiscoverAppLocator; - readonly showInlineTopNav: () => void; - readonly configureInlineTopNav: ( - projectNavId: string, - options: DiscoverCustomizationContext['inlineTopNav'] - ) => void; } export interface DiscoverStart { diff --git a/src/platform/plugins/shared/esql/kibana.jsonc b/src/platform/plugins/shared/esql/kibana.jsonc index 2f2e765f0b774..56fb397f09870 100644 --- a/src/platform/plugins/shared/esql/kibana.jsonc +++ b/src/platform/plugins/shared/esql/kibana.jsonc @@ -18,7 +18,7 @@ "expressions", "dataViews", "uiActions", - "contentManagement" + "contentManagement", ], "requiredBundles": [ "kibanaReact", diff --git a/src/platform/plugins/shared/esql/public/index.ts b/src/platform/plugins/shared/esql/public/index.ts index 90473418e24b5..89bbf477124fd 100644 --- a/src/platform/plugins/shared/esql/public/index.ts +++ b/src/platform/plugins/shared/esql/public/index.ts @@ -10,6 +10,7 @@ import { EsqlPlugin, type EsqlPluginStart } from './plugin'; export { ESQLLangEditor } from './create_editor'; +export { type ESQLControlState, EsqlControlType } from './triggers/esql_controls/types'; export type { ESQLEditorProps } from '@kbn/esql-editor'; export type { EsqlPluginStart }; diff --git a/src/platform/plugins/shared/esql/public/kibana_services.ts b/src/platform/plugins/shared/esql/public/kibana_services.ts index 8c348cf4d287c..c15ab734a6f47 100644 --- a/src/platform/plugins/shared/esql/public/kibana_services.ts +++ b/src/platform/plugins/shared/esql/public/kibana_services.ts @@ -15,6 +15,7 @@ import type { Storage } from '@kbn/kibana-utils-plugin/public'; import type { IndexManagementPluginSetup } from '@kbn/index-management-shared-types'; import type { FieldsMetadataPublicStart } from '@kbn/fields-metadata-plugin/public'; import type { UsageCollectionStart } from '@kbn/usage-collection-plugin/public'; +import type { UiActionsStart } from '@kbn/ui-actions-plugin/public'; import type { EsqlPluginStart } from './plugin'; export let core: CoreStart; @@ -24,6 +25,7 @@ interface ServiceDeps { dataViews: DataViewsPublicPluginStart; expressions: ExpressionsStart; storage: Storage; + uiActions: UiActionsStart; indexManagementApiService?: IndexManagementPluginSetup['apiService']; fieldsMetadata?: FieldsMetadataPublicStart; usageCollection?: UsageCollectionStart; @@ -49,6 +51,7 @@ export const setKibanaServices = ( dataViews: DataViewsPublicPluginStart, expressions: ExpressionsStart, storage: Storage, + uiActions: UiActionsStart, indexManagement?: IndexManagementPluginSetup, fieldsMetadata?: FieldsMetadataPublicStart, usageCollection?: UsageCollectionStart @@ -59,6 +62,7 @@ export const setKibanaServices = ( dataViews, expressions, storage, + uiActions, indexManagementApiService: indexManagement?.apiService, fieldsMetadata, usageCollection, diff --git a/src/platform/plugins/shared/esql/public/plugin.ts b/src/platform/plugins/shared/esql/public/plugin.ts index a196c4c974e2d..21786e041a8c6 100755 --- a/src/platform/plugins/shared/esql/public/plugin.ts +++ b/src/platform/plugins/shared/esql/public/plugin.ts @@ -20,10 +20,14 @@ import { updateESQLQueryTrigger, UpdateESQLQueryAction, UPDATE_ESQL_QUERY_TRIGGER, + esqlControlTrigger, + CreateESQLControlAction, + ESQL_CONTROL_TRIGGER, } from './triggers'; import { setKibanaServices } from './kibana_services'; import { JoinIndicesAutocompleteResult } from '../common'; import { cacheNonParametrizedAsyncFunction } from './util/cache'; +import { EsqlVariablesService } from './variables_service'; interface EsqlPluginSetupDependencies { indexManagement: IndexManagementPluginSetup; @@ -41,6 +45,7 @@ interface EsqlPluginStartDependencies { export interface EsqlPluginStart { getJoinIndicesAutocomplete: () => Promise; + variablesService: EsqlVariablesService; } export class EsqlPlugin implements Plugin<{}, EsqlPluginStart> { @@ -50,6 +55,7 @@ export class EsqlPlugin implements Plugin<{}, EsqlPluginStart> { this.indexManagement = indexManagement; uiActions.registerTrigger(updateESQLQueryTrigger); + uiActions.registerTrigger(esqlControlTrigger); return {}; } @@ -66,9 +72,15 @@ export class EsqlPlugin implements Plugin<{}, EsqlPluginStart> { }: EsqlPluginStartDependencies ): EsqlPluginStart { const storage = new Storage(localStorage); + + // Register triggers const appendESQLAction = new UpdateESQLQueryAction(data); uiActions.addTriggerAction(UPDATE_ESQL_QUERY_TRIGGER, appendESQLAction); + const createESQLControlAction = new CreateESQLControlAction(core, data.search.search); + uiActions.addTriggerAction(ESQL_CONTROL_TRIGGER, createESQLControlAction); + + const variablesService = new EsqlVariablesService(); const getJoinIndicesAutocomplete = cacheNonParametrizedAsyncFunction( async () => { @@ -84,6 +96,7 @@ export class EsqlPlugin implements Plugin<{}, EsqlPluginStart> { const start = { getJoinIndicesAutocomplete, + variablesService, }; setKibanaServices( @@ -92,6 +105,7 @@ export class EsqlPlugin implements Plugin<{}, EsqlPluginStart> { dataViews, expressions, storage, + uiActions, this.indexManagement, fieldsMetadata, usageCollection diff --git a/src/platform/plugins/shared/esql/public/triggers/esql_controls/control_flyout/choose_column_popover.test.tsx b/src/platform/plugins/shared/esql/public/triggers/esql_controls/control_flyout/choose_column_popover.test.tsx new file mode 100644 index 0000000000000..0a1a997a36179 --- /dev/null +++ b/src/platform/plugins/shared/esql/public/triggers/esql_controls/control_flyout/choose_column_popover.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", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import React from 'react'; +import { render, screen, fireEvent } from '@testing-library/react'; +import { ChooseColumnPopover } from './choose_column_popover'; + +describe('ChooseColumnPopover', () => { + it('should render a search input and a list', () => { + render(); + // open the popover + screen.getByTestId('chooseColumnBtn').click(); + // expect the search input to be rendered + expect(screen.getByTestId('selectableColumnSearch')).toBeInTheDocument(); + expect(screen.getByTestId('selectableColumnList')).toBeInTheDocument(); + }); + + it('should update the list when there is a text in the input', () => { + render(); + // open the popover + screen.getByTestId('chooseColumnBtn').click(); + // expect the search input to be rendered + + // type in the search input + const input = screen.getByTestId('selectableColumnSearch'); + fireEvent.change(input, { target: { value: 'col2' } }); + + // get the list + const list = screen.getByTestId('selectableColumnList'); + const listItems = list.querySelector('li'); + expect(listItems).toHaveTextContent('col2'); + }); + + it('should call the updateQuery prop if a list item is clicked', () => { + const updateQuerySpy = jest.fn(); + render(); + // open the popover + screen.getByTestId('chooseColumnBtn').click(); + // expect the search input to be rendered + + // type in the search input + const input = screen.getByTestId('selectableColumnSearch'); + fireEvent.change(input, { target: { value: 'col2' } }); + + const list = screen.getByTestId('selectableColumnList'); + const listItems = list.querySelector('li'); + + // click the list item + if (listItems) fireEvent.click(listItems); + expect(updateQuerySpy).toHaveBeenCalledWith('col2'); + }); +}); diff --git a/src/platform/plugins/shared/esql/public/triggers/esql_controls/control_flyout/choose_column_popover.tsx b/src/platform/plugins/shared/esql/public/triggers/esql_controls/control_flyout/choose_column_popover.tsx new file mode 100644 index 0000000000000..b9f84e4d545d6 --- /dev/null +++ b/src/platform/plugins/shared/esql/public/triggers/esql_controls/control_flyout/choose_column_popover.tsx @@ -0,0 +1,83 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import React, { useCallback, useState } from 'react'; +import { i18n } from '@kbn/i18n'; +import { EuiLink, EuiPopover, EuiSelectable, EuiSelectableOption } from '@elastic/eui'; +import { css } from '@emotion/react'; + +export function ChooseColumnPopover({ + columns, + updateQuery, +}: { + columns: string[]; + updateQuery: (column: string) => void; +}) { + const [isPopoverOpen, setIsPopoverOpen] = useState(false); + const [options, setOptions] = useState( + columns.map((column) => ({ label: column })) + ); + + const onButtonClick = () => setIsPopoverOpen((status) => !status); + const closePopover = () => setIsPopoverOpen(false); + + const button = ( + + {i18n.translate('esql.flyout.chooseColumnBtn.label', { + defaultMessage: 'here', + })} + + ); + + const onColumnChange = useCallback( + (newOptions: EuiSelectableOption[]) => { + setOptions(newOptions); + + const selectedColumn = newOptions.find((option) => option.checked === 'on'); + if (selectedColumn) { + updateQuery(selectedColumn.label); + } + }, + [updateQuery] + ); + + return ( + + + {(list, search) => ( + <> + {search} + {list} + + )} + + + ); +} diff --git a/src/platform/plugins/shared/esql/public/triggers/esql_controls/control_flyout/field_control_form.test.tsx b/src/platform/plugins/shared/esql/public/triggers/esql_controls/control_flyout/field_control_form.test.tsx new file mode 100644 index 0000000000000..dba47a4618b25 --- /dev/null +++ b/src/platform/plugins/shared/esql/public/triggers/esql_controls/control_flyout/field_control_form.test.tsx @@ -0,0 +1,201 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import React from 'react'; +import { render, within, fireEvent } from '@testing-library/react'; +import { monaco } from '@kbn/monaco'; +import { dataPluginMock } from '@kbn/data-plugin/public/mocks'; +import { ESQLVariableType } from '@kbn/esql-validation-autocomplete'; +import { FieldControlForm } from './field_control_form'; +import { ESQLControlState, EsqlControlType } from '../types'; + +jest.mock('@kbn/esql-utils', () => ({ + getESQLQueryColumnsRaw: jest.fn().mockResolvedValue([{ name: 'column1' }, { name: 'column2' }]), +})); + +describe('FieldControlForm', () => { + const dataMock = dataPluginMock.createStartContract(); + const searchMock = dataMock.search.search; + + it('should default correctly if no initial state is given', async () => { + const { findByTestId, findByTitle } = render( + + ); + // control type dropdown should be rendered and default to 'STATIC_VALUES' + // no need to test further as the control type is disabled + expect(await findByTestId('esqlControlTypeDropdown')).toBeInTheDocument(); + const controlTypeInputPopover = await findByTestId('esqlControlTypeInputPopover'); + expect(within(controlTypeInputPopover).getByRole('combobox')).toHaveValue(`Static values`); + + // variable name input should be rendered and with the default value + expect(await findByTestId('esqlVariableName')).toHaveValue('field'); + + // fields dropdown should be rendered with available fields column1 and column2 + const fieldsOptionsDropdown = await findByTestId('esqlFieldsOptions'); + expect(fieldsOptionsDropdown).toBeInTheDocument(); + const fieldsOptionsDropdownSearchInput = within(fieldsOptionsDropdown).getByRole('combobox'); + fireEvent.click(fieldsOptionsDropdownSearchInput); + expect(fieldsOptionsDropdownSearchInput).toHaveValue(''); + expect(await findByTitle('column1')).toBeDefined(); + expect(await findByTitle('column2')).toBeDefined(); + + // variable label input should be rendered and with the default value (empty) + expect(await findByTestId('esqlControlLabel')).toHaveValue(''); + + // control width dropdown should be rendered and default to 'MEDIUM' + expect(await findByTestId('esqlControlMinimumWidth')).toBeInTheDocument(); + const pressedWidth = within(await findByTestId('esqlControlMinimumWidth')).getByTitle('Medium'); + expect(pressedWidth).toHaveAttribute('aria-pressed', 'true'); + + // control grow switch should be rendered and default to 'false' + expect(await findByTestId('esqlControlGrow')).toBeInTheDocument(); + const growSwitch = await findByTestId('esqlControlGrow'); + expect(growSwitch).not.toBeChecked(); + }); + + it('should call the onCreateControl callback, if no initialState is given', async () => { + const onCreateControlSpy = jest.fn(); + const { findByTestId, findByTitle } = render( + + ); + + // select the first field + const fieldsOptionsDropdownSearchInput = within( + await findByTestId('esqlFieldsOptions') + ).getByRole('combobox'); + fireEvent.click(fieldsOptionsDropdownSearchInput); + fireEvent.click(await findByTitle('column1')); + // click on the create button + fireEvent.click(await findByTestId('saveEsqlControlsFlyoutButton')); + expect(onCreateControlSpy).toHaveBeenCalled(); + }); + + it('should call the onCancelControl callback, if Cancel button is clicked', async () => { + const onCancelControlSpy = jest.fn(); + const { findByTestId } = render( + + ); + // click on the cancel button + fireEvent.click(await findByTestId('cancelEsqlControlsFlyoutButton')); + expect(onCancelControlSpy).toHaveBeenCalled(); + }); + + it('should default correctly if initial state is given', async () => { + const initialState = { + grow: true, + width: 'small', + title: 'my control', + availableOptions: ['column2'], + selectedOptions: ['column2'], + variableName: 'myField', + variableType: ESQLVariableType.FIELDS, + esqlQuery: 'FROM foo | STATS BY', + controlType: EsqlControlType.STATIC_VALUES, + } as ESQLControlState; + const { findByTestId } = render( + + ); + // variable name input should be rendered and with the default value + expect(await findByTestId('esqlVariableName')).toHaveValue('myField'); + + // fields dropdown should be rendered with column2 selected + const fieldsOptionsDropdown = await findByTestId('esqlFieldsOptions'); + const fieldsOptionsDropdownBadge = within(fieldsOptionsDropdown).getByTestId('column2'); + expect(fieldsOptionsDropdownBadge).toBeInTheDocument(); + + // variable label input should be rendered and with the default value (my control) + expect(await findByTestId('esqlControlLabel')).toHaveValue('my control'); + + // control width dropdown should be rendered and default to 'MEDIUM' + expect(await findByTestId('esqlControlMinimumWidth')).toBeInTheDocument(); + const pressedWidth = within(await findByTestId('esqlControlMinimumWidth')).getByTitle('Small'); + expect(pressedWidth).toHaveAttribute('aria-pressed', 'true'); + + // control grow switch should be rendered and default to 'false' + expect(await findByTestId('esqlControlGrow')).toBeInTheDocument(); + const growSwitch = await findByTestId('esqlControlGrow'); + expect(growSwitch).toBeChecked(); + }); + + it('should call the onEditControl callback, if initialState is given', async () => { + const initialState = { + grow: true, + width: 'small', + title: 'my control', + availableOptions: ['column2'], + selectedOptions: ['column2'], + variableName: 'myField', + variableType: ESQLVariableType.FIELDS, + esqlQuery: 'FROM foo | STATS BY', + controlType: EsqlControlType.STATIC_VALUES, + } as ESQLControlState; + const onEditControlSpy = jest.fn(); + const { findByTestId, findByTitle } = render( + + ); + + // select the first field + const fieldsOptionsDropdownSearchInput = within( + await findByTestId('esqlFieldsOptions') + ).getByRole('combobox'); + fireEvent.click(fieldsOptionsDropdownSearchInput); + fireEvent.click(await findByTitle('column1')); + // click on the create button + fireEvent.click(await findByTestId('saveEsqlControlsFlyoutButton')); + expect(onEditControlSpy).toHaveBeenCalled(); + }); +}); diff --git a/src/platform/plugins/shared/esql/public/triggers/esql_controls/control_flyout/field_control_form.tsx b/src/platform/plugins/shared/esql/public/triggers/esql_controls/control_flyout/field_control_form.tsx new file mode 100644 index 0000000000000..3fe61b6398245 --- /dev/null +++ b/src/platform/plugins/shared/esql/public/triggers/esql_controls/control_flyout/field_control_form.tsx @@ -0,0 +1,278 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import React, { useCallback, useState, useMemo, useEffect } from 'react'; +import { i18n } from '@kbn/i18n'; +import { + EuiComboBox, + EuiFormRow, + EuiFlyoutBody, + type EuiSwitchEvent, + type EuiComboBoxOptionOption, +} from '@elastic/eui'; +import { css } from '@emotion/react'; +import { monaco } from '@kbn/monaco'; +import type { ISearchGeneric } from '@kbn/search-types'; +import { ESQLVariableType, ESQLControlVariable } from '@kbn/esql-validation-autocomplete'; +import { getESQLQueryColumnsRaw } from '@kbn/esql-utils'; +import type { ESQLControlState, ControlWidthOptions } from '../types'; +import { + Header, + Footer, + ControlWidth, + ControlType, + VariableName, + ControlLabel, +} from './shared_form_components'; +import { + getRecurrentVariableName, + getFlyoutStyling, + getQueryForFields, + validateVariableName, +} from './helpers'; +import { EsqlControlType } from '../types'; + +interface FieldControlFormProps { + search: ISearchGeneric; + variableType: ESQLVariableType; + queryString: string; + esqlVariables: ESQLControlVariable[]; + closeFlyout: () => void; + onCreateControl: (state: ESQLControlState, variableName: string) => void; + onEditControl: (state: ESQLControlState) => void; + cursorPosition?: monaco.Position; + initialState?: ESQLControlState; + onCancelControl?: () => void; +} + +export function FieldControlForm({ + variableType, + initialState, + queryString, + esqlVariables, + cursorPosition, + onCreateControl, + onEditControl, + onCancelControl, + search, + closeFlyout, +}: FieldControlFormProps) { + const suggestedVariableName = useMemo(() => { + const existingVariables = esqlVariables.filter((variable) => variable.type === variableType); + + return initialState + ? `${initialState.variableName}` + : getRecurrentVariableName( + 'field', + existingVariables.map((variable) => variable.key) + ); + }, [esqlVariables, initialState, variableType]); + + const [availableFieldsOptions, setAvailableFieldsOptions] = useState( + [] + ); + + const [selectedFields, setSelectedFields] = useState( + initialState + ? initialState.availableOptions.map((option) => { + return { + label: option, + key: option, + 'data-test-subj': option, + }; + }) + : [] + ); + const [formIsInvalid, setFormIsInvalid] = useState(false); + const [variableName, setVariableName] = useState(suggestedVariableName); + const [label, setLabel] = useState(initialState?.title ?? ''); + const [minimumWidth, setMinimumWidth] = useState(initialState?.width ?? 'medium'); + const [grow, setGrow] = useState(initialState?.grow ?? false); + + const isControlInEditMode = useMemo(() => !!initialState, [initialState]); + + useEffect(() => { + if (!availableFieldsOptions.length) { + const queryForFields = getQueryForFields(queryString, cursorPosition); + getESQLQueryColumnsRaw({ + esqlQuery: queryForFields, + search, + }).then((columns) => { + setAvailableFieldsOptions( + columns.map((col) => { + return { + label: col.name, + key: col.name, + 'data-test-subj': col.name, + }; + }) + ); + }); + } + }, [availableFieldsOptions.length, variableType, cursorPosition, queryString, search]); + + useEffect(() => { + const variableExists = + esqlVariables.some((variable) => variable.key === variableName.replace('?', '')) && + !isControlInEditMode; + + setFormIsInvalid(!selectedFields.length || !variableName || variableExists); + }, [esqlVariables, isControlInEditMode, selectedFields.length, variableName]); + + const onFieldsChange = useCallback((selectedOptions: EuiComboBoxOptionOption[]) => { + setSelectedFields(selectedOptions); + }, []); + + const onVariableNameChange = useCallback( + (e: { target: { value: React.SetStateAction } }) => { + const text = validateVariableName(String(e.target.value)); + setVariableName(text); + }, + [] + ); + + const onLabelChange = useCallback((e: { target: { value: React.SetStateAction } }) => { + setLabel(e.target.value); + }, []); + + const onMinimumSizeChange = useCallback((optionId: string) => { + if (optionId) { + setMinimumWidth(optionId as ControlWidthOptions); + } + }, []); + + const onGrowChange = useCallback((e: EuiSwitchEvent) => { + setGrow(e.target.checked); + }, []); + + const onCreateOption = useCallback( + (searchValue: string, flattenedOptions: EuiComboBoxOptionOption[] = []) => { + if (!searchValue.trim()) { + return; + } + + const normalizedSearchValue = searchValue.trim().toLowerCase(); + + const newOption = { + label: searchValue, + key: searchValue, + 'data-test-subj': searchValue, + }; + + if ( + flattenedOptions.findIndex( + (option) => option.label.trim().toLowerCase() === normalizedSearchValue + ) === -1 + ) { + setAvailableFieldsOptions([...availableFieldsOptions, newOption]); + } + + setSelectedFields((prevSelected) => [...prevSelected, newOption]); + }, + [availableFieldsOptions] + ); + + const onCreateFieldControl = useCallback(async () => { + const availableOptions = selectedFields.map((field) => field.label); + const state = { + availableOptions, + selectedOptions: [availableOptions[0]], + width: minimumWidth, + title: label || variableName, + variableName, + variableType, + controlType: EsqlControlType.STATIC_VALUES, + esqlQuery: queryString, + grow, + }; + + if (availableOptions.length) { + if (!isControlInEditMode) { + await onCreateControl(state, variableName); + } else { + onEditControl(state); + } + } + closeFlyout(); + }, [ + selectedFields, + minimumWidth, + label, + variableName, + variableType, + queryString, + grow, + isControlInEditMode, + closeFlyout, + onCreateControl, + onEditControl, + ]); + + const styling = useMemo(() => getFlyoutStyling(), []); + + return ( + <> +
+ + + + + + + + + + + + + +
+ + ); +} diff --git a/src/platform/plugins/shared/esql/public/triggers/esql_controls/control_flyout/helpers.test.ts b/src/platform/plugins/shared/esql/public/triggers/esql_controls/control_flyout/helpers.test.ts new file mode 100644 index 0000000000000..c555f03d7da70 --- /dev/null +++ b/src/platform/plugins/shared/esql/public/triggers/esql_controls/control_flyout/helpers.test.ts @@ -0,0 +1,139 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ +import { monaco } from '@kbn/monaco'; +import { + updateQueryStringWithVariable, + getQueryForFields, + areValuesIntervalsValid, + getRecurrentVariableName, + getValuesFromQueryField, + appendStatsByToQuery, + validateVariableName, +} from './helpers'; + +describe('helpers', () => { + describe('updateQueryStringWithVariable', () => { + it('should update the query string with the variable for an one line query string', () => { + const queryString = 'FROM my_index | STATS BY '; + const variable = 'my_variable'; + const cursorPosition = { column: 26, lineNumber: 1 } as monaco.Position; + const updatedQueryString = updateQueryStringWithVariable( + queryString, + variable, + cursorPosition + ); + expect(updatedQueryString).toBe('FROM my_index | STATS BY ?my_variable'); + }); + + it('should update the query string with the variable for multiline query string', () => { + const queryString = 'FROM my_index \n| STATS BY '; + const variable = 'my_variable'; + const cursorPosition = { column: 12, lineNumber: 2 } as monaco.Position; + const updatedQueryString = updateQueryStringWithVariable( + queryString, + variable, + cursorPosition + ); + expect(updatedQueryString).toBe('FROM my_index \n| STATS BY ?my_variable'); + }); + }); + + describe('getQueryForFields', () => { + it('should return the query to retrieve the fields for an one liner base query string', () => { + const queryString = 'FROM my_index | LIMIT 10 | WHERE a =='; + const cursorPosition = { column: 37, lineNumber: 1 } as monaco.Position; + const queryForFields = getQueryForFields(queryString, cursorPosition); + expect(queryForFields).toBe('FROM my_index | LIMIT 10 '); + }); + + it('should return the query to retrieve the fields for a multi liner base query string', () => { + const queryString = 'FROM my_index \n| LIMIT 10 \n| WHERE a =='; + const cursorPosition = { column: 12, lineNumber: 3 } as monaco.Position; + const queryForFields = getQueryForFields(queryString, cursorPosition); + expect(queryForFields).toBe('FROM my_index \n| LIMIT 10 '); + }); + }); + + describe('areValuesIntervalsValid', () => { + it('should return true if all values are valid intervals', () => { + const values = ['1d', '2h', '3m', '4 seconds']; + const isValid = areValuesIntervalsValid(values); + expect(isValid).toBe(true); + }); + + it('should return false if any value is not a valid interval', () => { + const values = ['1d', '2h', '3m', 'invalid']; + const isValid = areValuesIntervalsValid(values); + expect(isValid).toBe(false); + }); + }); + + describe('getRecurrentVariableName', () => { + it('should return a new name if the name already exists', () => { + const name = 'field'; + const existingNames = ['field', 'field1', 'field2']; + const newName = getRecurrentVariableName(name, existingNames); + expect(newName).toBe('field3'); + }); + + it('should return the same name if the name does not exist', () => { + const name = 'field'; + const existingNames = ['field1', 'field2']; + const newName = getRecurrentVariableName(name, existingNames); + expect(newName).toBe('field'); + }); + }); + + describe('getValuesFromQueryField', () => { + it('should return the values from the query field', () => { + const queryString = 'FROM my_index | WHERE my_field =='; + const values = getValuesFromQueryField(queryString); + expect(values).toEqual('my_field'); + }); + + it('should return the values from the query field with new lines', () => { + const queryString = 'FROM my_index \n| WHERE my_field >='; + const values = getValuesFromQueryField(queryString); + expect(values).toEqual('my_field'); + }); + }); + + describe('appendStatsByToQuery', () => { + it('should append the stats by clause to the query', () => { + const queryString = 'FROM my_index'; + const statsBy = 'my_field'; + const updatedQueryString = appendStatsByToQuery(queryString, statsBy); + expect(updatedQueryString).toBe('FROM my_index\n| STATS BY my_field'); + }); + + it('should append the stats by clause to the query with existing clauses', () => { + const queryString = 'FROM my_index | LIMIT 10 | STATS BY meow'; + const statsBy = 'my_field'; + const updatedQueryString = appendStatsByToQuery(queryString, statsBy); + expect(updatedQueryString).toBe('FROM my_index | LIMIT 10\n| STATS BY my_field'); + }); + }); + + describe('validateVariableName', () => { + it('should return the variable without special characters', () => { + const variable = validateVariableName('my_variable/123'); + expect(variable).toBe('my_variable123'); + }); + + it('should remove the questionarks', () => { + const variable = validateVariableName('?my_variable'); + expect(variable).toBe('my_variable'); + }); + + it('should remove the _ in the first char', () => { + const variable = validateVariableName('?_my_variable'); + expect(variable).toBe('my_variable'); + }); + }); +}); diff --git a/src/platform/plugins/shared/esql/public/triggers/esql_controls/control_flyout/helpers.ts b/src/platform/plugins/shared/esql/public/triggers/esql_controls/control_flyout/helpers.ts new file mode 100644 index 0000000000000..2a49d6aa2ed4e --- /dev/null +++ b/src/platform/plugins/shared/esql/public/triggers/esql_controls/control_flyout/helpers.ts @@ -0,0 +1,128 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ +import { monaco } from '@kbn/monaco'; +import { inKnownTimeInterval } from '@kbn/esql-validation-autocomplete'; +import { type ESQLColumn, parse, walk, mutate, BasicPrettyPrinter, Walker } from '@kbn/esql-ast'; + +export const updateQueryStringWithVariable = ( + queryString: string, + variable: string, + cursorPosition: monaco.Position +) => { + const variableName = `?${variable}`; + const cursorColumn = cursorPosition?.column ?? 0; + const cursorLine = cursorPosition?.lineNumber ?? 0; + const lines = queryString.split('\n'); + + if (lines.length > 1) { + const queryArray = queryString.split('\n'); + const queryPartToBeUpdated = queryArray[cursorLine - 1]; + const queryWithVariable = [ + queryPartToBeUpdated.slice(0, cursorColumn - 1), + variableName, + queryPartToBeUpdated.slice(cursorColumn - 1), + ].join(''); + queryArray[cursorLine - 1] = queryWithVariable; + return queryArray.join('\n'); + } + + return [ + queryString.slice(0, cursorColumn - 1), + variableName, + queryString.slice(cursorColumn - 1), + ].join(''); +}; + +export const getQueryForFields = (queryString: string, cursorPosition?: monaco.Position) => { + const cursorColumn = cursorPosition?.column ?? 0; + const cursorLine = cursorPosition?.lineNumber ?? 0; + const lines = queryString.split('\n'); + + if (lines.length > 1) { + const queryArray = queryString.split('\n'); + const lineToBeUpdated = cursorLine - 1; + return queryArray.slice(0, lineToBeUpdated).join('\n'); + } + const queryBefore = queryString.slice(0, cursorColumn - 1); + const pipes = queryBefore.split('|'); + return pipes.slice(0, pipes.length - 1).join('|'); +}; + +export const areValuesIntervalsValid = (values: string[]) => { + return values.every((value) => { + // remove digits and empty spaces from the string to get the unit + const unit = value.replace(/[0-9]/g, '').replace(/\s/g, ''); + return inKnownTimeInterval(unit); + }); +}; + +export const getRecurrentVariableName = (name: string, existingNames: string[]) => { + let newName = name; + let i = 1; + while (existingNames.includes(newName)) { + newName = `${name}${i}`; + i++; + } + return newName; +}; + +export const getValuesFromQueryField = (queryString: string) => { + const validQuery = `${queryString} ""`; + const { root } = parse(validQuery); + const lastCommand = root.commands[root.commands.length - 1]; + const columns: ESQLColumn[] = []; + + walk(lastCommand, { + visitColumn: (node) => columns.push(node), + }); + + const column = Walker.match(lastCommand, { type: 'column' }); + + if (column) { + return `${column.name}`; + } +}; + +export const getFlyoutStyling = () => { + return ` + .euiFlyoutBody__overflow { + -webkit-mask-image: none; + padding-left: inherit; + margin-left: inherit; + transform: initial; + } + .euiFlyoutBody__overflowContent { + block-size: 100%; + } + `; +}; + +export const appendStatsByToQuery = (queryString: string, column: string) => { + const { root } = parse(queryString); + const lastCommand = root.commands[root.commands.length - 1]; + if (lastCommand.name === 'stats') { + const statsCommand = lastCommand; + mutate.generic.commands.remove(root, statsCommand); + const queryWithoutStats = BasicPrettyPrinter.print(root); + return `${queryWithoutStats}\n| STATS BY ${column}`; + } else { + return `${queryString}\n| STATS BY ${column}`; + } +}; + +export const validateVariableName = (variableName: string) => { + let text = variableName + // variable name can only contain letters, numbers and underscores + .replace(/[^a-zA-Z0-9_]/g, ''); + if (text.charAt(0) === '_') { + text = text.substring(1); + } + + return text; +}; diff --git a/src/platform/plugins/shared/esql/public/triggers/esql_controls/control_flyout/index.tsx b/src/platform/plugins/shared/esql/public/triggers/esql_controls/control_flyout/index.tsx new file mode 100644 index 0000000000000..18a5396f9d14c --- /dev/null +++ b/src/platform/plugins/shared/esql/public/triggers/esql_controls/control_flyout/index.tsx @@ -0,0 +1,92 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import React, { useCallback } from 'react'; +import { ESQLVariableType, ESQLControlVariable } from '@kbn/esql-validation-autocomplete'; +import type { ISearchGeneric } from '@kbn/search-types'; +import { monaco } from '@kbn/monaco'; +import type { ESQLControlState } from '../types'; +import { ValueControlForm } from './value_control_form'; +import { FieldControlForm } from './field_control_form'; +import { updateQueryStringWithVariable } from './helpers'; + +interface ESQLControlsFlyoutProps { + search: ISearchGeneric; + variableType: ESQLVariableType; + queryString: string; + esqlVariables: ESQLControlVariable[]; + onSaveControl?: (controlState: ESQLControlState, updatedQuery: string) => Promise; + onCancelControl?: () => void; + cursorPosition?: monaco.Position; + initialState?: ESQLControlState; + closeFlyout: () => void; +} + +export function ESQLControlsFlyout({ + search, + variableType, + queryString, + esqlVariables, + onSaveControl, + onCancelControl, + cursorPosition, + initialState, + closeFlyout, +}: ESQLControlsFlyoutProps) { + const onCreateControl = useCallback( + async (state: ESQLControlState, variableName: string) => { + if (cursorPosition) { + const query = updateQueryStringWithVariable(queryString, variableName, cursorPosition); + + await onSaveControl?.(state, query); + } + }, + [cursorPosition, onSaveControl, queryString] + ); + + const onEditControl = useCallback( + async (state: ESQLControlState) => { + await onSaveControl?.(state, ''); + }, + [onSaveControl] + ); + + if (variableType === ESQLVariableType.VALUES || variableType === ESQLVariableType.TIME_LITERAL) { + return ( + + ); + } else if (variableType === ESQLVariableType.FIELDS) { + return ( + + ); + } + + return null; +} diff --git a/src/platform/plugins/shared/esql/public/triggers/esql_controls/control_flyout/shared_form_components.tsx b/src/platform/plugins/shared/esql/public/triggers/esql_controls/control_flyout/shared_form_components.tsx new file mode 100644 index 0000000000000..a654cd0e880c1 --- /dev/null +++ b/src/platform/plugins/shared/esql/public/triggers/esql_controls/control_flyout/shared_form_components.tsx @@ -0,0 +1,397 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import React, { useCallback } from 'react'; +import { i18n } from '@kbn/i18n'; +import { css } from '@emotion/react'; +import { ESQLControlVariable } from '@kbn/esql-validation-autocomplete'; +import { TooltipWrapper } from '@kbn/visualization-utils'; +import { + EuiFieldText, + EuiFormRow, + EuiComboBox, + type EuiComboBoxOptionOption, + EuiButtonGroup, + EuiSpacer, + EuiSwitch, + type EuiSwitchEvent, + EuiFlyoutFooter, + EuiFlexGroup, + EuiFlexItem, + EuiButtonEmpty, + EuiButton, + EuiFlyoutHeader, + EuiTitle, + EuiBetaBadge, + EuiToolTip, + EuiText, + EuiTextColor, +} from '@elastic/eui'; +import { EsqlControlType } from '../types'; + +const controlTypeOptions = [ + { + label: i18n.translate('esql.flyout.controlTypeOptions.staticValuesLabel', { + defaultMessage: 'Static values', + }), + 'data-test-subj': 'staticValues', + key: EsqlControlType.STATIC_VALUES, + }, + { + label: i18n.translate('esql.flyout.controlTypeOptions.valuesFromQueryLabel', { + defaultMessage: 'Values from a query', + }), + 'data-test-subj': 'valuesFromQuery', + key: EsqlControlType.VALUES_FROM_QUERY, + }, +]; + +const minimumWidthButtonGroup = [ + { + id: `small`, + label: i18n.translate('esql.flyout.minimumWidth.small', { + defaultMessage: 'Small', + }), + }, + { + id: `medium`, + label: i18n.translate('esql.flyout.minimumWidth.medium', { + defaultMessage: 'Medium', + }), + }, + { + id: `large`, + label: i18n.translate('esql.flyout.minimumWidth.large', { + defaultMessage: 'Large', + }), + }, +]; + +export function ControlType({ + isDisabled, + initialControlFlyoutType, + onFlyoutTypeChange, +}: { + isDisabled: boolean; + initialControlFlyoutType: EsqlControlType; + onFlyoutTypeChange?: (flyoutType: EsqlControlType) => void; +}) { + const controlFlyoutType = controlTypeOptions.find( + (option) => option.key === initialControlFlyoutType + )!; + + const onTypeChange = useCallback( + (selectedOptions: EuiComboBoxOptionOption[]) => { + const flyoutType = controlTypeOptions.find( + (option) => option.key === selectedOptions[0].key + )!; + onFlyoutTypeChange?.(flyoutType.key); + }, + [onFlyoutTypeChange] + ); + + return ( + <> + + + + + + + + ); +} + +export function VariableName({ + variableName, + isControlInEditMode, + esqlVariables = [], + onVariableNameChange, +}: { + variableName: string; + isControlInEditMode: boolean; + esqlVariables?: ESQLControlVariable[]; + onVariableNameChange: (e: React.ChangeEvent) => void; +}) { + const genericContent = i18n.translate('esql.flyout.variableName.helpText', { + defaultMessage: 'This name will be prefaced with a "?" in the editor', + }); + const isDisabledTooltipText = i18n.translate('esql.flyout.variableName.disabledTooltip', { + defaultMessage: 'You can’t edit a control name after it’s been created.', + }); + const variableExists = + esqlVariables.some((variable) => variable.key === variableName.replace('?', '')) && + !isControlInEditMode; + return ( + + + + + + ); +} + +export function ControlLabel({ + label, + onLabelChange, +}: { + label: string; + onLabelChange: (e: React.ChangeEvent) => void; +}) { + return ( + + + {i18n.translate('esql.flyout.label.extraLabel', { + defaultMessage: 'Optional', + })} + + + } + fullWidth + > + + + ); +} + +export function ControlWidth({ + minimumWidth, + grow, + onMinimumSizeChange, + onGrowChange, +}: { + minimumWidth: string; + grow: boolean; + onMinimumSizeChange: (id: string) => void; + onGrowChange: (e: EuiSwitchEvent) => void; +}) { + return ( + <> + + onMinimumSizeChange(id)} + type="single" + isFullWidth + data-test-subj="esqlControlMinimumWidth" + /> + + + onGrowChange(e)} + data-test-subj="esqlControlGrow" + /> + + ); +} + +export function Header({ isInEditMode }: { isInEditMode: boolean }) { + return ( + + + + +

+ {isInEditMode + ? i18n.translate('esql.flyout.editTitle', { + defaultMessage: 'Edit ES|QL control', + }) + : i18n.translate('esql.flyout.title', { + defaultMessage: 'Create ES|QL control', + })} +

+
+
+ + + + + +
+
+ ); +} + +export function Footer({ + isControlInEditMode, + variableName, + onCancelControl, + isSaveDisabled, + closeFlyout, + onCreateControl, +}: { + isControlInEditMode: boolean; + variableName: string; + isSaveDisabled: boolean; + closeFlyout: () => void; + onCreateControl: () => void; + onCancelControl?: () => void; +}) { + const onCancel = useCallback(() => { + closeFlyout(); + onCancelControl?.(); + }, [closeFlyout, onCancelControl]); + + return ( + + + + + {i18n.translate('esql.flyout.cancelLabel', { + defaultMessage: 'Cancel', + })} + + + + + {i18n.translate('esql.flyout.saveLabel', { + defaultMessage: 'Save', + })} + + + + + ); +} diff --git a/src/platform/plugins/shared/esql/public/triggers/esql_controls/control_flyout/value_control_form.test.tsx b/src/platform/plugins/shared/esql/public/triggers/esql_controls/control_flyout/value_control_form.test.tsx new file mode 100644 index 0000000000000..22f24631aa602 --- /dev/null +++ b/src/platform/plugins/shared/esql/public/triggers/esql_controls/control_flyout/value_control_form.test.tsx @@ -0,0 +1,260 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import React from 'react'; +import { render, within, fireEvent } from '@testing-library/react'; +import { dataPluginMock } from '@kbn/data-plugin/public/mocks'; +import { IUiSettingsClient } from '@kbn/core/public'; +import { coreMock } from '@kbn/core/server/mocks'; +import { ESQLVariableType } from '@kbn/esql-validation-autocomplete'; +import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public'; +import { __IntlProvider as IntlProvider } from '@kbn/i18n-react'; +import { ValueControlForm } from './value_control_form'; +import { EsqlControlType, ESQLControlState } from '../types'; + +jest.mock('@kbn/esql-utils', () => { + return { + getESQLResults: jest.fn().mockResolvedValue({ + response: { + columns: [ + { + name: 'field', + id: 'field', + meta: { + type: 'keyword', + }, + }, + ], + values: [], + }, + }), + getIndexPatternFromESQLQuery: jest.fn().mockReturnValue('index1'), + getLimitFromESQLQuery: jest.fn().mockReturnValue(1000), + isQueryWrappedByPipes: jest.fn().mockReturnValue(false), + }; +}); + +describe('ValueControlForm', () => { + const dataMock = dataPluginMock.createStartContract(); + const searchMock = dataMock.search.search; + + const uiConfig: Record = {}; + const uiSettings = { + get: (key: string) => uiConfig[key], + } as IUiSettingsClient; + + const services = { + uiSettings, + settings: { + client: uiSettings, + }, + core: coreMock.createStart(), + }; + + describe('Interval type', () => { + it('should default correctly if no initial state is given for an interval variable type', async () => { + const { findByTestId, findByTitle } = render( + + ); + // control type dropdown should be rendered and default to 'STATIC_VALUES' + expect(await findByTestId('esqlControlTypeDropdown')).toBeInTheDocument(); + const controlTypeInputPopover = await findByTestId('esqlControlTypeInputPopover'); + expect(within(controlTypeInputPopover).getByRole('combobox')).toHaveValue(`Static values`); + + // variable name input should be rendered and with the default value + expect(await findByTestId('esqlVariableName')).toHaveValue('interval'); + + // values dropdown should be rendered + const valuesOptionsDropdown = await findByTestId('esqlValuesOptions'); + expect(valuesOptionsDropdown).toBeInTheDocument(); + const valuesOptionsDropdownSearchInput = within(valuesOptionsDropdown).getByRole('combobox'); + fireEvent.click(valuesOptionsDropdownSearchInput); + expect(valuesOptionsDropdownSearchInput).toHaveValue(''); + expect(await findByTitle('5 minutes')).toBeDefined(); + expect(await findByTitle('1 hour')).toBeDefined(); + + // variable label input should be rendered and with the default value (empty) + expect(await findByTestId('esqlControlLabel')).toHaveValue(''); + + // control width dropdown should be rendered and default to 'MEDIUM' + expect(await findByTestId('esqlControlMinimumWidth')).toBeInTheDocument(); + const pressedWidth = within(await findByTestId('esqlControlMinimumWidth')).getByTitle( + 'Medium' + ); + expect(pressedWidth).toHaveAttribute('aria-pressed', 'true'); + + // control grow switch should be rendered and default to 'false' + expect(await findByTestId('esqlControlGrow')).toBeInTheDocument(); + const growSwitch = await findByTestId('esqlControlGrow'); + expect(growSwitch).not.toBeChecked(); + }); + + it('should call the onCreateControl callback, if no initialState is given', async () => { + const onCreateControlSpy = jest.fn(); + const { findByTestId, findByTitle } = render( + + ); + + // select the first interval + const valuesOptionsDropdownSearchInput = within( + await findByTestId('esqlValuesOptions') + ).getByRole('combobox'); + fireEvent.click(valuesOptionsDropdownSearchInput); + fireEvent.click(await findByTitle('5 minutes')); + // click on the create button + fireEvent.click(await findByTestId('saveEsqlControlsFlyoutButton')); + expect(onCreateControlSpy).toHaveBeenCalled(); + }); + + it('should call the onCancelControl callback, if Cancel button is clicked', async () => { + const onCancelControlSpy = jest.fn(); + const { findByTestId } = render( + + ); + // click on the cancel button + fireEvent.click(await findByTestId('cancelEsqlControlsFlyoutButton')); + expect(onCancelControlSpy).toHaveBeenCalled(); + }); + + it('should default correctly if initial state is given', async () => { + const initialState = { + grow: true, + width: 'small', + title: 'my control', + availableOptions: ['5 minutes'], + selectedOptions: ['5 minutes'], + variableName: 'myInterval', + variableType: ESQLVariableType.TIME_LITERAL, + esqlQuery: 'FROM foo | STATS BY BUCKET(@timestamp,)"', + controlType: EsqlControlType.STATIC_VALUES, + } as ESQLControlState; + const { findByTestId } = render( + + ); + // variable name input should be rendered and with the default value + expect(await findByTestId('esqlVariableName')).toHaveValue('myInterval'); + + // values dropdown should be rendered with column2 selected + const valuesOptionsDropdown = await findByTestId('esqlValuesOptions'); + const valuesOptionsDropdownBadge = within(valuesOptionsDropdown).getByTestId('5 minutes'); + expect(valuesOptionsDropdownBadge).toBeInTheDocument(); + + // variable label input should be rendered and with the default value (my control) + expect(await findByTestId('esqlControlLabel')).toHaveValue('my control'); + + // control width dropdown should be rendered and default to 'MEDIUM' + expect(await findByTestId('esqlControlMinimumWidth')).toBeInTheDocument(); + const pressedWidth = within(await findByTestId('esqlControlMinimumWidth')).getByTitle( + 'Small' + ); + expect(pressedWidth).toHaveAttribute('aria-pressed', 'true'); + + // control grow switch should be rendered and default to 'false' + expect(await findByTestId('esqlControlGrow')).toBeInTheDocument(); + const growSwitch = await findByTestId('esqlControlGrow'); + expect(growSwitch).toBeChecked(); + }); + + it('should call the onEditControl callback, if initialState is given', async () => { + const initialState = { + grow: true, + width: 'small', + title: 'my control', + availableOptions: ['5 minutes'], + selectedOptions: ['5 minutes'], + variableName: 'myInterval', + variableType: ESQLVariableType.TIME_LITERAL, + esqlQuery: 'FROM foo | STATS BY BUCKET(@timestamp,)"', + controlType: EsqlControlType.STATIC_VALUES, + } as ESQLControlState; + const onEditControlSpy = jest.fn(); + const { findByTestId } = render( + + ); + // click on the create button + fireEvent.click(await findByTestId('saveEsqlControlsFlyoutButton')); + expect(onEditControlSpy).toHaveBeenCalled(); + }); + + describe('Values type', () => { + it('should default correctly if no initial state is given for a values variable type', async () => { + const { findByTestId } = render( + + + + + + ); + // control type dropdown should be rendered and default to 'Values from a query' + expect(await findByTestId('esqlControlTypeDropdown')).toBeInTheDocument(); + const controlTypeInputPopover = await findByTestId('esqlControlTypeInputPopover'); + expect(within(controlTypeInputPopover).getByRole('combobox')).toHaveValue( + `Values from a query` + ); + + // code editor should be rendered + expect(await findByTestId('ESQLEditor')).toBeInTheDocument(); + + // values preview panel should be rendered + expect(await findByTestId('esqlValuesPreview')).toBeInTheDocument(); + }); + }); + }); +}); diff --git a/src/platform/plugins/shared/esql/public/triggers/esql_controls/control_flyout/value_control_form.tsx b/src/platform/plugins/shared/esql/public/triggers/esql_controls/control_flyout/value_control_form.tsx new file mode 100644 index 0000000000000..5b4c29ec738d2 --- /dev/null +++ b/src/platform/plugins/shared/esql/public/triggers/esql_controls/control_flyout/value_control_form.tsx @@ -0,0 +1,484 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import React, { useCallback, useState, useMemo, useEffect } from 'react'; +import { i18n } from '@kbn/i18n'; +import { + EuiComboBox, + EuiComboBoxOptionOption, + EuiFormRow, + EuiFlyoutBody, + EuiCallOut, + type EuiSwitchEvent, + EuiPanel, +} from '@elastic/eui'; +import { css } from '@emotion/react'; +import { FormattedMessage } from '@kbn/i18n-react'; +import type { ISearchGeneric } from '@kbn/search-types'; +import ESQLEditor from '@kbn/esql-editor'; +import { ESQLVariableType, ESQLControlVariable } from '@kbn/esql-validation-autocomplete'; +import { getIndexPatternFromESQLQuery, getESQLResults } from '@kbn/esql-utils'; +import type { ESQLControlState, ControlWidthOptions } from '../types'; +import { + Header, + Footer, + ControlWidth, + ControlType, + VariableName, + ControlLabel, +} from './shared_form_components'; +import { + getRecurrentVariableName, + getValuesFromQueryField, + getFlyoutStyling, + appendStatsByToQuery, + areValuesIntervalsValid, + validateVariableName, +} from './helpers'; +import { EsqlControlType } from '../types'; +import { ChooseColumnPopover } from './choose_column_popover'; + +interface ValueControlFormProps { + search: ISearchGeneric; + variableType: ESQLVariableType; + queryString: string; + esqlVariables: ESQLControlVariable[]; + closeFlyout: () => void; + onCreateControl: (state: ESQLControlState, variableName: string) => void; + onEditControl: (state: ESQLControlState) => void; + onCancelControl?: () => void; + initialState?: ESQLControlState; +} + +const SUGGESTED_INTERVAL_VALUES = ['5 minutes', '1 hour', '1 day', '1 week', '1 month']; + +export function ValueControlForm({ + variableType, + initialState, + onCancelControl, + queryString, + esqlVariables, + search, + closeFlyout, + onCreateControl, + onEditControl, +}: ValueControlFormProps) { + const valuesField = useMemo(() => { + if (variableType === ESQLVariableType.VALUES) { + return getValuesFromQueryField(queryString); + } + return null; + }, [variableType, queryString]); + const suggestedVariableName = useMemo(() => { + const existingVariables = esqlVariables.filter((variable) => variable.type === variableType); + + if (initialState) { + return initialState.variableName; + } + + if (valuesField && variableType === ESQLVariableType.VALUES) { + // variables names can't have special characters, only underscore + const fieldVariableName = valuesField.replace(/[^a-zA-Z0-9]/g, '_'); + return getRecurrentVariableName( + fieldVariableName, + existingVariables.map((variable) => variable.key) + ); + } + + if (variableType === ESQLVariableType.TIME_LITERAL) { + return getRecurrentVariableName( + 'interval', + existingVariables.map((variable) => variable.key) + ); + } + return getRecurrentVariableName( + 'variable', + existingVariables.map((variable) => variable.key) + ); + }, [esqlVariables, initialState, valuesField, variableType]); + + const [controlFlyoutType, setControlFlyoutType] = useState( + initialState?.controlType ?? + (variableType === ESQLVariableType.TIME_LITERAL + ? EsqlControlType.STATIC_VALUES + : EsqlControlType.VALUES_FROM_QUERY) + ); + + const [availableValuesOptions, setAvailableValuesOptions] = useState( + variableType === ESQLVariableType.TIME_LITERAL + ? SUGGESTED_INTERVAL_VALUES.map((option) => { + return { + label: option, + key: option, + 'data-test-subj': option, + }; + }) + : [] + ); + + const [selectedValues, setSelectedValues] = useState( + initialState + ? initialState.availableOptions.map((option) => { + return { + label: option, + key: option, + 'data-test-subj': option, + }; + }) + : [] + ); + + const [valuesQuery, setValuesQuery] = useState( + variableType === ESQLVariableType.VALUES ? initialState?.esqlQuery ?? '' : '' + ); + const [esqlQueryErrors, setEsqlQueryErrors] = useState(); + const [formIsInvalid, setFormIsInvalid] = useState(false); + const [queryColumns, setQueryColumns] = useState(valuesField ? [valuesField] : []); + const [variableName, setVariableName] = useState(suggestedVariableName); + const [label, setLabel] = useState(initialState?.title ?? ''); + const [minimumWidth, setMinimumWidth] = useState(initialState?.width ?? 'medium'); + const [grow, setGrow] = useState(initialState?.grow ?? false); + + const isControlInEditMode = useMemo(() => !!initialState, [initialState]); + + const areValuesValid = useMemo(() => { + return variableType === ESQLVariableType.TIME_LITERAL + ? areValuesIntervalsValid(selectedValues.map((option) => option.label)) + : true; + }, [variableType, selectedValues]); + + useEffect(() => { + const variableExists = + esqlVariables.some((variable) => variable.key === variableName.replace('?', '')) && + !isControlInEditMode; + setFormIsInvalid(!variableName || variableExists || !areValuesValid || !selectedValues.length); + }, [ + areValuesValid, + esqlVariables, + isControlInEditMode, + selectedValues.length, + valuesQuery, + variableName, + ]); + + const onValuesChange = useCallback((selectedOptions: EuiComboBoxOptionOption[]) => { + setSelectedValues(selectedOptions); + }, []); + + const onFlyoutTypeChange = useCallback( + (type: EsqlControlType) => { + setControlFlyoutType(type); + if (type !== controlFlyoutType && variableType === ESQLVariableType.TIME_LITERAL) { + setSelectedValues([]); + } + }, + [controlFlyoutType, variableType] + ); + + const onCreateOption = useCallback( + (searchValue: string, flattenedOptions: EuiComboBoxOptionOption[] = []) => { + if (!searchValue) { + return; + } + + const normalizedSearchValue = searchValue.trim().toLowerCase(); + + const newOption = { + 'data-test-subj': searchValue, + label: searchValue, + key: searchValue, + }; + + if ( + flattenedOptions.findIndex( + (option) => option.label.trim().toLowerCase() === normalizedSearchValue + ) === -1 + ) { + setAvailableValuesOptions([...availableValuesOptions, newOption]); + } + + setSelectedValues((prevSelected) => [...prevSelected, newOption]); + }, + [availableValuesOptions] + ); + + const onVariableNameChange = useCallback( + (e: { target: { value: React.SetStateAction } }) => { + const text = validateVariableName(String(e.target.value)); + setVariableName(text); + }, + [] + ); + + const onLabelChange = useCallback((e: { target: { value: React.SetStateAction } }) => { + setLabel(e.target.value); + }, []); + + const onMinimumSizeChange = useCallback((optionId: string) => { + if (optionId) { + setMinimumWidth(optionId as ControlWidthOptions); + } + }, []); + + const onGrowChange = useCallback((e: EuiSwitchEvent) => { + setGrow(e.target.checked); + }, []); + + const onValuesQuerySubmit = useCallback( + async (query: string) => { + try { + getESQLResults({ + esqlQuery: query, + search, + signal: undefined, + filter: undefined, + dropNullColumns: true, + }).then((results) => { + const columns = results.response.columns.map((col) => col.name); + setQueryColumns(columns); + + if (columns.length === 1) { + const valuesArray = results.response.values.map((value) => value[0]); + const options = valuesArray + .filter((v) => v) + .map((option) => { + return { + label: String(option), + key: String(option), + 'data-test-subj': String(option), + }; + }); + setSelectedValues(options); + setAvailableValuesOptions(options); + setEsqlQueryErrors([]); + } + }); + setValuesQuery(query); + } catch (e) { + setEsqlQueryErrors([e]); + } + }, + [search] + ); + + useEffect(() => { + if ( + !selectedValues?.length && + controlFlyoutType === EsqlControlType.VALUES_FROM_QUERY && + valuesField + ) { + const queryForValues = + suggestedVariableName !== '' + ? `FROM ${getIndexPatternFromESQLQuery(queryString)} | STATS BY ${valuesField}` + : ''; + onValuesQuerySubmit(queryForValues); + } + }, [ + controlFlyoutType, + onValuesQuerySubmit, + queryString, + selectedValues?.length, + suggestedVariableName, + valuesField, + variableName, + ]); + + const onCreateValueControl = useCallback(async () => { + const availableOptions = selectedValues.map((value) => value.label); + const state = { + availableOptions, + selectedOptions: [availableOptions[0]], + width: minimumWidth, + title: label || variableName, + variableName, + variableType, + esqlQuery: valuesQuery || queryString, + controlType: controlFlyoutType, + grow, + }; + + if (availableOptions.length) { + if (!isControlInEditMode) { + await onCreateControl(state, variableName); + } else { + onEditControl(state); + } + } + closeFlyout(); + }, [ + selectedValues, + controlFlyoutType, + minimumWidth, + label, + variableName, + variableType, + valuesQuery, + queryString, + grow, + closeFlyout, + isControlInEditMode, + onCreateControl, + onEditControl, + ]); + + const updateQuery = useCallback( + (column: string) => { + const updatedQuery = appendStatsByToQuery(valuesQuery, column); + onValuesQuerySubmit(updatedQuery); + }, + [onValuesQuerySubmit, valuesQuery] + ); + + const styling = useMemo(() => getFlyoutStyling(), []); + + return ( + <> +
+ + + + + + {controlFlyoutType === EsqlControlType.VALUES_FROM_QUERY && ( + <> + + { + setValuesQuery(q.esql); + }} + hideTimeFilterInfo={true} + disableAutoFocus={true} + errors={esqlQueryErrors} + editorIsInline + hideRunQueryText + onTextLangQuerySubmit={async (q, a) => { + if (q) { + await onValuesQuerySubmit(q.esql); + } + }} + isDisabled={false} + isLoading={false} + /> + + {queryColumns.length > 0 && ( + + {queryColumns.length === 1 ? ( + + {selectedValues.map((value) => value.label).join(', ')} + + ) : ( + +

+ STATS BY, + chooseColumnPopover: ( + + ), + }} + /> +

+
+ )} +
+ )} + + )} + {controlFlyoutType === EsqlControlType.STATIC_VALUES && ( + + + + )} + + + +
+
+ + ); +} diff --git a/src/platform/plugins/shared/esql/public/triggers/esql_controls/esql_control_action.test.ts b/src/platform/plugins/shared/esql/public/triggers/esql_controls/esql_control_action.test.ts new file mode 100644 index 0000000000000..07f9b50e43d75 --- /dev/null +++ b/src/platform/plugins/shared/esql/public/triggers/esql_controls/esql_control_action.test.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", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import { dataPluginMock } from '@kbn/data-plugin/public/mocks'; +import { coreMock } from '@kbn/core/public/mocks'; +import { ESQLVariableType } from '@kbn/esql-validation-autocomplete'; +import { CreateESQLControlAction } from './esql_control_action'; + +describe('update ES|QL query action', () => { + const dataMock = dataPluginMock.createStartContract(); + const searchMock = dataMock.search.search; + const coreStart = coreMock.createStart(); + describe('compatibility check', () => { + it('is incompatible if no query is applied', async () => { + const createControlAction = new CreateESQLControlAction(coreStart, searchMock); + const isCompatible = await createControlAction.isCompatible({ + queryString: '', + variableType: ESQLVariableType.FIELDS, + esqlVariables: [], + }); + + expect(isCompatible).toBeFalsy(); + }); + + it('is compatible if queryString is given', async () => { + const createControlAction = new CreateESQLControlAction(coreStart, searchMock); + const isCompatible = await createControlAction.isCompatible({ + queryString: 'FROM meow', + variableType: ESQLVariableType.FIELDS, + esqlVariables: [], + }); + + expect(isCompatible).toBeTruthy(); + }); + }); +}); diff --git a/src/platform/plugins/shared/esql/public/triggers/esql_controls/esql_control_action.ts b/src/platform/plugins/shared/esql/public/triggers/esql_controls/esql_control_action.ts new file mode 100644 index 0000000000000..48ffc47bff613 --- /dev/null +++ b/src/platform/plugins/shared/esql/public/triggers/esql_controls/esql_control_action.ts @@ -0,0 +1,76 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import { i18n } from '@kbn/i18n'; +import type { Action } from '@kbn/ui-actions-plugin/public'; +import type { CoreStart } from '@kbn/core/public'; +import type { ISearchGeneric } from '@kbn/search-types'; +import type { ESQLVariableType, ESQLControlVariable } from '@kbn/esql-validation-autocomplete'; +import { monaco } from '@kbn/monaco'; +import type { ESQLControlState } from './types'; + +const ACTION_CREATE_ESQL_CONTROL = 'ACTION_CREATE_ESQL_CONTROL'; + +interface Context { + queryString: string; + variableType: ESQLVariableType; + esqlVariables: ESQLControlVariable[]; + onSaveControl?: (controlState: ESQLControlState, updatedQuery: string) => Promise; + onCancelControl?: () => void; + cursorPosition?: monaco.Position; + initialState?: ESQLControlState; +} + +export const getHelpersAsync = async () => await import('./esql_control_helpers'); + +export class CreateESQLControlAction implements Action { + public type = ACTION_CREATE_ESQL_CONTROL; + public id = ACTION_CREATE_ESQL_CONTROL; + public order = 50; + + constructor(protected readonly core: CoreStart, protected readonly search: ISearchGeneric) {} + + public getDisplayName(): string { + return i18n.translate('esql.createESQLControlLabel', { + defaultMessage: 'Creates an ES|QL control', + }); + } + + public getIconType() { + return 'pencil'; + } + + public async isCompatible({ queryString }: Context) { + const { isActionCompatible } = await getHelpersAsync(); + return isActionCompatible(queryString); + } + + public async execute({ + queryString, + variableType, + esqlVariables, + onSaveControl, + onCancelControl, + cursorPosition, + initialState, + }: Context) { + const { executeAction } = await getHelpersAsync(); + return executeAction({ + queryString, + core: this.core, + search: this.search, + variableType, + esqlVariables, + onSaveControl, + onCancelControl, + cursorPosition, + initialState, + }); + } +} diff --git a/src/platform/plugins/shared/esql/public/triggers/esql_controls/esql_control_helpers.tsx b/src/platform/plugins/shared/esql/public/triggers/esql_controls/esql_control_helpers.tsx new file mode 100644 index 0000000000000..d1eae4d266d6e --- /dev/null +++ b/src/platform/plugins/shared/esql/public/triggers/esql_controls/esql_control_helpers.tsx @@ -0,0 +1,101 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ +import React from 'react'; +import { IncompatibleActionError } from '@kbn/ui-actions-plugin/public'; +import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public'; +import { KibanaRenderContextProvider } from '@kbn/react-kibana-context-render'; +import type { CoreStart } from '@kbn/core/public'; +import type { ISearchGeneric } from '@kbn/search-types'; +import type { ESQLVariableType, ESQLControlVariable } from '@kbn/esql-validation-autocomplete'; +import { toMountPoint } from '@kbn/react-kibana-mount'; +import { monaco } from '@kbn/monaco'; +import { ESQLControlsFlyout } from './control_flyout'; +import { untilPluginStartServicesReady } from '../../kibana_services'; +import type { ESQLControlState } from './types'; + +interface Context { + queryString: string; + core: CoreStart; + search: ISearchGeneric; + variableType: ESQLVariableType; + esqlVariables: ESQLControlVariable[]; + onSaveControl?: (controlState: ESQLControlState, updatedQuery: string) => Promise; + onCancelControl?: () => void; + cursorPosition?: monaco.Position; + initialState?: ESQLControlState; +} + +export async function isActionCompatible(queryString: string) { + return Boolean(queryString && queryString.trim().length > 0); +} + +export async function executeAction({ + queryString, + core, + search, + variableType, + esqlVariables, + onSaveControl, + onCancelControl, + cursorPosition, + initialState, +}: Context) { + const isCompatibleAction = await isActionCompatible(queryString); + if (!isCompatibleAction) { + throw new IncompatibleActionError(); + } + + const deps = await untilPluginStartServicesReady(); + const handle = core.overlays.openFlyout( + toMountPoint( + React.cloneElement( + + + { + handle.close(); + }} + onSaveControl={onSaveControl} + onCancelControl={onCancelControl} + cursorPosition={cursorPosition} + initialState={initialState} + esqlVariables={esqlVariables} + /> + + , + { + closeFlyout: () => { + handle.close(); + }, + } + ), + core + ), + { + size: 's', + 'data-test-subj': 'create_esql_control_flyout', + isResizable: true, + type: 'push', + paddingSize: 'm', + hideCloseButton: true, + onClose: (overlayRef) => { + overlayRef.close(); + }, + outsideClickCloses: true, + maxWidth: 800, + } + ); +} diff --git a/src/platform/plugins/shared/esql/public/triggers/esql_controls/esql_control_trigger.ts b/src/platform/plugins/shared/esql/public/triggers/esql_controls/esql_control_trigger.ts new file mode 100644 index 0000000000000..9995b92afb591 --- /dev/null +++ b/src/platform/plugins/shared/esql/public/triggers/esql_controls/esql_control_trigger.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", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ +import { i18n } from '@kbn/i18n'; +import type { Trigger } from '@kbn/ui-actions-plugin/public'; + +export const ESQL_CONTROL_TRIGGER = 'ESQL_CONTROL_TRIGGER'; + +export const esqlControlTrigger: Trigger = { + id: ESQL_CONTROL_TRIGGER, + title: i18n.translate('esql.triggers.esqlControlTigger', { + defaultMessage: 'Create an ES|QL control', + }), + description: i18n.translate('esql.triggers.esqlControlTiggerDescription', { + defaultMessage: 'Create an ES|QL control to interact with the charts', + }), +}; diff --git a/src/platform/plugins/shared/esql/public/triggers/esql_controls/types.ts b/src/platform/plugins/shared/esql/public/triggers/esql_controls/types.ts new file mode 100644 index 0000000000000..5787d8e485724 --- /dev/null +++ b/src/platform/plugins/shared/esql/public/triggers/esql_controls/types.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", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ +import type { ESQLVariableType } from '@kbn/esql-validation-autocomplete'; + +export enum EsqlControlType { + STATIC_VALUES = 'STATIC_VALUES', + VALUES_FROM_QUERY = 'VALUES_FROM_QUERY', +} + +export type ControlWidthOptions = 'small' | 'medium' | 'large'; + +export interface ESQLControlState { + grow?: boolean; + width?: ControlWidthOptions; + title: string; + availableOptions: string[]; + selectedOptions: string[]; + variableName: string; + variableType: ESQLVariableType; + esqlQuery: string; + controlType: EsqlControlType; +} diff --git a/src/platform/plugins/shared/esql/public/triggers/index.ts b/src/platform/plugins/shared/esql/public/triggers/index.ts index e9dfab8c09d3a..49e9939a60871 100644 --- a/src/platform/plugins/shared/esql/public/triggers/index.ts +++ b/src/platform/plugins/shared/esql/public/triggers/index.ts @@ -7,5 +7,11 @@ * License v3.0 only", or the "Server Side Public License, v 1". */ -export { updateESQLQueryTrigger, UPDATE_ESQL_QUERY_TRIGGER } from './update_esql_query_trigger'; -export { UpdateESQLQueryAction } from './update_esql_query_actions'; +export { + updateESQLQueryTrigger, + UPDATE_ESQL_QUERY_TRIGGER, +} from './update_esql_query/update_esql_query_trigger'; +export { UpdateESQLQueryAction } from './update_esql_query/update_esql_query_actions'; + +export { esqlControlTrigger, ESQL_CONTROL_TRIGGER } from './esql_controls/esql_control_trigger'; +export { CreateESQLControlAction } from './esql_controls/esql_control_action'; diff --git a/src/platform/plugins/shared/esql/public/triggers/update_esql_query_actions.test.ts b/src/platform/plugins/shared/esql/public/triggers/update_esql_query/update_esql_query_actions.test.ts similarity index 100% rename from src/platform/plugins/shared/esql/public/triggers/update_esql_query_actions.test.ts rename to src/platform/plugins/shared/esql/public/triggers/update_esql_query/update_esql_query_actions.test.ts diff --git a/src/platform/plugins/shared/esql/public/triggers/update_esql_query_actions.ts b/src/platform/plugins/shared/esql/public/triggers/update_esql_query/update_esql_query_actions.ts similarity index 100% rename from src/platform/plugins/shared/esql/public/triggers/update_esql_query_actions.ts rename to src/platform/plugins/shared/esql/public/triggers/update_esql_query/update_esql_query_actions.ts diff --git a/src/platform/plugins/shared/esql/public/triggers/update_esql_query_helpers.ts b/src/platform/plugins/shared/esql/public/triggers/update_esql_query/update_esql_query_helpers.ts similarity index 100% rename from src/platform/plugins/shared/esql/public/triggers/update_esql_query_helpers.ts rename to src/platform/plugins/shared/esql/public/triggers/update_esql_query/update_esql_query_helpers.ts diff --git a/src/platform/plugins/shared/esql/public/triggers/update_esql_query_trigger.ts b/src/platform/plugins/shared/esql/public/triggers/update_esql_query/update_esql_query_trigger.ts similarity index 100% rename from src/platform/plugins/shared/esql/public/triggers/update_esql_query_trigger.ts rename to src/platform/plugins/shared/esql/public/triggers/update_esql_query/update_esql_query_trigger.ts diff --git a/src/platform/plugins/shared/esql/public/variables_service.test.ts b/src/platform/plugins/shared/esql/public/variables_service.test.ts new file mode 100644 index 0000000000000..5ef6cf8a3d759 --- /dev/null +++ b/src/platform/plugins/shared/esql/public/variables_service.test.ts @@ -0,0 +1,84 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ +import { ESQLVariableType } from '@kbn/esql-validation-autocomplete'; +import { EsqlVariablesService } from './variables_service'; + +describe('EsqlVariablesService', () => { + let esqlVariablesService: EsqlVariablesService; + + beforeEach(() => { + esqlVariablesService = new EsqlVariablesService(); + }); + + describe('enableSuggestions', () => { + it('should enable suggestions', () => { + esqlVariablesService.enableSuggestions(); + expect(esqlVariablesService.areSuggestionsEnabled).toBe(true); + }); + }); + + describe('disableSuggestions', () => { + it('should disable suggestions', () => { + esqlVariablesService.disableSuggestions(); + expect(esqlVariablesService.areSuggestionsEnabled).toBe(false); + }); + }); + + describe('addVariable', () => { + it('should add a variable', () => { + const variable = { + key: 'my_variable', + value: 'my_value', + type: ESQLVariableType.VALUES, + }; + esqlVariablesService.addVariable(variable); + expect(esqlVariablesService.esqlVariables).toEqual([variable]); + }); + + it('should not add a variable if it already exists', () => { + const variable = { + key: 'my_variable', + value: 'my_value', + type: ESQLVariableType.VALUES, + }; + esqlVariablesService.addVariable(variable); + esqlVariablesService.addVariable(variable); + expect(esqlVariablesService.esqlVariables).toEqual([variable]); + }); + + it('should add a variable with a number value', () => { + const variable = { + key: 'my_variable', + value: 10, + type: ESQLVariableType.VALUES, + }; + esqlVariablesService.addVariable(variable); + expect(esqlVariablesService.esqlVariables).toEqual([variable]); + }); + }); + + describe('clearVariables', () => { + it('should clear all variables', () => { + const variable1 = { + key: 'my_variable1', + value: 'my_value1', + type: ESQLVariableType.VALUES, + }; + const variable2 = { + key: 'my_variable2', + value: 'my_value2', + type: ESQLVariableType.FIELDS, + }; + esqlVariablesService.addVariable(variable1); + esqlVariablesService.addVariable(variable2); + esqlVariablesService.clearVariables(); + expect(esqlVariablesService.esqlVariables).toEqual([]); + }); + }); +}); diff --git a/src/platform/plugins/shared/esql/public/variables_service.ts b/src/platform/plugins/shared/esql/public/variables_service.ts new file mode 100644 index 0000000000000..a748e81f3bb19 --- /dev/null +++ b/src/platform/plugins/shared/esql/public/variables_service.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", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import type { ESQLControlVariable } from '@kbn/esql-validation-autocomplete'; + +export class EsqlVariablesService { + esqlVariables: ESQLControlVariable[] = []; + areSuggestionsEnabled: boolean = false; + + enableSuggestions() { + this.areSuggestionsEnabled = true; + } + + disableSuggestions() { + this.areSuggestionsEnabled = false; + } + + addVariable(variable: ESQLControlVariable): void { + const variables = [...this.esqlVariables]; + const variableExists = variables.find((v) => v.key === variable.key); + if (variableExists) { + return; + } + variables.push({ + ...variable, + value: Number.isNaN(Number(variable.value)) ? variable.value : Number(variable.value), + }); + this.esqlVariables = variables; + } + + clearVariables() { + this.esqlVariables = []; + } +} diff --git a/src/platform/plugins/shared/esql/tsconfig.json b/src/platform/plugins/shared/esql/tsconfig.json index bacd508aa7ea6..6c804a3eda4e8 100644 --- a/src/platform/plugins/shared/esql/tsconfig.json +++ b/src/platform/plugins/shared/esql/tsconfig.json @@ -26,7 +26,15 @@ "@kbn/usage-collection-plugin", "@kbn/content-management-plugin", "@kbn/kibana-utils-plugin", + "@kbn/esql-validation-autocomplete", + "@kbn/monaco", + "@kbn/esql-ast", + "@kbn/search-types", + "@kbn/react-kibana-context-render", + "@kbn/react-kibana-mount", "@kbn/core-test-helpers-kbn-server", + "@kbn/i18n-react", + "@kbn/visualization-utils", ], "exclude": [ "target/**/*", diff --git a/src/platform/plugins/shared/expressions/common/expression_types/specs/datatable.ts b/src/platform/plugins/shared/expressions/common/expression_types/specs/datatable.ts index 33f16106b6f8b..fa3cd763487fb 100644 --- a/src/platform/plugins/shared/expressions/common/expression_types/specs/datatable.ts +++ b/src/platform/plugins/shared/expressions/common/expression_types/specs/datatable.ts @@ -98,6 +98,7 @@ export interface DatatableColumn { name: string; meta: DatatableColumnMeta; isNull?: boolean; + variable?: string; } /** diff --git a/src/platform/plugins/shared/expressions/common/service/expressions_services.ts b/src/platform/plugins/shared/expressions/common/service/expressions_services.ts index 2d5b7962c0a01..a3434699808d2 100644 --- a/src/platform/plugins/shared/expressions/common/service/expressions_services.ts +++ b/src/platform/plugins/shared/expressions/common/service/expressions_services.ts @@ -400,7 +400,6 @@ export class ExpressionsService public readonly run: ExpressionsServiceStart['run'] = (ast, input, params) => { this.assertStart(); - return this.executor.run(ast, input, params); }; diff --git a/src/platform/plugins/shared/inspector/public/plugin.tsx b/src/platform/plugins/shared/inspector/public/plugin.tsx index 62e32568fec10..f746558f25543 100644 --- a/src/platform/plugins/shared/inspector/public/plugin.tsx +++ b/src/platform/plugins/shared/inspector/public/plugin.tsx @@ -115,6 +115,7 @@ export class InspectorPublicPlugin implements Plugin { { 'data-test-subj': 'inspectorPanel', closeButtonProps: { 'aria-label': closeButtonLabel }, + type: options.flyoutType, } ); }; diff --git a/src/platform/plugins/shared/inspector/public/types.ts b/src/platform/plugins/shared/inspector/public/types.ts index 59190e4ca0940..bc0f46c56e2bf 100644 --- a/src/platform/plugins/shared/inspector/public/types.ts +++ b/src/platform/plugins/shared/inspector/public/types.ts @@ -8,6 +8,7 @@ */ import { OverlayRef } from '@kbn/core/public'; +import { EuiFlyoutProps } from '@elastic/eui'; import { Adapters } from '../common'; /** @@ -60,6 +61,7 @@ export interface InspectorViewDescription { export interface InspectorOptions { title?: string; options?: unknown; + flyoutType?: EuiFlyoutProps['type']; } export type InspectorSession = OverlayRef; diff --git a/src/platform/plugins/shared/saved_search/common/expressions/kibana_context.ts b/src/platform/plugins/shared/saved_search/common/expressions/kibana_context.ts index a238df8b3e770..20e38ba49c534 100644 --- a/src/platform/plugins/shared/saved_search/common/expressions/kibana_context.ts +++ b/src/platform/plugins/shared/saved_search/common/expressions/kibana_context.ts @@ -131,6 +131,7 @@ export const getKibanaContextFn = ( return { type: 'kibana_context', query: queries, + esqlVariables: input?.esqlVariables, filters: uniqFilters(filters.filter((f: Filter) => !f.meta?.disabled)), timeRange, }; diff --git a/src/platform/plugins/shared/saved_search/common/service/get_saved_searches.test.ts b/src/platform/plugins/shared/saved_search/common/service/get_saved_searches.test.ts index c3c7e4b20e399..7ad47f04a2054 100644 --- a/src/platform/plugins/shared/saved_search/common/service/get_saved_searches.test.ts +++ b/src/platform/plugins/shared/saved_search/common/service/get_saved_searches.test.ts @@ -42,7 +42,7 @@ describe('getSavedSearch', () => { } expect(errorMessage).toBe( - 'Could not locate that search (id: ccf1af80-2297-11ec-86e0-1155ffb9c7a7)' + 'Could not locate that Discover session (id: ccf1af80-2297-11ec-86e0-1155ffb9c7a7)' ); }); diff --git a/src/platform/plugins/shared/saved_search/common/service/get_saved_searches.ts b/src/platform/plugins/shared/saved_search/common/service/get_saved_searches.ts index a7952d93d8eed..32f7da35ce6af 100644 --- a/src/platform/plugins/shared/saved_search/common/service/get_saved_searches.ts +++ b/src/platform/plugins/shared/saved_search/common/service/get_saved_searches.ts @@ -28,7 +28,7 @@ export interface GetSavedSearchDependencies { const getSavedSearchUrlConflictMessage = async (json: string) => i18n.translate('savedSearch.legacyURLConflict.errorMessage', { - defaultMessage: `This search has the same URL as a legacy alias. Disable the alias to resolve this error : {json}`, + defaultMessage: `This Discover session has the same URL as a legacy alias. Disable the alias to resolve this error : {json}`, values: { json }, }); @@ -40,7 +40,7 @@ export const getSearchSavedObject = async ( // @ts-expect-error if (so.error) { - throw new Error(`Could not locate that search (id: ${savedSearchId})`); + throw new Error(`Could not locate that Discover session (id: ${savedSearchId})`); } if (so.meta.outcome === 'conflict') { diff --git a/src/platform/plugins/shared/unified_search/public/dataview_picker/dataview_list.tsx b/src/platform/plugins/shared/unified_search/public/dataview_picker/dataview_list.tsx index 98c1677d480e4..8bc93ef5efdd9 100644 --- a/src/platform/plugins/shared/unified_search/public/dataview_picker/dataview_list.tsx +++ b/src/platform/plugins/shared/unified_search/public/dataview_picker/dataview_list.tsx @@ -162,9 +162,12 @@ export function DataViewsList({ searchProps={{ id: searchListInputId, compressed: true, - autoFocus: true, placeholder: strings.editorAndPopover.search.getSearchPlaceholder(), 'data-test-subj': 'indexPattern-switcher--input', + autoFocus: false, // focused manually below - see https://github.com/elastic/eui/issues/8287 + inputRef: (ref) => { + ref?.focus({ preventScroll: true }); + }, ...(selectableProps ? selectableProps.searchProps : undefined), }} > diff --git a/src/platform/plugins/shared/usage_collection/server/routes/stats/stats.ts b/src/platform/plugins/shared/usage_collection/server/routes/stats/stats.ts index 3a7683bb1c46d..d850dfd2572b5 100644 --- a/src/platform/plugins/shared/usage_collection/server/routes/stats/stats.ts +++ b/src/platform/plugins/shared/usage_collection/server/routes/stats/stats.ts @@ -62,6 +62,7 @@ export function registerStatsRoute({ }, options: { authRequired: !config.allowAnonymous, + excludeFromRateLimiter: true, // The `api` tag ensures that unauthenticated calls receive a 401 rather than a 302 redirect to login page. // The `security:acceptJWT` tag allows route to be accessed with JWT credentials. It points to // ROUTE_TAG_ACCEPT_JWT from '@kbn/security-plugin/server' that cannot be imported here directly. diff --git a/test/functional/apps/console/_autocomplete.ts b/test/functional/apps/console/_autocomplete.ts index ac5fdda98e417..f5c77ad13bde8 100644 --- a/test/functional/apps/console/_autocomplete.ts +++ b/test/functional/apps/console/_autocomplete.ts @@ -34,8 +34,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { }); } - // Failing: See https://github.com/elastic/kibana/issues/156926 - describe.skip('console autocomplete feature', function describeIndexTests() { + describe('console autocomplete feature', function describeIndexTests() { before(async () => { log.debug('navigateTo console'); await PageObjects.common.navigateToApp('console'); @@ -53,7 +52,6 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { it('should provide basic auto-complete functionality', async () => { await PageObjects.console.enterText(`GET _search\n`); - await PageObjects.console.pressEnter(); await PageObjects.console.enterText(`{\n\t"query": {`); await PageObjects.console.pressEnter(); await PageObjects.console.sleepForDebouncePeriod(); @@ -146,6 +144,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { it('JSON autocompletion with placeholder fields', async () => { await PageObjects.console.enterText('GET _search\n'); await PageObjects.console.enterText('{'); + await PageObjects.console.sleepForDebouncePeriod(); await PageObjects.console.pressEnter(); for (const char of '"ag') { diff --git a/test/functional/apps/dashboard/esql_controls/config.ts b/test/functional/apps/dashboard/esql_controls/config.ts new file mode 100644 index 0000000000000..941eec8ca621c --- /dev/null +++ b/test/functional/apps/dashboard/esql_controls/config.ts @@ -0,0 +1,19 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile(require.resolve('../../../config.base.js')); + + return { + ...functionalConfig.getAll(), + testFiles: [require.resolve('.')], + }; +} diff --git a/test/functional/apps/dashboard/esql_controls/field_control.ts b/test/functional/apps/dashboard/esql_controls/field_control.ts new file mode 100644 index 0000000000000..3356cf1773e82 --- /dev/null +++ b/test/functional/apps/dashboard/esql_controls/field_control.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", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import expect from '@kbn/expect'; + +import { FtrProviderContext } from '../../../ftr_provider_context'; + +export default function ({ getService, getPageObjects }: FtrProviderContext) { + const retry = getService('retry'); + const kibanaServer = getService('kibanaServer'); + const { dashboard, timePicker, common } = getPageObjects(['dashboard', 'timePicker', 'common']); + const testSubjects = getService('testSubjects'); + const esql = getService('esql'); + const dashboardAddPanel = getService('dashboardAddPanel'); + const browser = getService('browser'); + const comboBox = getService('comboBox'); + const elasticChart = getService('elasticChart'); + + describe('dashboard - add a field type ES|QL control', function () { + before(async () => { + await kibanaServer.savedObjects.cleanStandardList(); + await kibanaServer.importExport.load( + 'test/functional/fixtures/kbn_archiver/dashboard/current/kibana' + ); + await kibanaServer.uiSettings.replace({ + defaultIndex: '0bf35f60-3dc9-11e8-8660-4d65aa086b3c', + }); + }); + + after(async () => { + await dashboard.navigateToApp(); + await testSubjects.click('discard-unsaved-New-Dashboard'); + }); + + it('should add an ES|QL field control', async () => { + await dashboard.navigateToApp(); + await dashboard.clickNewDashboard(); + await timePicker.setDefaultDataRange(); + await dashboard.switchToEditMode(); + await dashboardAddPanel.clickEditorMenuButton(); + await dashboardAddPanel.clickAddNewPanelFromUIActionLink('ES|QL'); + await dashboard.waitForRenderComplete(); + + await retry.try(async () => { + const panelCount = await dashboard.getPanelCount(); + expect(panelCount).to.eql(1); + }); + + await esql.waitESQLEditorLoaded('InlineEditingESQLEditor'); + + await retry.waitFor('control flyout to open', async () => { + await esql.typeEsqlEditorQuery( + 'FROM logstash* | STATS COUNT(*) BY ', + 'InlineEditingESQLEditor' + ); + // Wait until suggestions are loaded + await common.sleep(1000); + // Create control is the third suggestion + await browser.pressKeys(browser.keys.ARROW_DOWN); + await browser.pressKeys(browser.keys.ARROW_DOWN); + await browser.pressKeys(browser.keys.ENTER); + + return await testSubjects.exists('create_esql_control_flyout'); + }); + + await comboBox.set('esqlFieldsOptions', 'geo.dest'); + await comboBox.set('esqlFieldsOptions', 'clientip'); + + // create the control + await testSubjects.click('saveEsqlControlsFlyoutButton'); + await dashboard.waitForRenderComplete(); + + await retry.try(async () => { + const controlGroupVisible = await testSubjects.exists('controls-group-wrapper'); + expect(controlGroupVisible).to.be(true); + }); + + // Check Lens editor has been updated accordingly + const editorValue = await esql.getEsqlEditorQuery(); + expect(editorValue).to.contain('FROM logstash* | STATS COUNT(*) BY ?field'); + }); + + it('should update the Lens chart accordingly', async () => { + await elasticChart.setNewChartUiDebugFlag(true); + // change the control value + await comboBox.set('esqlControlValuesDropdown', 'clientip'); + await dashboard.waitForRenderComplete(); + + const data = await elasticChart.getChartDebugData('xyVisChart'); + expect(data?.axes?.x[0]?.title).to.be('clientip'); + }); + }); +} diff --git a/test/functional/apps/dashboard/esql_controls/index.ts b/test/functional/apps/dashboard/esql_controls/index.ts new file mode 100644 index 0000000000000..00809cbb130ab --- /dev/null +++ b/test/functional/apps/dashboard/esql_controls/index.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", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import { FtrProviderContext } from '../../../ftr_provider_context'; + +export default function ({ getService, loadTestFile }: FtrProviderContext) { + const browser = getService('browser'); + const esArchiver = getService('esArchiver'); + + async function loadCurrentData() { + await browser.setWindowSize(1300, 900); + await esArchiver.unload('test/functional/fixtures/es_archiver/logstash_functional'); + await esArchiver.loadIfNeeded('test/functional/fixtures/es_archiver/dashboard/current/data'); + } + + async function unloadCurrentData() { + await esArchiver.unload('test/functional/fixtures/es_archiver/dashboard/current/data'); + } + + describe('dashboard app - esql controls', function () { + before(loadCurrentData); + after(unloadCurrentData); + + loadTestFile(require.resolve('./field_control')); + loadTestFile(require.resolve('./interval_control')); + loadTestFile(require.resolve('./value_control')); + }); +} diff --git a/test/functional/apps/dashboard/esql_controls/interval_control.ts b/test/functional/apps/dashboard/esql_controls/interval_control.ts new file mode 100644 index 0000000000000..ee2e386bba586 --- /dev/null +++ b/test/functional/apps/dashboard/esql_controls/interval_control.ts @@ -0,0 +1,90 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import expect from '@kbn/expect'; + +import { FtrProviderContext } from '../../../ftr_provider_context'; + +export default function ({ getService, getPageObjects }: FtrProviderContext) { + const retry = getService('retry'); + const kibanaServer = getService('kibanaServer'); + const { dashboard, timePicker, common } = getPageObjects(['dashboard', 'timePicker', 'common']); + const testSubjects = getService('testSubjects'); + const esql = getService('esql'); + const dashboardAddPanel = getService('dashboardAddPanel'); + const browser = getService('browser'); + const comboBox = getService('comboBox'); + + describe('dashboard - add an interval type ES|QL control', function () { + before(async () => { + await kibanaServer.savedObjects.cleanStandardList(); + await kibanaServer.importExport.load( + 'test/functional/fixtures/kbn_archiver/dashboard/current/kibana' + ); + await kibanaServer.uiSettings.replace({ + defaultIndex: '0bf35f60-3dc9-11e8-8660-4d65aa086b3c', + }); + }); + + after(async () => { + await dashboard.navigateToApp(); + await testSubjects.click('discard-unsaved-New-Dashboard'); + }); + + it('should add an ES|QL interval control', async () => { + await dashboard.navigateToApp(); + await dashboard.clickNewDashboard(); + await timePicker.setDefaultDataRange(); + await dashboard.switchToEditMode(); + await dashboardAddPanel.clickEditorMenuButton(); + await dashboardAddPanel.clickAddNewPanelFromUIActionLink('ES|QL'); + await dashboard.waitForRenderComplete(); + + await retry.try(async () => { + const panelCount = await dashboard.getPanelCount(); + expect(panelCount).to.eql(1); + }); + + await esql.waitESQLEditorLoaded('InlineEditingESQLEditor'); + + await retry.waitFor('control flyout to open', async () => { + await esql.typeEsqlEditorQuery( + 'FROM logstash* | STATS COUNT(*) BY BUCKET(@timestamp, )', + 'InlineEditingESQLEditor' + ); + await browser.pressKeys(browser.keys.ARROW_LEFT); + await browser.pressKeys(browser.keys.SPACE); + // Wait until suggestions are loaded + await common.sleep(1000); + // Create control is the first suggestion + await browser.pressKeys(browser.keys.ENTER); + + return await testSubjects.exists('create_esql_control_flyout'); + }); + + await comboBox.set('esqlValuesOptions', '1 hour'); + await comboBox.set('esqlValuesOptions', '1 day'); + + // create the control + await testSubjects.click('saveEsqlControlsFlyoutButton'); + await dashboard.waitForRenderComplete(); + + await retry.try(async () => { + const controlGroupVisible = await testSubjects.exists('controls-group-wrapper'); + expect(controlGroupVisible).to.be(true); + }); + + // Check Lens editor has been updated accordingly + const editorValue = await esql.getEsqlEditorQuery(); + expect(editorValue).to.contain( + 'FROM logstash* | STATS COUNT(*) BY BUCKET(@timestamp, ?interval)' + ); + }); + }); +} diff --git a/test/functional/apps/dashboard/esql_controls/value_control.ts b/test/functional/apps/dashboard/esql_controls/value_control.ts new file mode 100644 index 0000000000000..56ed18eaa2e1a --- /dev/null +++ b/test/functional/apps/dashboard/esql_controls/value_control.ts @@ -0,0 +1,130 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import expect from '@kbn/expect'; + +import { FtrProviderContext } from '../../../ftr_provider_context'; + +export default function ({ getService, getPageObjects }: FtrProviderContext) { + const retry = getService('retry'); + const kibanaServer = getService('kibanaServer'); + const { dashboard, timePicker, common, dashboardControls } = getPageObjects([ + 'dashboard', + 'timePicker', + 'common', + 'dashboardControls', + ]); + const find = getService('find'); + const testSubjects = getService('testSubjects'); + const esql = getService('esql'); + const dashboardAddPanel = getService('dashboardAddPanel'); + const browser = getService('browser'); + const comboBox = getService('comboBox'); + + describe('dashboard - add an value type ES|QL control', function () { + before(async () => { + await kibanaServer.savedObjects.cleanStandardList(); + await kibanaServer.importExport.load( + 'test/functional/fixtures/kbn_archiver/dashboard/current/kibana' + ); + await kibanaServer.uiSettings.replace({ + defaultIndex: '0bf35f60-3dc9-11e8-8660-4d65aa086b3c', + }); + }); + + after(async () => { + await dashboard.navigateToApp(); + await testSubjects.click('discard-unsaved-New-Dashboard'); + }); + + it('should add an ES|QL value control', async () => { + await dashboard.navigateToApp(); + await dashboard.clickNewDashboard(); + await timePicker.setDefaultDataRange(); + await dashboard.switchToEditMode(); + await dashboardAddPanel.clickEditorMenuButton(); + await dashboardAddPanel.clickAddNewPanelFromUIActionLink('ES|QL'); + await dashboard.waitForRenderComplete(); + + await retry.try(async () => { + const panelCount = await dashboard.getPanelCount(); + expect(panelCount).to.eql(1); + }); + + await esql.waitESQLEditorLoaded('InlineEditingESQLEditor'); + await retry.waitFor('control flyout to open', async () => { + await esql.typeEsqlEditorQuery( + 'FROM logstash-* | WHERE geo.dest == ', + 'InlineEditingESQLEditor' + ); + // Wait until suggestions are loaded + await common.sleep(1000); + // Create control is the first suggestion + await browser.pressKeys(browser.keys.ENTER); + + return await testSubjects.exists('create_esql_control_flyout'); + }); + + const valuesQueryEditorValue = await esql.getEsqlEditorQuery(); + expect(valuesQueryEditorValue).to.contain('FROM logstash-* | STATS BY geo.dest'); + + // create the control + await testSubjects.click('saveEsqlControlsFlyoutButton'); + await dashboard.waitForRenderComplete(); + + await retry.try(async () => { + const controlGroupVisible = await testSubjects.exists('controls-group-wrapper'); + expect(controlGroupVisible).to.be(true); + }); + + // Check Lens editor has been updated accordingly + const editorValue = await esql.getEsqlEditorQuery(); + expect(editorValue).to.contain('FROM logstash-* | WHERE geo.dest == ?geo_dest'); + + // change the table to keep only the column with the control + await esql.setEsqlEditorQuery( + 'FROM logstash-* | WHERE geo.dest == ?geo_dest | KEEP geo.dest' + ); + // run the query + await testSubjects.click('ESQLEditor-run-query-button'); + + // save the changes + await testSubjects.click('applyFlyoutButton'); + }); + + it('should update the Lens chart accordingly', async () => { + // change the control value + await comboBox.set('esqlControlValuesDropdown', 'AO'); + await dashboard.waitForRenderComplete(); + + const tableContent = await testSubjects.getVisibleText('lnsTableCellContent'); + expect(tableContent).to.contain('AO'); + }); + + it('should handle properly a query to retrieve the values that returns more than one column', async () => { + const firstId = (await dashboardControls.getAllControlIds())[0]; + await dashboardControls.editExistingControl(firstId); + + await esql.setEsqlEditorQuery('FROM logstash-*'); + // run the query + await testSubjects.click('ESQLEditor-run-query-button'); + expect(await testSubjects.exists('esqlMoreThanOneColumnCallout')).to.be(true); + await testSubjects.click('chooseColumnBtn'); + const searchInput = await testSubjects.find('selectableColumnSearch'); + await searchInput.type('geo.dest'); + const option = await find.byCssSelector('.euiSelectableListItem'); + await option.click(); + + await common.sleep(1000); + + const editorValue = await esql.getEsqlEditorQuery(); + expect(editorValue).to.contain('FROM logstash-*\n| STATS BY geo.dest'); + }); + }); +} diff --git a/test/functional/services/esql.ts b/test/functional/services/esql.ts index 9a2bd8149563e..f3c7db58ef062 100644 --- a/test/functional/services/esql.ts +++ b/test/functional/services/esql.ts @@ -14,6 +14,7 @@ import { FtrService } from '../ftr_provider_context'; export class ESQLService extends FtrService { private readonly retry = this.ctx.getService('retry'); private readonly testSubjects = this.ctx.getService('testSubjects'); + private readonly monacoEditor = this.ctx.getService('monacoEditor'); /** Ensures that the ES|QL code editor is loaded with a given statement */ public async expectEsqlStatement(statement: string) { @@ -110,4 +111,21 @@ export class ESQLService extends FtrService { return await this.isOpenQuickReferenceFlyout(); }); } + + public async waitESQLEditorLoaded(editorSubjId = 'ESQLEditor') { + await this.monacoEditor.waitCodeEditorReady(editorSubjId); + } + + public async getEsqlEditorQuery() { + return await this.monacoEditor.getCodeEditorValue(); + } + + public async setEsqlEditorQuery(query: string) { + await this.monacoEditor.setCodeEditorValue(query); + } + + public async typeEsqlEditorQuery(query: string, editorSubjId = 'ESQLEditor') { + await this.setEsqlEditorQuery(''); // clear the default query + await this.monacoEditor.typeCodeEditorValue(query, editorSubjId); + } } diff --git a/tsconfig.base.json b/tsconfig.base.json index 54671599879c5..25caeb3ec4bff 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -392,6 +392,8 @@ "@kbn/core-http-context-server-mocks/*": ["packages/core/http/core-http-context-server-mocks/*"], "@kbn/core-http-plugin": ["test/plugin_functional/plugins/core_http"], "@kbn/core-http-plugin/*": ["test/plugin_functional/plugins/core_http/*"], + "@kbn/core-http-rate-limiter-internal": ["src/core/packages/http/rate-limiter-internal"], + "@kbn/core-http-rate-limiter-internal/*": ["src/core/packages/http/rate-limiter-internal/*"], "@kbn/core-http-request-handler-context-server": ["src/core/packages/http/request-handler-context-server"], "@kbn/core-http-request-handler-context-server/*": ["src/core/packages/http/request-handler-context-server/*"], "@kbn/core-http-request-handler-context-server-internal": ["src/core/packages/http/request-handler-context-server-internal"], @@ -876,6 +878,8 @@ "@kbn/esql-validation-autocomplete/*": ["src/platform/packages/shared/kbn-esql-validation-autocomplete/*"], "@kbn/esql-validation-example-plugin": ["examples/esql_validation_example"], "@kbn/esql-validation-example-plugin/*": ["examples/esql_validation_example/*"], + "@kbn/esql-variables-types": ["src/platform/packages/shared/kbn-esql-variables-types"], + "@kbn/esql-variables-types/*": ["src/platform/packages/shared/kbn-esql-variables-types/*"], "@kbn/eui-provider-dev-warning": ["test/plugin_functional/plugins/eui_provider_dev_warning"], "@kbn/eui-provider-dev-warning/*": ["test/plugin_functional/plugins/eui_provider_dev_warning/*"], "@kbn/event-annotation-common": ["src/platform/packages/shared/kbn-event-annotation-common"], @@ -1134,8 +1138,6 @@ "@kbn/kibana-usage-collection-plugin/*": ["src/platform/plugins/private/kibana_usage_collection/*"], "@kbn/kibana-utils-plugin": ["src/platform/plugins/shared/kibana_utils"], "@kbn/kibana-utils-plugin/*": ["src/platform/plugins/shared/kibana_utils/*"], - "@kbn/kubernetes-security-plugin": ["x-pack/solutions/security/plugins/kubernetes_security"], - "@kbn/kubernetes-security-plugin/*": ["x-pack/solutions/security/plugins/kubernetes_security/*"], "@kbn/langchain": ["x-pack/platform/packages/shared/kbn-langchain"], "@kbn/langchain/*": ["x-pack/platform/packages/shared/kbn-langchain/*"], "@kbn/language-documentation": ["src/platform/packages/private/kbn-language-documentation"], @@ -1324,8 +1326,8 @@ "@kbn/observability-ai-assistant-app-plugin/*": ["x-pack/solutions/observability/plugins/observability_ai_assistant_app/*"], "@kbn/observability-ai-assistant-management-plugin": ["x-pack/solutions/observability/plugins/observability_ai_assistant_management"], "@kbn/observability-ai-assistant-management-plugin/*": ["x-pack/solutions/observability/plugins/observability_ai_assistant_management/*"], - "@kbn/observability-ai-assistant-plugin": ["x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant"], - "@kbn/observability-ai-assistant-plugin/*": ["x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/*"], + "@kbn/observability-ai-assistant-plugin": ["x-pack/platform/plugins/shared/observability_ai_assistant"], + "@kbn/observability-ai-assistant-plugin/*": ["x-pack/platform/plugins/shared/observability_ai_assistant/*"], "@kbn/observability-ai-common": ["x-pack/solutions/observability/packages/observability_ai/observability_ai_common"], "@kbn/observability-ai-common/*": ["x-pack/solutions/observability/packages/observability_ai/observability_ai_common/*"], "@kbn/observability-ai-server": ["x-pack/solutions/observability/packages/observability_ai/observability_ai_server"], @@ -1602,8 +1604,8 @@ "@kbn/search-playground/*": ["x-pack/solutions/search/plugins/search_playground/*"], "@kbn/search-response-warnings": ["src/platform/packages/shared/kbn-search-response-warnings"], "@kbn/search-response-warnings/*": ["src/platform/packages/shared/kbn-search-response-warnings/*"], - "@kbn/search-shared-ui": ["x-pack/solutions/search/packages/search/shared_ui"], - "@kbn/search-shared-ui/*": ["x-pack/solutions/search/packages/search/shared_ui/*"], + "@kbn/search-shared-ui": ["x-pack/solutions/search/packages/shared_ui"], + "@kbn/search-shared-ui/*": ["x-pack/solutions/search/packages/shared_ui/*"], "@kbn/search-synonyms": ["x-pack/solutions/search/plugins/search_synonyms"], "@kbn/search-synonyms/*": ["x-pack/solutions/search/plugins/search_synonyms/*"], "@kbn/search-types": ["src/platform/packages/shared/kbn-search-types"], diff --git a/x-pack/.i18nrc.json b/x-pack/.i18nrc.json index 4807bc2f1e242..73ccecf769a32 100644 --- a/x-pack/.i18nrc.json +++ b/x-pack/.i18nrc.json @@ -103,7 +103,7 @@ ], "xpack.observability": "solutions/observability/plugins/observability", "xpack.observabilityAiAssistant": [ - "platform/plugins/shared/observability_solution/observability_ai_assistant", + "platform/plugins/shared/observability_ai_assistant", "solutions/observability/plugins/observability_ai_assistant_app" ], "xpack.observabilityAiAssistantManagement": "solutions/observability/plugins/observability_ai_assistant_management", @@ -130,7 +130,7 @@ ], "xpack.runtimeFields": "platform/plugins/private/runtime_fields", "xpack.screenshotting": "platform/plugins/shared/screenshotting", - "xpack.searchSharedUI": "solutions/search/packages/search/shared_ui", + "xpack.searchSharedUI": "solutions/search/packages/shared_ui", "xpack.searchHomepage": "solutions/search/plugins/search_homepage", "xpack.searchIndices": "solutions/search/plugins/search_indices", "xpack.searchNavigation": "solutions/search/plugins/search_solution/search_navigation", diff --git a/x-pack/platform/packages/private/kbn-random-sampling/src/ui/slider_control/index.test.tsx b/x-pack/platform/packages/private/kbn-random-sampling/src/ui/slider_control/index.test.tsx index 86f5ac06ceb31..866c11a98cf6e 100644 --- a/x-pack/platform/packages/private/kbn-random-sampling/src/ui/slider_control/index.test.tsx +++ b/x-pack/platform/packages/private/kbn-random-sampling/src/ui/slider_control/index.test.tsx @@ -10,13 +10,42 @@ import React from 'react'; import { I18nProvider } from '@kbn/i18n-react'; import { ControlSlider } from '.'; +const values = [ + { + label: '.001%', + value: 0.00001, + accessibleLabel: 'Point zero zero one percent, most performant', + }, + { + label: '.01%', + value: 0.0001, + }, + { + label: '.1%', + value: 0.001, + }, + { + label: '1%', + value: 0.01, + }, + { + label: '10%', + value: 0.1, + }, + { + label: '100%', + value: 1, + accessibleLabel: 'One hundred percent, most accurate', + }, +]; + describe('Slider Control', () => { it('should basically work', () => { render( @@ -26,18 +55,35 @@ describe('Slider Control', () => { expect(input.value).toBe('0'); // index 0 of the values array }); + it('should display accessible label when provided', () => { + render( + + + + ); + const input = screen.getByTestId('test-id') as HTMLInputElement; + expect(input.getAttribute('aria-valuetext')).toBe( + '0, (Point zero zero one percent, most performant)' + ); + }); + it('should fallback to 1 when the provided value is not present within the values', () => { render( ); const input = screen.getByTestId('test-id') as HTMLInputElement; - expect(input.value).toBe('2'); // index 2 of the values array + expect(input.value).toBe('5'); // index 5 of the values array }); }); diff --git a/x-pack/platform/packages/private/kbn-random-sampling/src/ui/slider_control/index.tsx b/x-pack/platform/packages/private/kbn-random-sampling/src/ui/slider_control/index.tsx index 40a9256f9ba07..080aee531da2a 100644 --- a/x-pack/platform/packages/private/kbn-random-sampling/src/ui/slider_control/index.tsx +++ b/x-pack/platform/packages/private/kbn-random-sampling/src/ui/slider_control/index.tsx @@ -9,10 +9,11 @@ import { EuiFlexGroup, EuiFlexItem, EuiRange, EuiText, useEuiTheme } from '@elas import React from 'react'; import { FormattedMessage } from '@kbn/i18n-react'; import { TooltipWrapper } from '@kbn/visualization-utils'; +import { i18n } from '@kbn/i18n'; export interface ControlSliderProps { /** Allowed values to show on the Control Slider */ - values: number[]; + values: Array<{ label: string; value: number; accessibleLabel?: string }>; /** Current value set */ currentValue: number | undefined; /** When set will show the control in a disabled state */ @@ -34,8 +35,10 @@ export function ControlSlider({ 'data-test-subj': dataTestSubj, }: ControlSliderProps) { const { euiTheme } = useEuiTheme(); - const samplingIndex = values.findIndex((v) => v === currentValue); + + const samplingIndex = values.findIndex((v) => v.value === currentValue); const currentSamplingIndex = samplingIndex > -1 ? samplingIndex : values.length - 1; + return ( { - onChange(values[Number(e.currentTarget.value)]); + onChange(values[Number(e.currentTarget.value)].value); }} showInput={false} showRange={false} @@ -70,10 +80,9 @@ export function ControlSlider({ step={1} min={0} max={values.length - 1} - ticks={values.map((v, i) => ({ - // Remove the initial 0 from values with decimal digits: 0.001 => .001 - label: `${v * 100}%`.slice(Number.isInteger(v * 100) ? 0 : 1), - value: i, + ticks={values.map((tick, index) => ({ + ...tick, + value: index, }))} /> diff --git a/x-pack/platform/packages/private/kbn-random-sampling/tsconfig.json b/x-pack/platform/packages/private/kbn-random-sampling/tsconfig.json index 6db70ecebe120..616f0c7f43190 100644 --- a/x-pack/platform/packages/private/kbn-random-sampling/tsconfig.json +++ b/x-pack/platform/packages/private/kbn-random-sampling/tsconfig.json @@ -14,6 +14,7 @@ "kbn_references": [ "@kbn/i18n-react", "@kbn/visualization-utils", + "@kbn/i18n", ], "exclude": [ "target/**/*", diff --git a/x-pack/platform/packages/shared/kbn-inference-endpoint-ui-common/src/components/providers/assets/images/jinaai.svg b/x-pack/platform/packages/shared/kbn-inference-endpoint-ui-common/src/components/providers/assets/images/jinaai.svg new file mode 100644 index 0000000000000..605c0cff86942 --- /dev/null +++ b/x-pack/platform/packages/shared/kbn-inference-endpoint-ui-common/src/components/providers/assets/images/jinaai.svg @@ -0,0 +1,13 @@ + + + Jina-color + + + + + + + + + + \ No newline at end of file diff --git a/x-pack/platform/plugins/private/index_lifecycle_management/integration_tests/edit_policy/features/request_flyout.test.ts b/x-pack/platform/plugins/private/index_lifecycle_management/integration_tests/edit_policy/features/request_flyout.test.ts index 25bbdafda2506..a94f9137cfc65 100644 --- a/x-pack/platform/plugins/private/index_lifecycle_management/integration_tests/edit_policy/features/request_flyout.test.ts +++ b/x-pack/platform/plugins/private/index_lifecycle_management/integration_tests/edit_policy/features/request_flyout.test.ts @@ -14,14 +14,6 @@ describe(' request flyout', () => { let testBed: RequestFlyoutTestBed; const { httpSetup, httpRequestsMockHelpers } = setupEnvironment(); - beforeAll(() => { - jest.useFakeTimers({ legacyFakeTimers: true }); - }); - - afterAll(() => { - jest.useRealTimers(); - }); - beforeEach(async () => { httpRequestsMockHelpers.setDefaultResponses(); @@ -34,12 +26,8 @@ describe(' request flyout', () => { }); test('renders a json in flyout for a default policy', async () => { - const { actions, component } = testBed; + const { actions } = testBed; await actions.openRequestFlyout(); - await act(async () => { - jest.advanceTimersByTime(0); // allow the flyout to open and form validation to run - }); - component.update(); const json = actions.getRequestJson(); const expected = `PUT _ilm/policy/my_policy\n${JSON.stringify( diff --git a/x-pack/platform/plugins/private/index_lifecycle_management/integration_tests/helpers/actions/request_flyout_actions.ts b/x-pack/platform/plugins/private/index_lifecycle_management/integration_tests/helpers/actions/request_flyout_actions.ts index f8004f0076788..ca79d52741595 100644 --- a/x-pack/platform/plugins/private/index_lifecycle_management/integration_tests/helpers/actions/request_flyout_actions.ts +++ b/x-pack/platform/plugins/private/index_lifecycle_management/integration_tests/helpers/actions/request_flyout_actions.ts @@ -15,7 +15,6 @@ export const createRequestFlyoutActions = (testBed: TestBed) => { const openRequestFlyout = async () => { await act(async () => { find('requestButton').simulate('click'); - jest.advanceTimersByTime(0); // Wait for the flyout to open and form validation to run }); component.update(); }; diff --git a/x-pack/platform/plugins/private/snapshot_restore/public/application/sections/home/policy_list/policy_list.tsx b/x-pack/platform/plugins/private/snapshot_restore/public/application/sections/home/policy_list/policy_list.tsx index 6a74b92c4ac57..09c07080f1134 100644 --- a/x-pack/platform/plugins/private/snapshot_restore/public/application/sections/home/policy_list/policy_list.tsx +++ b/x-pack/platform/plugins/private/snapshot_restore/public/application/sections/home/policy_list/policy_list.tsx @@ -162,8 +162,6 @@ export const PolicyList: React.FunctionComponent ); } else { - const policySchedules = policies.map((policy: SlmPolicy) => policy.schedule); - const hasDuplicateSchedules = policySchedules.length > new Set(policySchedules).size; const hasRetention = Boolean(policies.find((policy: SlmPolicy) => policy.retention)); const isSlmRunning = slmStatus?.operation_mode === SLM_STATE.RUNNING; @@ -203,27 +201,6 @@ export const PolicyList: React.FunctionComponent ) : null} - {hasDuplicateSchedules ? ( - - - } - color="warning" - iconType="warning" - > - - - - - ) : null} - {hasRetention ? ( { let testBed: ElasticsearchTestBed; let httpRequestsMockHelpers: ReturnType['httpRequestsMockHelpers']; let httpSetup: ReturnType['httpSetup']; - const clusterSettingDeprecation = esDeprecationsMockResponse.deprecations[4]; + const clusterSettingDeprecation = esDeprecationsMockResponse.migrationsDeprecations[4]; beforeEach(async () => { const mockEnvironment = setupEnvironment(); diff --git a/x-pack/platform/plugins/private/upgrade_assistant/__jest__/client_integration/es_deprecations/default_deprecation_flyout.test.ts b/x-pack/platform/plugins/private/upgrade_assistant/__jest__/client_integration/es_deprecations/default_deprecation_flyout.test.ts index 6c716dd5ad12e..34504f4a234dc 100644 --- a/x-pack/platform/plugins/private/upgrade_assistant/__jest__/client_integration/es_deprecations/default_deprecation_flyout.test.ts +++ b/x-pack/platform/plugins/private/upgrade_assistant/__jest__/client_integration/es_deprecations/default_deprecation_flyout.test.ts @@ -46,7 +46,7 @@ describe('Default deprecation flyout', () => { }); test('renders a flyout with deprecation details', async () => { - const multiFieldsDeprecation = esDeprecationsMockResponse.deprecations[2]; + const multiFieldsDeprecation = esDeprecationsMockResponse.migrationsDeprecations[2]; const { actions, find, exists } = testBed; await actions.table.clickDeprecationRowAt('default', 0); diff --git a/x-pack/platform/plugins/private/upgrade_assistant/__jest__/client_integration/es_deprecations/deprecations_list.test.ts b/x-pack/platform/plugins/private/upgrade_assistant/__jest__/client_integration/es_deprecations/deprecations_list.test.ts index f73eb7fbfabbe..2cd44d63dec9e 100644 --- a/x-pack/platform/plugins/private/upgrade_assistant/__jest__/client_integration/es_deprecations/deprecations_list.test.ts +++ b/x-pack/platform/plugins/private/upgrade_assistant/__jest__/client_integration/es_deprecations/deprecations_list.test.ts @@ -60,7 +60,7 @@ describe('ES deprecations table', () => { // Verify all deprecations appear in the table expect(find('deprecationTableRow').length).toEqual( - esDeprecationsMockResponse.deprecations.length + esDeprecationsMockResponse.migrationsDeprecations.length ); }); @@ -69,8 +69,8 @@ describe('ES deprecations table', () => { await actions.table.clickRefreshButton(); - const mlDeprecation = esDeprecationsMockResponse.deprecations[0]; - const reindexDeprecation = esDeprecationsMockResponse.deprecations[3]; + const mlDeprecation = esDeprecationsMockResponse.migrationsDeprecations[0]; + const reindexDeprecation = esDeprecationsMockResponse.migrationsDeprecations[3]; // Since upgradeStatusMockResponse includes ML and reindex actions (which require fetching status), there will be 4 requests made expect(httpSetup.get).toHaveBeenCalledWith( @@ -96,10 +96,10 @@ describe('ES deprecations table', () => { it('shows critical and warning deprecations count', () => { const { find } = testBed; - const criticalDeprecations = esDeprecationsMockResponse.deprecations.filter( + const criticalDeprecations = esDeprecationsMockResponse.migrationsDeprecations.filter( (deprecation) => deprecation.isCritical ); - const warningDeprecations = esDeprecationsMockResponse.deprecations.filter( + const warningDeprecations = esDeprecationsMockResponse.migrationsDeprecations.filter( (deprecation) => deprecation.isCritical === false ); @@ -133,7 +133,7 @@ describe('ES deprecations table', () => { await actions.searchBar.clickCriticalFilterButton(); - const criticalDeprecations = esDeprecationsMockResponse.deprecations.filter( + const criticalDeprecations = esDeprecationsMockResponse.migrationsDeprecations.filter( (deprecation) => deprecation.isCritical ); @@ -142,7 +142,7 @@ describe('ES deprecations table', () => { await actions.searchBar.clickCriticalFilterButton(); expect(find('deprecationTableRow').length).toEqual( - esDeprecationsMockResponse.deprecations.length + esDeprecationsMockResponse.migrationsDeprecations.length ); }); @@ -165,7 +165,7 @@ describe('ES deprecations table', () => { component.update(); - const clusterDeprecations = esDeprecationsMockResponse.deprecations.filter( + const clusterDeprecations = esDeprecationsMockResponse.migrationsDeprecations.filter( (deprecation) => deprecation.type === 'cluster_settings' ); @@ -174,7 +174,7 @@ describe('ES deprecations table', () => { it('filters results by query string', async () => { const { find, actions } = testBed; - const multiFieldsDeprecation = esDeprecationsMockResponse.deprecations[2]; + const multiFieldsDeprecation = esDeprecationsMockResponse.migrationsDeprecations[2]; await actions.searchBar.setSearchInputValue(multiFieldsDeprecation.message); @@ -205,7 +205,7 @@ describe('ES deprecations table', () => { describe('pagination', () => { const esDeprecationsMockResponseWithManyDeprecations = createEsDeprecationsMockResponse(20); - const { deprecations } = esDeprecationsMockResponseWithManyDeprecations; + const { migrationsDeprecations } = esDeprecationsMockResponseWithManyDeprecations; beforeEach(async () => { httpRequestsMockHelpers.setLoadEsDeprecationsResponse( @@ -229,7 +229,7 @@ describe('ES deprecations table', () => { const { find, actions } = testBed; expect(find('esDeprecationsPagination').find('.euiPagination__item').length).toEqual( - Math.round(deprecations.length / 50) // Default rows per page is 50 + Math.round(migrationsDeprecations.length / 50) // Default rows per page is 50 ); expect(find('deprecationTableRow').length).toEqual(50); @@ -237,7 +237,7 @@ describe('ES deprecations table', () => { await actions.pagination.clickPaginationAt(1); // On the second (last) page, we expect to see the remaining deprecations - expect(find('deprecationTableRow').length).toEqual(deprecations.length - 50); + expect(find('deprecationTableRow').length).toEqual(migrationsDeprecations.length - 50); }); it('allows the number of viewable rows to change', async () => { @@ -260,15 +260,17 @@ describe('ES deprecations table', () => { component.update(); expect(find('esDeprecationsPagination').find('.euiPagination__item').length).toEqual( - Math.round(deprecations.length / 100) // Rows per page is now 100 + Math.round(migrationsDeprecations.length / 100) // Rows per page is now 100 ); - expect(find('deprecationTableRow').length).toEqual(deprecations.length); + expect(find('deprecationTableRow').length).toEqual(migrationsDeprecations.length); }); it('updates pagination when filters change', async () => { const { actions, find } = testBed; - const criticalDeprecations = deprecations.filter((deprecation) => deprecation.isCritical); + const criticalDeprecations = migrationsDeprecations.filter( + (deprecation) => deprecation.isCritical + ); await actions.searchBar.clickCriticalFilterButton(); @@ -279,7 +281,7 @@ describe('ES deprecations table', () => { it('updates pagination on search', async () => { const { actions, find } = testBed; - const reindexDeprecations = deprecations.filter( + const reindexDeprecations = migrationsDeprecations.filter( (deprecation) => deprecation.correctiveAction?.type === 'reindex' ); @@ -295,7 +297,9 @@ describe('ES deprecations table', () => { beforeEach(async () => { const noDeprecationsResponse = { totalCriticalDeprecations: 0, - deprecations: [], + migrationsDeprecations: [], + totalCriticalHealthIssues: 0, + enrichedHealthIndicators: [], }; httpRequestsMockHelpers.setLoadEsDeprecationsResponse(noDeprecationsResponse); diff --git a/x-pack/platform/plugins/private/upgrade_assistant/__jest__/client_integration/es_deprecations/index_settings_deprecation_flyout.test.ts b/x-pack/platform/plugins/private/upgrade_assistant/__jest__/client_integration/es_deprecations/index_settings_deprecation_flyout.test.ts index 10d7481bc232d..de96a180183ba 100644 --- a/x-pack/platform/plugins/private/upgrade_assistant/__jest__/client_integration/es_deprecations/index_settings_deprecation_flyout.test.ts +++ b/x-pack/platform/plugins/private/upgrade_assistant/__jest__/client_integration/es_deprecations/index_settings_deprecation_flyout.test.ts @@ -20,7 +20,7 @@ describe('Index settings deprecation flyout', () => { let testBed: ElasticsearchTestBed; let httpRequestsMockHelpers: ReturnType['httpRequestsMockHelpers']; let httpSetup: ReturnType['httpSetup']; - const indexSettingDeprecation = esDeprecationsMockResponse.deprecations[1]; + const indexSettingDeprecation = esDeprecationsMockResponse.migrationsDeprecations[1]; beforeEach(async () => { const mockEnvironment = setupEnvironment(); httpRequestsMockHelpers = mockEnvironment.httpRequestsMockHelpers; diff --git a/x-pack/platform/plugins/private/upgrade_assistant/__jest__/client_integration/es_deprecations/ml_snapshots_deprecation_flyout.test.ts b/x-pack/platform/plugins/private/upgrade_assistant/__jest__/client_integration/es_deprecations/ml_snapshots_deprecation_flyout.test.ts index 3f50690dbdeb7..aa5f80b48c447 100644 --- a/x-pack/platform/plugins/private/upgrade_assistant/__jest__/client_integration/es_deprecations/ml_snapshots_deprecation_flyout.test.ts +++ b/x-pack/platform/plugins/private/upgrade_assistant/__jest__/client_integration/es_deprecations/ml_snapshots_deprecation_flyout.test.ts @@ -14,7 +14,7 @@ import { esDeprecationsMockResponse, MOCK_SNAPSHOT_ID, MOCK_JOB_ID } from './moc describe('Machine learning deprecation flyout', () => { let testBed: ElasticsearchTestBed; - const mlDeprecation = esDeprecationsMockResponse.deprecations[0]; + const mlDeprecation = esDeprecationsMockResponse.migrationsDeprecations[0]; let httpRequestsMockHelpers: ReturnType['httpRequestsMockHelpers']; let httpSetup: ReturnType['httpSetup']; beforeEach(async () => { diff --git a/x-pack/platform/plugins/private/upgrade_assistant/__jest__/client_integration/es_deprecations/mocked_responses.ts b/x-pack/platform/plugins/private/upgrade_assistant/__jest__/client_integration/es_deprecations/mocked_responses.ts index 2f3bece2043a8..2dc33c29de9ec 100644 --- a/x-pack/platform/plugins/private/upgrade_assistant/__jest__/client_integration/es_deprecations/mocked_responses.ts +++ b/x-pack/platform/plugins/private/upgrade_assistant/__jest__/client_integration/es_deprecations/mocked_responses.ts @@ -77,13 +77,15 @@ const MOCK_DEFAULT_DEPRECATION: EnrichedDeprecationInfo = { export const esDeprecationsMockResponse: ESUpgradeStatus = { totalCriticalDeprecations: 2, - deprecations: [ + migrationsDeprecations: [ MOCK_ML_DEPRECATION, MOCK_INDEX_SETTING_DEPRECATION, MOCK_DEFAULT_DEPRECATION, MOCK_REINDEX_DEPRECATION, MOCK_CLUSTER_SETTING_DEPRECATION, ], + totalCriticalHealthIssues: 0, + enrichedHealthIndicators: [], }; // Useful for testing pagination where a large number of deprecations are needed @@ -118,7 +120,7 @@ export const createEsDeprecationsMockResponse = ( () => MOCK_DEFAULT_DEPRECATION ); - const deprecations: EnrichedDeprecationInfo[] = [ + const migrationsDeprecations: EnrichedDeprecationInfo[] = [ ...defaultDeprecations, ...reindexDeprecations, ...indexSettingsDeprecations, @@ -127,6 +129,8 @@ export const createEsDeprecationsMockResponse = ( return { totalCriticalDeprecations: mlDeprecations.length + reindexDeprecations.length, - deprecations, + migrationsDeprecations, + totalCriticalHealthIssues: esDeprecationsMockResponse.totalCriticalHealthIssues, + enrichedHealthIndicators: esDeprecationsMockResponse.enrichedHealthIndicators, }; }; diff --git a/x-pack/platform/plugins/private/upgrade_assistant/__jest__/client_integration/es_deprecations/reindex_deprecation_flyout.test.ts b/x-pack/platform/plugins/private/upgrade_assistant/__jest__/client_integration/es_deprecations/reindex_deprecation_flyout.test.ts index 29e6a80fc41bd..ad5d5d74f8059 100644 --- a/x-pack/platform/plugins/private/upgrade_assistant/__jest__/client_integration/es_deprecations/reindex_deprecation_flyout.test.ts +++ b/x-pack/platform/plugins/private/upgrade_assistant/__jest__/client_integration/es_deprecations/reindex_deprecation_flyout.test.ts @@ -68,7 +68,7 @@ describe('Reindex deprecation flyout', () => { }); it('renders a flyout with reindexing details', async () => { - const reindexDeprecation = esDeprecationsMockResponse.deprecations[3]; + const reindexDeprecation = esDeprecationsMockResponse.migrationsDeprecations[3]; const { actions, find, exists } = testBed; await actions.table.clickDeprecationRowAt('reindex', 0); diff --git a/x-pack/platform/plugins/private/upgrade_assistant/__jest__/client_integration/overview/fix_issues_step/mock_es_issues.ts b/x-pack/platform/plugins/private/upgrade_assistant/__jest__/client_integration/overview/fix_issues_step/mock_es_issues.ts index 99c0f4892a4ef..4fd2f767bc707 100644 --- a/x-pack/platform/plugins/private/upgrade_assistant/__jest__/client_integration/overview/fix_issues_step/mock_es_issues.ts +++ b/x-pack/platform/plugins/private/upgrade_assistant/__jest__/client_integration/overview/fix_issues_step/mock_es_issues.ts @@ -9,7 +9,7 @@ import { ESUpgradeStatus } from '../../../../common/types'; export const esCriticalAndWarningDeprecations: ESUpgradeStatus = { totalCriticalDeprecations: 1, - deprecations: [ + migrationsDeprecations: [ { isCritical: true, type: 'cluster_settings', @@ -34,11 +34,13 @@ export const esCriticalAndWarningDeprecations: ESUpgradeStatus = { }, }, ], + totalCriticalHealthIssues: 0, + enrichedHealthIndicators: [], }; export const esCriticalOnlyDeprecations: ESUpgradeStatus = { totalCriticalDeprecations: 1, - deprecations: [ + migrationsDeprecations: [ { isCritical: true, type: 'cluster_settings', @@ -49,9 +51,13 @@ export const esCriticalOnlyDeprecations: ESUpgradeStatus = { 'The Index Lifecycle Management poll interval setting [indices.lifecycle.poll_interval] is currently set to [500ms], but must be 1s or greater', }, ], + totalCriticalHealthIssues: 0, + enrichedHealthIndicators: [], }; export const esNoDeprecations: ESUpgradeStatus = { totalCriticalDeprecations: 0, - deprecations: [], + migrationsDeprecations: [], + totalCriticalHealthIssues: 0, + enrichedHealthIndicators: [], }; diff --git a/x-pack/platform/plugins/private/upgrade_assistant/common/types.ts b/x-pack/platform/plugins/private/upgrade_assistant/common/types.ts index 8e484a047c7b1..bff91b90698a6 100644 --- a/x-pack/platform/plugins/private/upgrade_assistant/common/types.ts +++ b/x-pack/platform/plugins/private/upgrade_assistant/common/types.ts @@ -244,7 +244,9 @@ export interface CloudBackupStatus { export interface ESUpgradeStatus { totalCriticalDeprecations: number; - deprecations: EnrichedDeprecationInfo[]; + migrationsDeprecations: EnrichedDeprecationInfo[]; + totalCriticalHealthIssues: number; + enrichedHealthIndicators: EnrichedDeprecationInfo[]; } export interface ResolveIndexResponseFromES { diff --git a/x-pack/platform/plugins/private/upgrade_assistant/public/application/components/es_deprecations/es_deprecations.tsx b/x-pack/platform/plugins/private/upgrade_assistant/public/application/components/es_deprecations/es_deprecations.tsx index adb6feeba1cbf..cec257f195892 100644 --- a/x-pack/platform/plugins/private/upgrade_assistant/public/application/components/es_deprecations/es_deprecations.tsx +++ b/x-pack/platform/plugins/private/upgrade_assistant/public/application/components/es_deprecations/es_deprecations.tsx @@ -127,8 +127,8 @@ export const EsDeprecations = withRouter(({ history }: RouteComponentProps) => { warningDeprecations: number; criticalDeprecations: number; } = useMemo( - () => getDeprecationCountByLevel(esDeprecations?.deprecations || []), - [esDeprecations?.deprecations] + () => getDeprecationCountByLevel(esDeprecations?.migrationsDeprecations || []), + [esDeprecations?.migrationsDeprecations] ); useEffect(() => { @@ -152,7 +152,7 @@ export const EsDeprecations = withRouter(({ history }: RouteComponentProps) => { return {i18nTexts.isLoading}; } - if (esDeprecations?.deprecations?.length === 0) { + if (esDeprecations?.migrationsDeprecations?.length === 0) { return ( { - +
); }); diff --git a/x-pack/platform/plugins/private/upgrade_assistant/public/application/components/overview/fix_issues_step/components/es_deprecation_issues_panel.tsx b/x-pack/platform/plugins/private/upgrade_assistant/public/application/components/overview/fix_issues_step/components/es_deprecation_issues_panel.tsx index b4258ababc92e..2ae7399c38ad1 100644 --- a/x-pack/platform/plugins/private/upgrade_assistant/public/application/components/overview/fix_issues_step/components/es_deprecation_issues_panel.tsx +++ b/x-pack/platform/plugins/private/upgrade_assistant/public/application/components/overview/fix_issues_step/components/es_deprecation_issues_panel.tsx @@ -23,11 +23,13 @@ export const EsDeprecationIssuesPanel: FunctionComponent = ({ setIsFixed const { data: esDeprecations, isLoading, error } = api.useLoadEsDeprecations(); const criticalDeprecationsCount = - esDeprecations?.deprecations?.filter((deprecation) => deprecation.isCritical)?.length ?? 0; + esDeprecations?.migrationsDeprecations?.filter((deprecation) => deprecation.isCritical) + ?.length ?? 0; const warningDeprecationsCount = - esDeprecations?.deprecations?.filter((deprecation) => deprecation.isCritical === false) - ?.length ?? 0; + esDeprecations?.migrationsDeprecations?.filter( + (deprecation) => deprecation.isCritical === false + )?.length ?? 0; const errorMessage = error && getEsDeprecationError(error).message; diff --git a/x-pack/platform/plugins/private/upgrade_assistant/server/lib/es_deprecations_status/__snapshots__/index.test.ts.snap b/x-pack/platform/plugins/private/upgrade_assistant/server/lib/es_deprecations_status/__snapshots__/index.test.ts.snap index 7f6b7826da8a8..a0e659be79a7a 100644 --- a/x-pack/platform/plugins/private/upgrade_assistant/server/lib/es_deprecations_status/__snapshots__/index.test.ts.snap +++ b/x-pack/platform/plugins/private/upgrade_assistant/server/lib/es_deprecations_status/__snapshots__/index.test.ts.snap @@ -2,7 +2,8 @@ exports[`getESUpgradeStatus returns the correct shape of data 1`] = ` Object { - "deprecations": Array [ + "enrichedHealthIndicators": Array [], + "migrationsDeprecations": Array [ Object { "correctiveAction": undefined, "details": "templates using \`template\` field: security_audit_log,watches,.monitoring-alerts,triggered_watches,.ml-anomalies-,.ml-notifications,.ml-meta,.monitoring-kibana,.monitoring-es,.monitoring-logstash,.watch-history-6,.ml-state,security-index-template", @@ -183,5 +184,6 @@ Object { }, ], "totalCriticalDeprecations": 6, + "totalCriticalHealthIssues": 0, } `; diff --git a/x-pack/platform/plugins/private/upgrade_assistant/server/lib/es_deprecations_status/index.test.ts b/x-pack/platform/plugins/private/upgrade_assistant/server/lib/es_deprecations_status/index.test.ts index dc1e4f48bc3ef..d2cc3b9ac67f5 100644 --- a/x-pack/platform/plugins/private/upgrade_assistant/server/lib/es_deprecations_status/index.test.ts +++ b/x-pack/platform/plugins/private/upgrade_assistant/server/lib/es_deprecations_status/index.test.ts @@ -126,9 +126,15 @@ describe('getESUpgradeStatus', () => { }); const upgradeStatus = await getESUpgradeStatus(esClient, featureSet); - - expect(upgradeStatus.deprecations).toHaveLength(0); - expect(upgradeStatus.totalCriticalDeprecations).toBe(0); + const { + totalCriticalDeprecations, + migrationsDeprecations, + totalCriticalHealthIssues, + enrichedHealthIndicators, + } = upgradeStatus; + expect([...migrationsDeprecations, ...enrichedHealthIndicators]).toHaveLength(0); + expect(totalCriticalDeprecations).toBe(0); + expect(totalCriticalHealthIssues).toBe(0); }); it('filters out ml_settings if featureSet.mlSnapshots is set to false', async () => { @@ -140,7 +146,10 @@ describe('getESUpgradeStatus', () => { esClient.asCurrentUser.migration.deprecations.mockResponse(mockResponse); const enabledUpgradeStatus = await getESUpgradeStatus(esClient, { ...featureSet }); - expect(enabledUpgradeStatus.deprecations).toHaveLength(2); + expect([ + ...enabledUpgradeStatus.migrationsDeprecations, + ...enabledUpgradeStatus.enrichedHealthIndicators, + ]).toHaveLength(2); expect(enabledUpgradeStatus.totalCriticalDeprecations).toBe(1); const disabledUpgradeStatus = await getESUpgradeStatus(esClient, { @@ -148,7 +157,10 @@ describe('getESUpgradeStatus', () => { mlSnapshots: false, }); - expect(disabledUpgradeStatus.deprecations).toHaveLength(0); + expect([ + ...disabledUpgradeStatus.migrationsDeprecations, + ...disabledUpgradeStatus.enrichedHealthIndicators, + ]).toHaveLength(0); expect(disabledUpgradeStatus.totalCriticalDeprecations).toBe(0); }); @@ -160,7 +172,10 @@ describe('getESUpgradeStatus', () => { esClient.asCurrentUser.migration.deprecations.mockResponse(mockResponse); const enabledUpgradeStatus = await getESUpgradeStatus(esClient, { ...featureSet }); - expect(enabledUpgradeStatus.deprecations).toHaveLength(1); + expect([ + ...enabledUpgradeStatus.migrationsDeprecations, + ...enabledUpgradeStatus.enrichedHealthIndicators, + ]).toHaveLength(1); expect(enabledUpgradeStatus.totalCriticalDeprecations).toBe(1); const disabledUpgradeStatus = await getESUpgradeStatus(esClient, { @@ -168,7 +183,10 @@ describe('getESUpgradeStatus', () => { migrateDataStreams: false, }); - expect(disabledUpgradeStatus.deprecations).toHaveLength(0); + expect([ + ...disabledUpgradeStatus.migrationsDeprecations, + ...disabledUpgradeStatus.enrichedHealthIndicators, + ]).toHaveLength(0); expect(disabledUpgradeStatus.totalCriticalDeprecations).toBe(0); }); @@ -203,7 +221,10 @@ describe('getESUpgradeStatus', () => { reindexCorrectiveActions: false, }); - expect(upgradeStatus.deprecations).toHaveLength(0); + expect([ + ...upgradeStatus.migrationsDeprecations, + ...upgradeStatus.enrichedHealthIndicators, + ]).toHaveLength(0); expect(upgradeStatus.totalCriticalDeprecations).toBe(0); }); @@ -235,9 +256,11 @@ describe('getESUpgradeStatus', () => { }); const upgradeStatus = await getESUpgradeStatus(esClient, featureSet); - - expect(upgradeStatus.totalCriticalDeprecations).toBe(2); - expect(upgradeStatus.deprecations).toMatchInlineSnapshot(` + expect(upgradeStatus.totalCriticalHealthIssues + upgradeStatus.totalCriticalDeprecations).toBe( + 2 + ); + expect([...upgradeStatus.enrichedHealthIndicators, ...upgradeStatus.migrationsDeprecations]) + .toMatchInlineSnapshot(` Array [ Object { "correctiveAction": Object { diff --git a/x-pack/platform/plugins/private/upgrade_assistant/server/lib/es_deprecations_status/index.ts b/x-pack/platform/plugins/private/upgrade_assistant/server/lib/es_deprecations_status/index.ts index 062c62660a538..ac052e92d1275 100644 --- a/x-pack/platform/plugins/private/upgrade_assistant/server/lib/es_deprecations_status/index.ts +++ b/x-pack/platform/plugins/private/upgrade_assistant/server/lib/es_deprecations_status/index.ts @@ -56,14 +56,22 @@ export async function getESUpgradeStatus( return status !== 'green'; }) as EnrichedDeprecationInfo[]; - return [...enrichedHealthIndicators, ...toggledMigrationsDeprecations]; + return { + enrichedHealthIndicators, + migrationsDeprecations: toggledMigrationsDeprecations, + }; }; + const { enrichedHealthIndicators, migrationsDeprecations } = await getCombinedDeprecations(); - const combinedDeprecations = await getCombinedDeprecations(); - const criticalWarnings = combinedDeprecations.filter(({ isCritical }) => isCritical === true); - - return { - totalCriticalDeprecations: criticalWarnings.length, - deprecations: combinedDeprecations, + const result = { + totalCriticalDeprecations: migrationsDeprecations.filter( + ({ isCritical }) => isCritical === true + ).length, + migrationsDeprecations, + totalCriticalHealthIssues: enrichedHealthIndicators.filter( + ({ isCritical }) => isCritical === true + ).length, + enrichedHealthIndicators, }; + return result; } diff --git a/x-pack/platform/plugins/private/upgrade_assistant/server/lib/upgrade_type.test.ts b/x-pack/platform/plugins/private/upgrade_assistant/server/lib/upgrade_type.test.ts new file mode 100644 index 0000000000000..e3a0fd2a80f79 --- /dev/null +++ b/x-pack/platform/plugins/private/upgrade_assistant/server/lib/upgrade_type.test.ts @@ -0,0 +1,43 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { getUpgradeType } from './upgrade_type'; +import { versionService } from './version'; +import semver, { SemVer } from 'semver'; + +describe('getUpgradeType', () => { + let current: SemVer; + beforeEach(() => { + versionService.setup('8.0.0'); + current = versionService.getCurrentVersion(); + }); + it('returns null if the upgrade target version is the same as the current version', () => { + const target = current.raw.toString(); + const result = getUpgradeType({ current, target }); + expect(result).toBeNull(); + }); + it("returns 'major' if the upgrade target version is the next major", () => { + const target = semver.inc(current, 'major')?.toString()!; + const result = getUpgradeType({ current, target }); + expect(result).toBe('major'); + }); + it("returns 'minor' if the upgrade target version is the next minor", () => { + const target = semver.inc(current, 'minor')?.toString()!; + const result = getUpgradeType({ current, target }); + expect(result).toBe('minor'); + }); + it('returns undefined if the upgrade target version is more than 1 major', () => { + const target = new SemVer('10.0.0').raw.toString(); + const result = getUpgradeType({ current, target }); + expect(result).toBeUndefined(); + }); + it('returns undefined if the upgrade target version is less than the current version', () => { + const target = new SemVer('7.0.0').raw.toString(); + const result = getUpgradeType({ current, target }); + expect(result).toBeUndefined(); + }); +}); diff --git a/x-pack/platform/plugins/private/upgrade_assistant/server/lib/upgrade_type.ts b/x-pack/platform/plugins/private/upgrade_assistant/server/lib/upgrade_type.ts new file mode 100644 index 0000000000000..2ac5e33d8dbc1 --- /dev/null +++ b/x-pack/platform/plugins/private/upgrade_assistant/server/lib/upgrade_type.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 semver, { SemVer } from 'semver'; + +export interface UpgradeTypeParams { + current: SemVer; + target: string; +} + +/** + * @param {SemVer} current kibana version + * @param {string} target version to upgrade to, defaults to next major + * @returns {semver.ReleaseType | null | undefined} null if same version, undefined if target version is out of bounds + */ +export const getUpgradeType = ({ current, target }: UpgradeTypeParams) => { + const targetVersion = semver.coerce(target)!; + const versionDiff = targetVersion.major - current.major; + if (versionDiff > 1 || versionDiff < 0) { + return; + } + return semver.diff(current, semver.coerce(target)!); +}; diff --git a/x-pack/platform/plugins/private/upgrade_assistant/server/lib/version.ts b/x-pack/platform/plugins/private/upgrade_assistant/server/lib/version.ts index 49ec4c223fdf2..b67468ec2a572 100644 --- a/x-pack/platform/plugins/private/upgrade_assistant/server/lib/version.ts +++ b/x-pack/platform/plugins/private/upgrade_assistant/server/lib/version.ts @@ -7,7 +7,15 @@ import SemVer from 'semver/classes/semver'; -export class Version { +export interface IVersion { + setup(version: string): void; + getCurrentVersion(): SemVer; + getMajorVersion(): number; + getNextMajorVersion(): number; + getPrevMajorVersion(): number; +} + +export class Version implements IVersion { private version!: SemVer; public setup(version: string) { diff --git a/x-pack/platform/plugins/private/upgrade_assistant/server/plugin.ts b/x-pack/platform/plugins/private/upgrade_assistant/server/plugin.ts index 3df9f7deced9d..9641fd52ed324 100644 --- a/x-pack/platform/plugins/private/upgrade_assistant/server/plugin.ts +++ b/x-pack/platform/plugins/private/upgrade_assistant/server/plugin.ts @@ -119,6 +119,8 @@ export class UpgradeAssistantServerPlugin implements Plugin { }); const router = http.createRouter(); + // Initialize version service with current kibana version + versionService.setup(this.kibanaVersion); const dependencies: RouteDependencies = { router, @@ -139,11 +141,10 @@ export class UpgradeAssistantServerPlugin implements Plugin { featureSet: this.initialFeatureSet, isSecurityEnabled: () => security !== undefined && security.license.isEnabled(), }, + current: versionService.getCurrentVersion(), + defaultTarget: versionService.getNextMajorVersion(), }; - // Initialize version service with current kibana version - versionService.setup(this.kibanaVersion); - registerRoutes(dependencies, this.getWorker.bind(this)); if (usageCollection) { diff --git a/x-pack/platform/plugins/private/upgrade_assistant/server/routes/es_deprecations.test.ts b/x-pack/platform/plugins/private/upgrade_assistant/server/routes/es_deprecations.test.ts index f4792d3a24250..344e0ed76df25 100644 --- a/x-pack/platform/plugins/private/upgrade_assistant/server/routes/es_deprecations.test.ts +++ b/x-pack/platform/plugins/private/upgrade_assistant/server/routes/es_deprecations.test.ts @@ -54,8 +54,10 @@ describe('ES deprecations API', () => { describe('GET /api/upgrade_assistant/es_deprecations', () => { it('returns state', async () => { ESUpgradeStatusApis.getESUpgradeStatus.mockResolvedValue({ - deprecations: [], + migrationsDeprecations: [], + enrichedHealthIndicators: [], totalCriticalDeprecations: 0, + totalCriticalHealthIssues: 0, }); const resp = await routeDependencies.router.getHandler({ method: 'get', @@ -64,7 +66,7 @@ describe('ES deprecations API', () => { expect(resp.status).toEqual(200); expect(JSON.stringify(resp.payload)).toMatchInlineSnapshot( - `"{\\"deprecations\\":[],\\"totalCriticalDeprecations\\":0}"` + `"{\\"migrationsDeprecations\\":[],\\"enrichedHealthIndicators\\":[],\\"totalCriticalDeprecations\\":0,\\"totalCriticalHealthIssues\\":0}"` ); }); diff --git a/x-pack/platform/plugins/private/upgrade_assistant/server/routes/es_deprecations.ts b/x-pack/platform/plugins/private/upgrade_assistant/server/routes/es_deprecations.ts index 3b3d2387c196a..aa015c0523a18 100644 --- a/x-pack/platform/plugins/private/upgrade_assistant/server/routes/es_deprecations.ts +++ b/x-pack/platform/plugins/private/upgrade_assistant/server/routes/es_deprecations.ts @@ -41,7 +41,7 @@ export function registerESDeprecationRoutes({ const asCurrentUser = client.asCurrentUser; const reindexActions = reindexActionsFactory(savedObjectsClient, asCurrentUser); const reindexService = reindexServiceFactory(asCurrentUser, reindexActions, log, licensing); - const indexNames = status.deprecations + const indexNames = [...status.migrationsDeprecations, ...status.enrichedHealthIndicators] .filter(({ index }) => typeof index !== 'undefined') .map(({ index }) => index as string); diff --git a/x-pack/platform/plugins/private/upgrade_assistant/server/routes/status.test.ts b/x-pack/platform/plugins/private/upgrade_assistant/server/routes/status.test.ts index 21daa3e69697e..ada9c4a16fdfa 100644 --- a/x-pack/platform/plugins/private/upgrade_assistant/server/routes/status.test.ts +++ b/x-pack/platform/plugins/private/upgrade_assistant/server/routes/status.test.ts @@ -15,7 +15,10 @@ import { getESUpgradeStatus } from '../lib/es_deprecations_status'; import { getKibanaUpgradeStatus } from '../lib/kibana_status'; import { getESSystemIndicesMigrationStatus } from '../lib/es_system_indices_migration'; import type { FeatureSet } from '../../common/types'; +import { versionService } from '../lib/version'; +import { getMockVersionInfo } from '../lib/__fixtures__/version'; +const { currentVersion, nextMajor } = getMockVersionInfo(); jest.mock('../lib/es_version_precheck', () => ({ versionCheckHandlerWrapper: (a: any) => a, })); @@ -36,28 +39,36 @@ jest.mock('../lib/es_system_indices_migration', () => ({ const getESSystemIndicesMigrationStatusMock = getESSystemIndicesMigrationStatus as jest.Mock; const esDeprecationsResponse = { - cluster: [ + totalCriticalDeprecations: 1, + migrationsDeprecations: [ { - level: 'critical', - message: - 'Model snapshot [1] for job [deprecation_check_job] has an obsolete minimum version [6.3.0].', - details: 'Delete model snapshot [1] or update it to 7.0.0 or greater.', - url: 'doc_url', - correctiveAction: { - type: 'mlSnapshot', - snapshotId: '1', - jobId: 'deprecation_check_job', - }, + // This is a critical migration deprecation object, but it's not used in the tests }, ], - indices: [], + totalCriticalHealthIssues: 0, + enrichedHealthIndicators: [], +}; + +const esHealthResponse = { totalCriticalDeprecations: 1, + migrationsDeprecations: [ + { + // This is a critical migration deprecation object, but it's not used in the tests + }, + ], + totalCriticalHealthIssues: 1, + enrichedHealthIndicators: [ + { + status: 'red', // this is a critical health issue + }, + ], }; const esNoDeprecationsResponse = { - cluster: [], - indices: [], totalCriticalDeprecations: 0, + migrationsDeprecations: [], + totalCriticalHealthIssues: 0, + enrichedHealthIndicators: [], }; const systemIndicesMigrationResponse = { @@ -87,27 +98,32 @@ const systemIndicesNoMigrationResponse = { }; describe('Status API', () => { - const registerRoutes = (featureSetOverrides: Partial = {}) => { - const mockRouter = createMockRouter(); - const routeDependencies: any = { - config: { - featureSet: { - mlSnapshots: true, - migrateSystemIndices: true, - reindexCorrectiveActions: true, - ...featureSetOverrides, - }, - }, - router: mockRouter, - lib: { handleEsError }, - }; + beforeAll(() => { + versionService.setup('8.17.0'); + }); - registerUpgradeStatusRoute(routeDependencies); + describe('GET /api/upgrade_assistant/status for major upgrade', () => { + const registerRoutes = (featureSetOverrides: Partial = {}) => { + const mockRouter = createMockRouter(); + const routeDependencies: any = { + config: { + featureSet: { + mlSnapshots: true, + migrateSystemIndices: true, + reindexCorrectiveActions: true, + ...featureSetOverrides, + }, + }, + router: mockRouter, + lib: { handleEsError }, + current: currentVersion, + defaultTarget: nextMajor, + }; - return { mockRouter, routeDependencies }; - }; + registerUpgradeStatusRoute(routeDependencies); - describe('GET /api/upgrade_assistant/status', () => { + return { mockRouter, routeDependencies }; + }; afterEach(() => { jest.resetAllMocks(); }); @@ -128,6 +144,7 @@ describe('Status API', () => { })(routeHandlerContextMock, createRequestMock(), kibanaResponseFactory); expect(getESSystemIndicesMigrationStatusMock).toBeCalledTimes(1); + expect(getKibanaUpgradeStatusMock).toBeCalledTimes(1); expect(resp.status).toEqual(200); expect(resp.payload).toEqual({ readyForUpgrade: false, @@ -244,4 +261,187 @@ describe('Status API', () => { ).rejects.toThrow('test error'); }); }); + + describe('GET /api/upgrade_assistant/status for non-major upgrade', () => { + const registerRoutes = (featureSetOverrides: Partial = {}) => { + const mockRouter = createMockRouter(); + const routeDependencies: any = { + config: { + featureSet: { + mlSnapshots: true, + migrateSystemIndices: true, + reindexCorrectiveActions: true, + ...featureSetOverrides, + }, + }, + router: mockRouter, + lib: { handleEsError }, + current: currentVersion, + defaultTarget: nextMajor, + }; + + registerUpgradeStatusRoute(routeDependencies); + + return { mockRouter, routeDependencies }; + }; + const testQuery = { query: { targetVersion: '8.18.0' } }; + afterEach(() => { + jest.resetAllMocks(); + }); + + it('returns readyForUpgrade === false if ES contains critical health issues, ignoring deprecations', async () => { + const { routeDependencies } = registerRoutes(); + getESUpgradeStatusMock.mockResolvedValue(esHealthResponse); + + getKibanaUpgradeStatusMock.mockResolvedValue({ + totalCriticalDeprecations: 1, + }); + + getESSystemIndicesMigrationStatusMock.mockResolvedValue(systemIndicesNoMigrationResponse); + + const resp = await routeDependencies.router.getHandler({ + method: 'get', + pathPattern: '/api/upgrade_assistant/status', + })(routeHandlerContextMock, createRequestMock(testQuery), kibanaResponseFactory); + + expect(getESSystemIndicesMigrationStatusMock).toBeCalledTimes(1); + expect(getKibanaUpgradeStatusMock).toBeCalledTimes(1); + expect(resp.status).toEqual(200); + expect(resp.payload).toEqual({ + readyForUpgrade: false, + details: + 'The following issues must be resolved before upgrading: 1 Elasticsearch deprecation issue.', + }); + }); + + it('returns readyForUpgrade === true if Kibana or ES contain critical deprecations and no system indices need migration', async () => { + const { routeDependencies } = registerRoutes(); + getESUpgradeStatusMock.mockResolvedValue(esDeprecationsResponse); + + getKibanaUpgradeStatusMock.mockResolvedValue({ + totalCriticalDeprecations: 1, + }); + + getESSystemIndicesMigrationStatusMock.mockResolvedValue(systemIndicesNoMigrationResponse); + + const resp = await routeDependencies.router.getHandler({ + method: 'get', + pathPattern: '/api/upgrade_assistant/status', + })(routeHandlerContextMock, createRequestMock(testQuery), kibanaResponseFactory); + + expect(getESSystemIndicesMigrationStatusMock).toBeCalledTimes(1); + expect(getKibanaUpgradeStatusMock).toBeCalledTimes(1); + expect(resp.status).toEqual(200); + expect(resp.payload).toEqual({ + readyForUpgrade: true, + details: 'All deprecation warnings have been resolved.', + }); + }); + + it('returns readyForUpgrade === true if Kibana or ES contain critical deprecations and system indices need migration', async () => { + const { routeDependencies } = registerRoutes(); + getESUpgradeStatusMock.mockResolvedValue(esDeprecationsResponse); + + getKibanaUpgradeStatusMock.mockResolvedValue({ + totalCriticalDeprecations: 1, + }); + + getESSystemIndicesMigrationStatusMock.mockResolvedValue(systemIndicesMigrationResponse); + + const resp = await routeDependencies.router.getHandler({ + method: 'get', + pathPattern: '/api/upgrade_assistant/status', + })(routeHandlerContextMock, createRequestMock(testQuery), kibanaResponseFactory); + + expect(getESSystemIndicesMigrationStatusMock).toBeCalledTimes(1); + expect(resp.status).toEqual(200); + expect(resp.payload).toEqual({ + readyForUpgrade: true, + details: 'All deprecation warnings have been resolved.', + }); + }); + + it('returns readyForUpgrade === true if no critical Kibana or ES deprecations but system indices need migration', async () => { + const { routeDependencies } = registerRoutes(); + getESUpgradeStatusMock.mockResolvedValue(esNoDeprecationsResponse); + + getKibanaUpgradeStatusMock.mockResolvedValue({ + totalCriticalDeprecations: 0, + }); + + getESSystemIndicesMigrationStatusMock.mockResolvedValue(systemIndicesMigrationResponse); + + const resp = await routeDependencies.router.getHandler({ + method: 'get', + pathPattern: '/api/upgrade_assistant/status', + })(routeHandlerContextMock, createRequestMock(testQuery), kibanaResponseFactory); + + expect(getESSystemIndicesMigrationStatusMock).toBeCalledTimes(1); + expect(resp.status).toEqual(200); + expect(resp.payload).toEqual({ + readyForUpgrade: true, + details: 'All deprecation warnings have been resolved.', + }); + }); + + it('returns readyForUpgrade === true if there are no critical deprecations and no system indices need migration', async () => { + const { routeDependencies } = registerRoutes(); + getESUpgradeStatusMock.mockResolvedValue(esNoDeprecationsResponse); + + getKibanaUpgradeStatusMock.mockResolvedValue({ + totalCriticalDeprecations: 0, + }); + + getESSystemIndicesMigrationStatusMock.mockResolvedValue(systemIndicesNoMigrationResponse); + + const resp = await routeDependencies.router.getHandler({ + method: 'get', + pathPattern: '/api/upgrade_assistant/status', + })(routeHandlerContextMock, createRequestMock(testQuery), kibanaResponseFactory); + + expect(resp.status).toEqual(200); + expect(resp.payload).toEqual({ + readyForUpgrade: true, + details: 'All deprecation warnings have been resolved.', + }); + }); + + it('skips ES system indices migration check when featureSet.migrateSystemIndices is set to false', async () => { + const { routeDependencies } = registerRoutes({ migrateSystemIndices: false }); + getESUpgradeStatusMock.mockResolvedValue(esNoDeprecationsResponse); + + getKibanaUpgradeStatusMock.mockResolvedValue({ + totalCriticalDeprecations: 0, + }); + + getESSystemIndicesMigrationStatusMock.mockResolvedValue(systemIndicesMigrationResponse); + const resp = await routeDependencies.router.getHandler({ + method: 'get', + pathPattern: '/api/upgrade_assistant/status', + })(routeHandlerContextMock, createRequestMock(testQuery), kibanaResponseFactory); + + expect(getESSystemIndicesMigrationStatusMock).toBeCalledTimes(0); + expect(resp.status).toEqual(200); + expect(resp.payload).toEqual({ + readyForUpgrade: true, + details: 'All deprecation warnings have been resolved.', + }); + }); + + it('returns an error if it throws', async () => { + const { routeDependencies } = registerRoutes(); + getESUpgradeStatusMock.mockRejectedValue(new Error('test error')); + + getKibanaUpgradeStatusMock.mockResolvedValue({ + totalCriticalDeprecations: 0, + }); + + await expect( + routeDependencies.router.getHandler({ + method: 'get', + pathPattern: '/api/upgrade_assistant/status', + })(routeHandlerContextMock, createRequestMock(testQuery), kibanaResponseFactory) + ).rejects.toThrow('test error'); + }); + }); }); diff --git a/x-pack/platform/plugins/private/upgrade_assistant/server/routes/status.ts b/x-pack/platform/plugins/private/upgrade_assistant/server/routes/status.ts index 19f3a5c07a944..54d00e0e8f132 100644 --- a/x-pack/platform/plugins/private/upgrade_assistant/server/routes/status.ts +++ b/x-pack/platform/plugins/private/upgrade_assistant/server/routes/status.ts @@ -4,14 +4,15 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ - import { i18n } from '@kbn/i18n'; +import { schema } from '@kbn/config-schema'; import { API_BASE_PATH } from '../../common/constants'; import { getESUpgradeStatus } from '../lib/es_deprecations_status'; import { versionCheckHandlerWrapper } from '../lib/es_version_precheck'; import { getKibanaUpgradeStatus } from '../lib/kibana_status'; import { getESSystemIndicesMigrationStatus } from '../lib/es_system_indices_migration'; import { RouteDependencies } from '../types'; +import { getUpgradeType } from '../lib/upgrade_type'; /** * Note that this route is primarily intended for consumption by Cloud. @@ -20,6 +21,8 @@ export function registerUpgradeStatusRoute({ config: { featureSet }, router, lib: { handleEsError }, + current, + defaultTarget, }: RouteDependencies) { router.get( { @@ -34,25 +37,33 @@ export function registerUpgradeStatusRoute({ access: 'public', summary: `Get upgrade readiness status`, }, - validate: false, + validate: { + query: schema.object({ + targetVersion: schema.maybe(schema.string()), + }), + }, }, versionCheckHandlerWrapper(async ({ core }, request, response) => { + const targetVersion = request.query?.targetVersion || `${defaultTarget}`; + const upgradeType = getUpgradeType({ current, target: targetVersion }); + if (!upgradeType) return response.forbidden(); + try { const { elasticsearch: { client: esClient }, deprecations: { client: deprecationsClient }, } = await core; // Fetch ES upgrade status - const { totalCriticalDeprecations: esTotalCriticalDeps } = await getESUpgradeStatus( - esClient, - featureSet - ); + const { + totalCriticalDeprecations, // critical deprecations + totalCriticalHealthIssues, // critical health issues + } = await getESUpgradeStatus(esClient, featureSet); const getSystemIndicesMigrationStatus = async () => { /** * Skip system indices migration status check if `featureSet.migrateSystemIndices` * is set to `false`. This flag is enabled from configs for major version stack ugprades. - * returns `migration_status: 'NO_MIGRATION_NEEDED'` to indicate no migation needed. + * returns `migration_status: 'NO_MIGRATION_NEEDED'` to indicate no migration needed. */ if (!featureSet.migrateSystemIndices) { return { @@ -76,10 +87,19 @@ export function registerUpgradeStatusRoute({ const { totalCriticalDeprecations: kibanaTotalCriticalDeps } = await getKibanaUpgradeStatus( deprecationsClient ); - const readyForUpgrade = - esTotalCriticalDeps === 0 && - kibanaTotalCriticalDeps === 0 && - systemIndicesMigrationStatus === 'NO_MIGRATION_NEEDED'; + // non-major upgrades blocked only for health issues (status !== green) + let upgradeTypeBasedReadyForUpgrade: boolean; + if (upgradeType === 'major') { + upgradeTypeBasedReadyForUpgrade = + totalCriticalHealthIssues === 0 && + totalCriticalDeprecations === 0 && + kibanaTotalCriticalDeps === 0 && + systemIndicesMigrationStatus === 'NO_MIGRATION_NEEDED'; + } else { + upgradeTypeBasedReadyForUpgrade = totalCriticalHealthIssues === 0; + } + + const readyForUpgrade = upgradeType && upgradeTypeBasedReadyForUpgrade; const getStatusMessage = () => { if (readyForUpgrade) { @@ -89,8 +109,12 @@ export function registerUpgradeStatusRoute({ } const upgradeIssues: string[] = []; + let esTotalCriticalDeps = totalCriticalHealthIssues; + if (upgradeType === 'major') { + esTotalCriticalDeps += totalCriticalDeprecations; + } - if (notMigratedSystemIndices) { + if (upgradeType === 'major' && notMigratedSystemIndices) { upgradeIssues.push( i18n.translate('xpack.upgradeAssistant.status.systemIndicesMessage', { defaultMessage: @@ -99,7 +123,7 @@ export function registerUpgradeStatusRoute({ }) ); } - + // can be improved by showing health indicator issues separately if (esTotalCriticalDeps) { upgradeIssues.push( i18n.translate('xpack.upgradeAssistant.status.esTotalCriticalDepsMessage', { @@ -110,7 +134,7 @@ export function registerUpgradeStatusRoute({ ); } - if (kibanaTotalCriticalDeps) { + if (upgradeType === 'major' && kibanaTotalCriticalDeps) { upgradeIssues.push( i18n.translate('xpack.upgradeAssistant.status.kibanaTotalCriticalDepsMessage', { defaultMessage: @@ -119,7 +143,6 @@ export function registerUpgradeStatusRoute({ }) ); } - return i18n.translate('xpack.upgradeAssistant.status.deprecationsUnresolvedMessage', { defaultMessage: 'The following issues must be resolved before upgrading: {upgradeIssues}.', diff --git a/x-pack/platform/plugins/private/upgrade_assistant/server/types.ts b/x-pack/platform/plugins/private/upgrade_assistant/server/types.ts index 487577b648a52..a5b1049bd6cb4 100644 --- a/x-pack/platform/plugins/private/upgrade_assistant/server/types.ts +++ b/x-pack/platform/plugins/private/upgrade_assistant/server/types.ts @@ -8,6 +8,7 @@ import { IRouter, Logger, SavedObjectsServiceStart } from '@kbn/core/server'; import { LicensingPluginSetup } from '@kbn/licensing-plugin/server'; import { SecurityPluginStart } from '@kbn/security-plugin/server'; +import SemVer from 'semver/classes/semver'; import { CredentialStore } from './lib/reindexing/credential_store'; import { handleEsError } from './shared_imports'; import type { FeatureSet } from '../common/types'; @@ -26,4 +27,6 @@ export interface RouteDependencies { featureSet: FeatureSet; isSecurityEnabled: () => boolean; }; + current: SemVer; + defaultTarget: number; } diff --git a/x-pack/platform/plugins/shared/alerting/common/routes/rule/response/schemas/v1.ts b/x-pack/platform/plugins/shared/alerting/common/routes/rule/response/schemas/v1.ts index 6226a17d51025..754b9a0637458 100644 --- a/x-pack/platform/plugins/shared/alerting/common/routes/rule/response/schemas/v1.ts +++ b/x-pack/platform/plugins/shared/alerting/common/routes/rule/response/schemas/v1.ts @@ -407,6 +407,18 @@ export const monitoringSchema = schema.object( }) ) ), + gap_range: schema.maybe( + schema.nullable( + schema.object({ + lte: schema.string({ + meta: { description: 'Start of the gap range.' }, + }), + gte: schema.string({ + meta: { description: 'End of the gap range.' }, + }), + }) + ) + ), }), }), }, diff --git a/x-pack/platform/plugins/shared/alerting/common/rule.ts b/x-pack/platform/plugins/shared/alerting/common/rule.ts index 4981fc6dea263..48d972d6a0035 100644 --- a/x-pack/platform/plugins/shared/alerting/common/rule.ts +++ b/x-pack/platform/plugins/shared/alerting/common/rule.ts @@ -106,4 +106,8 @@ export interface RuleMonitoringLastRunMetrics extends SavedObjectAttributes { total_alerts_detected?: number | null; total_alerts_created?: number | null; gap_duration_s?: number | null; + gap_range?: { + lte: string; + gte: string; + } | null; } diff --git a/x-pack/platform/plugins/shared/alerting/server/application/rule/schemas/rule_schemas.ts b/x-pack/platform/plugins/shared/alerting/server/application/rule/schemas/rule_schemas.ts index 978e11f0183cf..134f6f2ff896a 100644 --- a/x-pack/platform/plugins/shared/alerting/server/application/rule/schemas/rule_schemas.ts +++ b/x-pack/platform/plugins/shared/alerting/server/application/rule/schemas/rule_schemas.ts @@ -125,6 +125,14 @@ export const monitoringSchema = schema.object({ total_alerts_detected: schema.maybe(schema.nullable(schema.number())), total_alerts_created: schema.maybe(schema.nullable(schema.number())), gap_duration_s: schema.maybe(schema.nullable(schema.number())), + gap_range: schema.maybe( + schema.nullable( + schema.object({ + gte: schema.string(), + lte: schema.string(), + }) + ) + ), }), }), }), diff --git a/x-pack/platform/plugins/shared/alerting/server/lib/alerting_event_logger/alerting_event_logger.mock.ts b/x-pack/platform/plugins/shared/alerting/server/lib/alerting_event_logger/alerting_event_logger.mock.ts index 6aa8eb9744441..942a1a625c06f 100644 --- a/x-pack/platform/plugins/shared/alerting/server/lib/alerting_event_logger/alerting_event_logger.mock.ts +++ b/x-pack/platform/plugins/shared/alerting/server/lib/alerting_event_logger/alerting_event_logger.mock.ts @@ -19,6 +19,7 @@ const createAlertingEventLoggerMock = () => { logAlert: jest.fn(), logAction: jest.fn(), done: jest.fn(), + reportGap: jest.fn(), }; }); }; diff --git a/x-pack/platform/plugins/shared/alerting/server/lib/alerting_event_logger/alerting_event_logger.test.ts b/x-pack/platform/plugins/shared/alerting/server/lib/alerting_event_logger/alerting_event_logger.test.ts index a206f4e058eed..da9f54567d886 100644 --- a/x-pack/platform/plugins/shared/alerting/server/lib/alerting_event_logger/alerting_event_logger.test.ts +++ b/x-pack/platform/plugins/shared/alerting/server/lib/alerting_event_logger/alerting_event_logger.test.ts @@ -22,6 +22,7 @@ import { initializeExecuteBackfillRecord, SavedObjects, updateEventWithRuleData, + createGapRecord, } from './alerting_event_logger'; import { UntypedNormalizedRuleType } from '../../rule_type_registry'; import { @@ -1457,6 +1458,32 @@ describe('AlertingEventLogger', () => { expect(alertingEventLogger.getEvent()!.message).toBe('first failure message'); }); }); + + describe('reportGap()', () => { + test('should throw error if alertingEventLogger has not been initialized', () => { + expect(() => + alertingEventLogger.reportGap({ + gap: { gte: '', lte: '' }, + }) + ).toThrowErrorMatchingInlineSnapshot(`"AlertingEventLogger not initialized"`); + }); + + test('should report gap event', () => { + alertingEventLogger.initialize({ context: ruleContext, runDate, ruleData }); + const range = { + gte: '2022-05-05T15:59:54.480Z', + lte: '2022-05-05T16:59:54.480Z', + }; + alertingEventLogger.reportGap({ gap: range }); + + const event = createGapRecord(ruleContext, ruleData, [alertSO], { + status: 'unfilled', + range, + }); + + expect(eventLogger.logEvent).toHaveBeenCalledWith(event); + }); + }); }); describe('helper functions', () => { @@ -2065,6 +2092,59 @@ describe('helper functions', () => { }); }); }); + + describe('createGapRecord', () => { + test('should populate expected fields in event log record', () => { + const record = createGapRecord(ruleContextWithScheduleDelay, ruleDataWithName, [alertSO], { + status: 'unfilled', + range: { + gte: '2022-05-05T15:59:54.480Z', + lte: '2022-05-05T16:59:54.480Z', + }, + }); + + // these fields should be explicitly set + expect(record.event?.action).toEqual('gap'); + expect(record.event?.kind).toEqual('alert'); + expect(record.event?.category).toEqual([ruleDataWithName.type?.producer]); + + expect(record.kibana?.alert?.rule?.gap?.status).toEqual('unfilled'); + expect(record.kibana?.alert?.rule?.gap?.range?.gte).toEqual('2022-05-05T15:59:54.480Z'); + expect(record.kibana?.alert?.rule?.gap?.range?.lte).toEqual('2022-05-05T16:59:54.480Z'); + + expect(record.kibana?.alert?.rule?.rule_type_id).toEqual(ruleDataWithName.type?.id); + expect(record.kibana?.alert?.rule?.consumer).toEqual(ruleDataWithName.consumer); + expect(record.kibana?.alert?.rule?.execution?.uuid).toEqual( + ruleContextWithScheduleDelay.executionId + ); + + expect(record.kibana?.saved_objects).toEqual([ + { + id: ruleContextWithScheduleDelay.savedObjectId, + type: ruleContextWithScheduleDelay.savedObjectType, + type_id: ruleDataWithName.type?.id, + rel: SAVED_OBJECT_REL_PRIMARY, + }, + ]); + expect(record.kibana?.space_ids).toEqual([ruleContextWithScheduleDelay.spaceId]); + expect(record?.rule?.id).toEqual(ruleDataWithName.id); + expect(record?.rule?.license).toEqual(ruleDataWithName.type?.minimumLicenseRequired); + expect(record?.rule?.category).toEqual(ruleDataWithName.type?.id); + expect(record?.rule?.ruleset).toEqual(ruleDataWithName.type?.producer); + expect(record?.rule?.name).toEqual(ruleDataWithName.name); + + // these fields should not be set by this function + expect(record.kibana?.alert?.rule?.gap?.filled_intervals).toEqual(undefined); + expect(record['@timestamp']).toBeUndefined(); + expect(record.event?.provider).toBeUndefined(); + expect(record.event?.outcome).toBeUndefined(); + expect(record.kibana?.alert?.rule?.execution?.metrics).toBeUndefined(); + expect(record.kibana?.server_uuid).toBeUndefined(); + expect(record.kibana?.task).toBeUndefined(); + expect(record.kibana?.version).toBeUndefined(); + expect(record?.ecs).toBeUndefined(); + }); + }); }); function mockEventLoggerStartTiming() { diff --git a/x-pack/platform/plugins/shared/alerting/server/lib/alerting_event_logger/alerting_event_logger.ts b/x-pack/platform/plugins/shared/alerting/server/lib/alerting_event_logger/alerting_event_logger.ts index d344a8f2a240b..90749ebb0bb88 100644 --- a/x-pack/platform/plugins/shared/alerting/server/lib/alerting_event_logger/alerting_event_logger.ts +++ b/x-pack/platform/plugins/shared/alerting/server/lib/alerting_event_logger/alerting_event_logger.ts @@ -395,6 +395,26 @@ export class AlertingEventLogger { this.eventLogger.logEvent(this.event); } + + public reportGap({ + gap, + }: { + gap: { + lte: string; + gte: string; + }; + }): void { + if (!this.isInitialized || !this.context || !this.ruleData) { + throw new Error('AlertingEventLogger not initialized'); + } + + this.eventLogger.logEvent( + createGapRecord(this.context, this.ruleData, this.relatedSavedObjects, { + status: 'unfilled', + range: gap, + }) + ); + } } export function createAlertRecord( @@ -488,6 +508,33 @@ export function createExecuteTimeoutRecord( }); } +export function createGapRecord( + context: ContextOpts, + ruleData: RuleContext, + savedObjects: SavedObjects[], + gap: { + status: string; + range: { + gte: string; + lte: string; + }; + } +) { + return createAlertEventLogRecordObject({ + ruleId: ruleData?.id, + ruleType: ruleData?.type, + consumer: ruleData?.consumer, + namespace: context.namespace, + spaceId: context.spaceId, + executionId: context.executionId, + action: EVENT_LOG_ACTIONS.gap, + savedObjects, + ruleName: ruleData?.name, + ruleRevision: ruleData?.revision, + gap, + }); +} + export function initializeExecuteRecord( context: Context, ruleData: RuleContext, diff --git a/x-pack/platform/plugins/shared/alerting/server/lib/create_alert_event_log_record_object.ts b/x-pack/platform/plugins/shared/alerting/server/lib/create_alert_event_log_record_object.ts index 8231faa43c74d..47208e06b1234 100644 --- a/x-pack/platform/plugins/shared/alerting/server/lib/create_alert_event_log_record_object.ts +++ b/x-pack/platform/plugins/shared/alerting/server/lib/create_alert_event_log_record_object.ts @@ -44,6 +44,13 @@ interface CreateAlertEventLogRecordParams { }; maintenanceWindowIds?: string[]; ruleRevision?: number; + gap?: { + status: string; + range: { + gte: string; + lte: string; + }; + }; } export function createAlertEventLogRecordObject(params: CreateAlertEventLogRecordParams): Event { @@ -64,6 +71,7 @@ export function createAlertEventLogRecordObject(params: CreateAlertEventLogRecor alertSummary, maintenanceWindowIds, ruleRevision, + gap, } = params; const alerting = params.instanceId || group || alertSummary @@ -109,6 +117,7 @@ export function createAlertEventLogRecordObject(params: CreateAlertEventLogRecor }, } : {}), + ...(gap ? { gap } : {}), }, }, ...(alerting ? alerting : {}), diff --git a/x-pack/platform/plugins/shared/alerting/server/lib/monitoring.ts b/x-pack/platform/plugins/shared/alerting/server/lib/monitoring.ts index bff533cfc591f..b25592b88bdb0 100644 --- a/x-pack/platform/plugins/shared/alerting/server/lib/monitoring.ts +++ b/x-pack/platform/plugins/shared/alerting/server/lib/monitoring.ts @@ -21,6 +21,8 @@ const INITIAL_LAST_RUN_METRICS: RuleMonitoringLastRunMetrics = { total_alerts_detected: null, total_alerts_created: null, gap_duration_s: null, + // TODO: should initialised field, after inermidiate release + // gap_range: null, }; export const getDefaultMonitoring = (timestamp: string): RawRuleMonitoring => { diff --git a/x-pack/platform/plugins/shared/alerting/server/monitoring/rule_monitoring_service.mock.ts b/x-pack/platform/plugins/shared/alerting/server/monitoring/rule_monitoring_service.mock.ts index 132aa395a9630..9fc3d44ef1e9b 100644 --- a/x-pack/platform/plugins/shared/alerting/server/monitoring/rule_monitoring_service.mock.ts +++ b/x-pack/platform/plugins/shared/alerting/server/monitoring/rule_monitoring_service.mock.ts @@ -25,6 +25,7 @@ function createPublicRuleMonitoringServiceMock() { setLastRunMetricsTotalAlertsDetected: jest.fn(), setLastRunMetricsTotalIndexingDurationMs: jest.fn(), setLastRunMetricsTotalSearchDurationMs: jest.fn(), + setLastRunMetricsGapRange: jest.fn(), }; }); } diff --git a/x-pack/platform/plugins/shared/alerting/server/monitoring/rule_monitoring_service.test.ts b/x-pack/platform/plugins/shared/alerting/server/monitoring/rule_monitoring_service.test.ts index 73f614e027aed..decefd779e461 100644 --- a/x-pack/platform/plugins/shared/alerting/server/monitoring/rule_monitoring_service.test.ts +++ b/x-pack/platform/plugins/shared/alerting/server/monitoring/rule_monitoring_service.test.ts @@ -171,5 +171,22 @@ describe('RuleMonitoringService', () => { } = ruleMonitoringService.getMonitoring(); expect(metrics.gap_duration_s).toEqual(567); }); + + it('should set gapRange', () => { + const ruleMonitoringService = new RuleMonitoringService(); + const { setLastRunMetricsGapRange } = ruleMonitoringService.getLastRunMetricsSetters(); + setLastRunMetricsGapRange({ + gte: '2020-01-01T00:00:00.000Z', + lte: '2020-01-01T01:00:00.000Z', + }); + + const { + run: { + last_run: { metrics }, + }, + } = ruleMonitoringService.getMonitoring(); + expect(metrics.gap_range?.gte).toEqual('2020-01-01T00:00:00.000Z'); + expect(metrics.gap_range?.lte).toEqual('2020-01-01T01:00:00.000Z'); + }); }); }); diff --git a/x-pack/platform/plugins/shared/alerting/server/monitoring/rule_monitoring_service.ts b/x-pack/platform/plugins/shared/alerting/server/monitoring/rule_monitoring_service.ts index 0043f47c51633..07d4098018610 100644 --- a/x-pack/platform/plugins/shared/alerting/server/monitoring/rule_monitoring_service.ts +++ b/x-pack/platform/plugins/shared/alerting/server/monitoring/rule_monitoring_service.ts @@ -63,6 +63,7 @@ export class RuleMonitoringService { setLastRunMetricsTotalAlertsDetected: this.setLastRunMetricsTotalAlertsDetected.bind(this), setLastRunMetricsTotalAlertsCreated: this.setLastRunMetricsTotalAlertsCreated.bind(this), setLastRunMetricsGapDurationS: this.setLastRunMetricsGapDurationS.bind(this), + setLastRunMetricsGapRange: this.setLastRunMetricsGapRange.bind(this), }; } @@ -86,6 +87,10 @@ export class RuleMonitoringService { this.monitoring.run.last_run.metrics.gap_duration_s = gapDurationS; } + private setLastRunMetricsGapRange(gap: { lte: string; gte: string } | null) { + this.monitoring.run.last_run.metrics.gap_range = gap; + } + private buildExecutionSuccessRatio() { const { history } = this.monitoring.run; return history.filter(({ success }) => success).length / history.length; diff --git a/x-pack/platform/plugins/shared/alerting/server/plugin.ts b/x-pack/platform/plugins/shared/alerting/server/plugin.ts index 9d1a15305f7e3..5c0c6dda41663 100644 --- a/x-pack/platform/plugins/shared/alerting/server/plugin.ts +++ b/x-pack/platform/plugins/shared/alerting/server/plugin.ts @@ -128,6 +128,7 @@ export const EVENT_LOG_ACTIONS = { activeInstance: 'active-instance', executeTimeout: 'execute-timeout', untrackedInstance: 'untracked-instance', + gap: 'gap', }; export const LEGACY_EVENT_LOG_ACTIONS = { resolvedInstance: 'resolved-instance', diff --git a/x-pack/platform/plugins/shared/alerting/server/saved_objects/model_versions/rule_model_versions.ts b/x-pack/platform/plugins/shared/alerting/server/saved_objects/model_versions/rule_model_versions.ts index 33b1bfd315769..ab976cb49ad9e 100644 --- a/x-pack/platform/plugins/shared/alerting/server/saved_objects/model_versions/rule_model_versions.ts +++ b/x-pack/platform/plugins/shared/alerting/server/saved_objects/model_versions/rule_model_versions.ts @@ -6,7 +6,12 @@ */ import { SavedObjectsModelVersionMap } from '@kbn/core-saved-objects-server'; -import { rawRuleSchemaV1, rawRuleSchemaV2, rawRuleSchemaV3 } from '../schemas/raw_rule'; +import { + rawRuleSchemaV1, + rawRuleSchemaV2, + rawRuleSchemaV3, + rawRuleSchemaV4, +} from '../schemas/raw_rule'; export const ruleModelVersions: SavedObjectsModelVersionMap = { '1': { @@ -30,4 +35,11 @@ export const ruleModelVersions: SavedObjectsModelVersionMap = { create: rawRuleSchemaV3, }, }, + '4': { + changes: [], + schemas: { + forwardCompatibility: rawRuleSchemaV4.extends({}, { unknowns: 'ignore' }), + create: rawRuleSchemaV4, + }, + }, }; diff --git a/x-pack/platform/plugins/shared/alerting/server/saved_objects/schemas/raw_rule/index.ts b/x-pack/platform/plugins/shared/alerting/server/saved_objects/schemas/raw_rule/index.ts index c38a80601dc48..684e813f7f868 100644 --- a/x-pack/platform/plugins/shared/alerting/server/saved_objects/schemas/raw_rule/index.ts +++ b/x-pack/platform/plugins/shared/alerting/server/saved_objects/schemas/raw_rule/index.ts @@ -10,3 +10,4 @@ export * from './latest'; export { rawRuleSchema as rawRuleSchemaV1 } from './v1'; export { rawRuleSchema as rawRuleSchemaV2 } from './v2'; export { rawRuleSchema as rawRuleSchemaV3 } from './v3'; +export { rawRuleSchema as rawRuleSchemaV4 } from './v4'; diff --git a/x-pack/platform/plugins/shared/alerting/server/saved_objects/schemas/raw_rule/latest.ts b/x-pack/platform/plugins/shared/alerting/server/saved_objects/schemas/raw_rule/latest.ts index dded0a98f6d53..843ac3d0bd02a 100644 --- a/x-pack/platform/plugins/shared/alerting/server/saved_objects/schemas/raw_rule/latest.ts +++ b/x-pack/platform/plugins/shared/alerting/server/saved_objects/schemas/raw_rule/latest.ts @@ -11,10 +11,10 @@ import { rawRuleActionSchema, rawRuleAlertsFilterSchema, rawRuleLastRunSchema, - rawRuleMonitoringSchema, - rawRuleSchema, } from './v3'; +import { rawRuleMonitoringSchema, rawRuleSchema } from './v4'; + type Mutable = { -readonly [P in keyof T]: T[P] extends object ? Mutable : T[P] }; export type RawRuleAction = Mutable>; diff --git a/x-pack/platform/plugins/shared/alerting/server/saved_objects/schemas/raw_rule/v4.ts b/x-pack/platform/plugins/shared/alerting/server/saved_objects/schemas/raw_rule/v4.ts new file mode 100644 index 0000000000000..eac95327594de --- /dev/null +++ b/x-pack/platform/plugins/shared/alerting/server/saved_objects/schemas/raw_rule/v4.ts @@ -0,0 +1,57 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { schema } from '@kbn/config-schema'; +import { rawRuleSchema as rawRuleSchemaV3 } from './v3'; + +const outcome = schema.oneOf([ + schema.literal('succeeded'), + schema.literal('warning'), + schema.literal('failed'), +]); + +export const rawRuleMonitoringSchema = schema.object({ + run: schema.object({ + history: schema.arrayOf( + schema.object({ + success: schema.boolean(), + timestamp: schema.number(), + duration: schema.maybe(schema.number()), + outcome: schema.maybe(outcome), + }) + ), + calculated_metrics: schema.object({ + p50: schema.maybe(schema.number()), + p95: schema.maybe(schema.number()), + p99: schema.maybe(schema.number()), + success_ratio: schema.number(), + }), + last_run: schema.object({ + timestamp: schema.string(), + metrics: schema.object({ + duration: schema.maybe(schema.number()), + total_search_duration_ms: schema.maybe(schema.nullable(schema.number())), + total_indexing_duration_ms: schema.maybe(schema.nullable(schema.number())), + total_alerts_detected: schema.maybe(schema.nullable(schema.number())), + total_alerts_created: schema.maybe(schema.nullable(schema.number())), + gap_duration_s: schema.maybe(schema.nullable(schema.number())), + gap_range: schema.maybe( + schema.nullable( + schema.object({ + gte: schema.string(), + lte: schema.string(), + }) + ) + ), + }), + }), + }), +}); + +export const rawRuleSchema = rawRuleSchemaV3.extends({ + monitoring: schema.maybe(rawRuleMonitoringSchema), +}); diff --git a/x-pack/platform/plugins/shared/alerting/server/task_runner/task_runner.test.ts b/x-pack/platform/plugins/shared/alerting/server/task_runner/task_runner.test.ts index f65a1b57b42d3..5c4ddb522dc98 100644 --- a/x-pack/platform/plugins/shared/alerting/server/task_runner/task_runner.test.ts +++ b/x-pack/platform/plugins/shared/alerting/server/task_runner/task_runner.test.ts @@ -90,6 +90,7 @@ import { alertsClientMock } from '../alerts_client/alerts_client.mock'; import { RULE_SAVED_OBJECT_TYPE } from '../saved_objects'; import { getErrorSource } from '@kbn/task-manager-plugin/server/task_running'; import { RuleResultService } from '../monitoring/rule_result_service'; +import { RuleMonitoringService } from '../monitoring/rule_monitoring_service'; import { ruleResultServiceMock } from '../monitoring/rule_result_service.mock'; import { backfillClientMock } from '../backfill_client/backfill_client.mock'; import { UntypedNormalizedRuleType } from '../rule_type_registry'; @@ -3222,6 +3223,43 @@ describe('Task Runner', () => { expect(getErrorSource(runnerResult.taskRunError as Error)).toBe(TaskErrorSource.USER); }); + test('when there is a gap, report it to alert event log', async () => { + encryptedSavedObjectsClient.getDecryptedAsInternalUser.mockResolvedValue(mockedRawRuleSO); + jest.spyOn(RuleMonitoringService.prototype, 'getMonitoring').mockImplementation(() => { + return { + run: { + history: [], + calculated_metrics: { + success_ratio: 0, + }, + last_run: { + timestamp: '2021-09-01T00:00:00.000Z', + metrics: { + gap_range: { + gte: '2021-09-01T00:00:00.000Z', + lte: '2021-09-01T00:00:00.001Z', + }, + }, + }, + }, + }; + }); + + const taskRunner = new TaskRunner({ + ruleType, + taskInstance: mockedTaskInstance, + context: taskRunnerFactoryInitializerParams, + inMemoryMetrics, + internalSavedObjectsRepository, + }); + + await taskRunner.run(); + + expect(alertingEventLogger.reportGap).toHaveBeenCalledWith({ + gap: { gte: '2021-09-01T00:00:00.000Z', lte: '2021-09-01T00:00:00.001Z' }, + }); + }); + test('reschedules when persistAlerts returns a cluster_block_exception', async () => { const err = new ErrorWithType({ message: 'Index is blocked', diff --git a/x-pack/platform/plugins/shared/alerting/server/task_runner/task_runner.ts b/x-pack/platform/plugins/shared/alerting/server/task_runner/task_runner.ts index 425754b24b90e..01a8523f7b746 100644 --- a/x-pack/platform/plugins/shared/alerting/server/task_runner/task_runner.ts +++ b/x-pack/platform/plugins/shared/alerting/server/task_runner/task_runner.ts @@ -539,7 +539,9 @@ export class TaskRunner< // Set rule monitoring data this.ruleMonitoring.setMonitoring(runRuleParams.rule.monitoring); - + if (this.ruleMonitoring.getMonitoring()?.run?.last_run?.metrics?.gap_range) { + this.ruleMonitoring.getLastRunMetricsSetters().setLastRunMetricsGapRange(null); + } (async () => { try { await clearExpiredSnoozes({ @@ -608,6 +610,13 @@ export class TaskRunner< runDate: this.runDate, }); + const gap = this.ruleMonitoring.getMonitoring()?.run?.last_run?.metrics?.gap_range; + if (gap) { + this.alertingEventLogger.reportGap({ + gap, + }); + } + if (!this.cancelled) { this.inMemoryMetrics.increment(IN_MEMORY_METRICS.RULE_EXECUTIONS); if (outcome === 'failure') { diff --git a/x-pack/platform/plugins/shared/alerting/server/types.ts b/x-pack/platform/plugins/shared/alerting/server/types.ts index 4c3d9ee57f51d..f0db7c3f4ed43 100644 --- a/x-pack/platform/plugins/shared/alerting/server/types.ts +++ b/x-pack/platform/plugins/shared/alerting/server/types.ts @@ -400,6 +400,7 @@ export interface PublicMetricsSetters { setLastRunMetricsTotalAlertsDetected: (totalAlertDetected: number) => void; setLastRunMetricsTotalAlertsCreated: (totalAlertCreated: number) => void; setLastRunMetricsGapDurationS: (gapDurationS: number) => void; + setLastRunMetricsGapRange: (gapRange: { lte: string; gte: string } | null) => void; } export interface PublicLastRunSetters { diff --git a/x-pack/platform/plugins/shared/cases/common/api/helpers.ts b/x-pack/platform/plugins/shared/cases/common/api/helpers.ts index 45dad60a9bad1..df4059c11b356 100644 --- a/x-pack/platform/plugins/shared/cases/common/api/helpers.ts +++ b/x-pack/platform/plugins/shared/cases/common/api/helpers.ts @@ -9,7 +9,6 @@ import { CASE_DETAILS_URL, INTERNAL_CASE_METRICS_DETAILS_URL, CASE_COMMENTS_URL, - CASE_USER_ACTIONS_URL, CASE_PUSH_URL, CASE_CONFIGURE_DETAILS_URL, CASE_ALERTS_URL, @@ -48,10 +47,6 @@ export const getCaseCommentDeleteUrl = (caseId: string, commentId: string): stri return CASE_COMMENT_DELETE_URL.replace('{case_id}', caseId).replace('{comment_id}', commentId); }; -export const getCaseUserActionUrl = (id: string): string => { - return CASE_USER_ACTIONS_URL.replace('{case_id}', id); -}; - export const getCaseUserActionStatsUrl = (id: string): string => { return INTERNAL_GET_CASE_USER_ACTIONS_STATS_URL.replace('{case_id}', id); }; diff --git a/x-pack/platform/plugins/shared/cases/common/constants/index.ts b/x-pack/platform/plugins/shared/cases/common/constants/index.ts index 76787c791b808..ed22bd56f9cb1 100644 --- a/x-pack/platform/plugins/shared/cases/common/constants/index.ts +++ b/x-pack/platform/plugins/shared/cases/common/constants/index.ts @@ -54,7 +54,6 @@ export const CASE_COMMENT_DETAILS_URL = `${CASE_DETAILS_URL}/comments/{comment_i export const CASE_COMMENT_DELETE_URL = `${CASE_DETAILS_URL}/comments/{comment_id}` as const; export const CASE_PUSH_URL = `${CASE_DETAILS_URL}/connector/{connector_id}/_push` as const; export const CASE_REPORTERS_URL = `${CASES_URL}/reporters` as const; -export const CASE_STATUS_URL = `${CASES_URL}/status` as const; export const CASE_TAGS_URL = `${CASES_URL}/tags` as const; export const CASE_USER_ACTIONS_URL = `${CASE_DETAILS_URL}/user_actions` as const; export const CASE_FIND_USER_ACTIONS_URL = `${CASE_USER_ACTIONS_URL}/_find` as const; diff --git a/x-pack/platform/plugins/shared/cases/docs/openapi/bundled.json b/x-pack/platform/plugins/shared/cases/docs/openapi/bundled.json index fabe0e105d97e..aec5834c71160 100644 --- a/x-pack/platform/plugins/shared/cases/docs/openapi/bundled.json +++ b/x-pack/platform/plugins/shared/cases/docs/openapi/bundled.json @@ -1117,55 +1117,6 @@ } } }, - "/api/cases/status": { - "get": { - "summary": "Get case status summary", - "operationId": "getCaseStatusDefaultSpace", - "description": "Returns the number of cases that are open, closed, and in progress. Deprecated in 8.1.0. This API is deprecated and will be removed in a future release; use the find cases API instead. You must have `read` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana feature privileges, depending on the owner of the cases you're seeking.\n", - "deprecated": true, - "tags": [ - "cases" - ], - "parameters": [ - { - "$ref": "#/components/parameters/owner_filter" - } - ], - "responses": { - "200": { - "description": "Indicates a successful call.", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "count_closed_cases": { - "type": "integer" - }, - "count_in_progress_cases": { - "type": "integer" - }, - "count_open_cases": { - "type": "integer" - } - } - } - } - } - }, - "401": { - "description": "Authorization information is missing or invalid.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/4xx_response" - } - } - } - } - } - } - }, "/api/cases/tags": { "get": { "summary": "Get case tags", @@ -1645,47 +1596,6 @@ } } }, - "/api/cases/{caseId}/user_actions": { - "get": { - "summary": "Get case activity", - "description": "Returns all user activity for a case. Deprecated in 8.1.0. This API is deprecated and will be removed in a future release; use the find user actions API instead. You must have `read` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana feature privileges, depending on the owner of the case you're seeking.\n", - "deprecated": true, - "operationId": "getCaseActivityDefaultSpace", - "tags": [ - "cases" - ], - "parameters": [ - { - "$ref": "#/components/parameters/case_id" - } - ], - "responses": { - "200": { - "description": "Indicates a successful call.", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/user_actions_response_properties" - } - } - } - } - }, - "401": { - "description": "Authorization information is missing or invalid.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/4xx_response" - } - } - } - } - } - } - }, "/api/cases/{caseId}/user_actions/_find": { "get": { "summary": "Find case activity", @@ -4554,140 +4464,6 @@ } } }, - "action_types": { - "type": "string", - "description": "The type of action.", - "enum": [ - "assignees", - "create_case", - "comment", - "connector", - "delete_case", - "description", - "pushed", - "tags", - "title", - "status", - "settings", - "severity" - ], - "example": "create_case" - }, - "user_actions_response_properties": { - "type": "object", - "required": [ - "action", - "action_id", - "case_id", - "comment_id", - "created_at", - "created_by", - "owner", - "payload", - "type" - ], - "properties": { - "action": { - "$ref": "#/components/schemas/actions" - }, - "action_id": { - "type": "string", - "example": "22fd3e30-03b1-11ed-920c-974bfa104448" - }, - "case_id": { - "type": "string", - "example": "22df07d0-03b1-11ed-920c-974bfa104448" - }, - "comment_id": { - "type": "string", - "nullable": true, - "example": "578608d0-03b1-11ed-920c-974bfa104448" - }, - "created_at": { - "type": "string", - "format": "date-time", - "example": "2022-05-13T09:16:17.416Z" - }, - "created_by": { - "type": "object", - "properties": { - "email": { - "type": "string", - "example": null, - "nullable": true - }, - "full_name": { - "type": "string", - "example": null, - "nullable": true - }, - "username": { - "type": "string", - "example": "elastic", - "nullable": true - }, - "profile_uid": { - "type": "string", - "example": "u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0" - } - }, - "required": [ - "email", - "full_name", - "username" - ] - }, - "owner": { - "$ref": "#/components/schemas/owner" - }, - "payload": { - "oneOf": [ - { - "$ref": "#/components/schemas/payload_alert_comment" - }, - { - "$ref": "#/components/schemas/payload_assignees" - }, - { - "$ref": "#/components/schemas/payload_connector" - }, - { - "$ref": "#/components/schemas/payload_create_case" - }, - { - "$ref": "#/components/schemas/payload_delete" - }, - { - "$ref": "#/components/schemas/payload_description" - }, - { - "$ref": "#/components/schemas/payload_pushed" - }, - { - "$ref": "#/components/schemas/payload_settings" - }, - { - "$ref": "#/components/schemas/payload_severity" - }, - { - "$ref": "#/components/schemas/payload_status" - }, - { - "$ref": "#/components/schemas/payload_tags" - }, - { - "$ref": "#/components/schemas/payload_title" - }, - { - "$ref": "#/components/schemas/payload_user_comment" - } - ] - }, - "type": { - "$ref": "#/components/schemas/action_types" - } - } - }, "user_actions_find_response_properties": { "type": "object", "required": [ diff --git a/x-pack/platform/plugins/shared/cases/docs/openapi/bundled.yaml b/x-pack/platform/plugins/shared/cases/docs/openapi/bundled.yaml index 26ba97f36824d..9c2f650d56fa3 100644 --- a/x-pack/platform/plugins/shared/cases/docs/openapi/bundled.yaml +++ b/x-pack/platform/plugins/shared/cases/docs/openapi/bundled.yaml @@ -750,37 +750,6 @@ paths: application/json: schema: $ref: '#/components/schemas/4xx_response' - /api/cases/status: - get: - summary: Get case status summary - operationId: getCaseStatusDefaultSpace - description: | - Returns the number of cases that are open, closed, and in progress. Deprecated in 8.1.0. This API is deprecated and will be removed in a future release; use the find cases API instead. You must have `read` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana feature privileges, depending on the owner of the cases you're seeking. - deprecated: true - tags: - - cases - parameters: - - $ref: '#/components/parameters/owner_filter' - responses: - '200': - description: Indicates a successful call. - content: - application/json: - schema: - type: object - properties: - count_closed_cases: - type: integer - count_in_progress_cases: - type: integer - count_open_cases: - type: integer - '401': - description: Authorization information is missing or invalid. - content: - application/json: - schema: - $ref: '#/components/schemas/4xx_response' /api/cases/tags: get: summary: Get case tags @@ -1067,32 +1036,6 @@ paths: application/json: schema: $ref: '#/components/schemas/4xx_response' - /api/cases/{caseId}/user_actions: - get: - summary: Get case activity - description: | - Returns all user activity for a case. Deprecated in 8.1.0. This API is deprecated and will be removed in a future release; use the find user actions API instead. You must have `read` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana feature privileges, depending on the owner of the case you're seeking. - deprecated: true - operationId: getCaseActivityDefaultSpace - tags: - - cases - parameters: - - $ref: '#/components/parameters/case_id' - responses: - '200': - description: Indicates a successful call. - content: - application/json: - schema: - type: array - items: - $ref: '#/components/schemas/user_actions_response_properties' - '401': - description: Authorization information is missing or invalid. - content: - application/json: - schema: - $ref: '#/components/schemas/4xx_response' /api/cases/{caseId}/user_actions/_find: get: summary: Find case activity @@ -3172,93 +3115,6 @@ components: type: string enum: - user - action_types: - type: string - description: The type of action. - enum: - - assignees - - create_case - - comment - - connector - - delete_case - - description - - pushed - - tags - - title - - status - - settings - - severity - example: create_case - user_actions_response_properties: - type: object - required: - - action - - action_id - - case_id - - comment_id - - created_at - - created_by - - owner - - payload - - type - properties: - action: - $ref: '#/components/schemas/actions' - action_id: - type: string - example: 22fd3e30-03b1-11ed-920c-974bfa104448 - case_id: - type: string - example: 22df07d0-03b1-11ed-920c-974bfa104448 - comment_id: - type: string - nullable: true - example: 578608d0-03b1-11ed-920c-974bfa104448 - created_at: - type: string - format: date-time - example: '2022-05-13T09:16:17.416Z' - created_by: - type: object - properties: - email: - type: string - example: null - nullable: true - full_name: - type: string - example: null - nullable: true - username: - type: string - example: elastic - nullable: true - profile_uid: - type: string - example: u_J41Oh6L9ki-Vo2tOogS8WRTENzhHurGtRc87NgEAlkc_0 - required: - - email - - full_name - - username - owner: - $ref: '#/components/schemas/owner' - payload: - oneOf: - - $ref: '#/components/schemas/payload_alert_comment' - - $ref: '#/components/schemas/payload_assignees' - - $ref: '#/components/schemas/payload_connector' - - $ref: '#/components/schemas/payload_create_case' - - $ref: '#/components/schemas/payload_delete' - - $ref: '#/components/schemas/payload_description' - - $ref: '#/components/schemas/payload_pushed' - - $ref: '#/components/schemas/payload_settings' - - $ref: '#/components/schemas/payload_severity' - - $ref: '#/components/schemas/payload_status' - - $ref: '#/components/schemas/payload_tags' - - $ref: '#/components/schemas/payload_title' - - $ref: '#/components/schemas/payload_user_comment' - type: - $ref: '#/components/schemas/action_types' user_actions_find_response_properties: type: object required: diff --git a/x-pack/platform/plugins/shared/cases/docs/openapi/components/schemas/user_actions_response_properties.yaml b/x-pack/platform/plugins/shared/cases/docs/openapi/components/schemas/user_actions_response_properties.yaml deleted file mode 100644 index b6253e4a2a533..0000000000000 --- a/x-pack/platform/plugins/shared/cases/docs/openapi/components/schemas/user_actions_response_properties.yaml +++ /dev/null @@ -1,55 +0,0 @@ -type: object -required: - - action - - action_id - - case_id - - comment_id - - created_at - - created_by - - owner - - payload - - type -properties: - action: - $ref: 'actions.yaml' - action_id: - type: string - example: 22fd3e30-03b1-11ed-920c-974bfa104448 - case_id: - type: string - example: 22df07d0-03b1-11ed-920c-974bfa104448 - comment_id: - type: string - nullable: true - example: 578608d0-03b1-11ed-920c-974bfa104448 - created_at: - type: string - format: date-time - example: 2022-05-13T09:16:17.416Z - created_by: - type: object - properties: - $ref: 'user_properties.yaml' - required: - - email - - full_name - - username - owner: - $ref: 'owner.yaml' - payload: - oneOf: - - $ref: 'payload_alert_comment.yaml' - - $ref: 'payload_assignees.yaml' - - $ref: 'payload_connector.yaml' - - $ref: 'payload_create_case.yaml' - - $ref: 'payload_delete.yaml' - - $ref: 'payload_description.yaml' - - $ref: 'payload_pushed.yaml' - - $ref: 'payload_settings.yaml' - - $ref: 'payload_severity.yaml' - - $ref: 'payload_status.yaml' - - $ref: 'payload_tags.yaml' - - $ref: 'payload_title.yaml' - - $ref: 'payload_user_comment.yaml' - type: - $ref: 'action_types.yaml' diff --git a/x-pack/platform/plugins/shared/cases/docs/openapi/entrypoint.yaml b/x-pack/platform/plugins/shared/cases/docs/openapi/entrypoint.yaml index 09280d6f33ff9..c82b47fe8f563 100644 --- a/x-pack/platform/plugins/shared/cases/docs/openapi/entrypoint.yaml +++ b/x-pack/platform/plugins/shared/cases/docs/openapi/entrypoint.yaml @@ -27,8 +27,6 @@ paths: $ref: paths/api@cases@configure@{configurationid}.yaml '/api/cases/reporters': $ref: 'paths/api@cases@reporters.yaml' - '/api/cases/status': - $ref: 'paths/api@cases@status.yaml' '/api/cases/tags': $ref: 'paths/api@cases@tags.yaml' '/api/cases/{caseId}': @@ -43,8 +41,6 @@ paths: $ref: 'paths/api@cases@{caseid}@comments@{commentid}.yaml' '/api/cases/{caseId}/connector/{connectorId}/_push': $ref: 'paths/api@cases@{caseid}@connector@{connectorid}@_push.yaml' - '/api/cases/{caseId}/user_actions': - $ref: 'paths/api@cases@{caseid}@user_actions.yaml' '/api/cases/{caseId}/user_actions/_find': $ref: 'paths/api@cases@{caseid}@user_actions@_find.yaml' '/api/cases/configure/connectors/_find': diff --git a/x-pack/platform/plugins/shared/cases/docs/openapi/paths/api@cases@status.yaml b/x-pack/platform/plugins/shared/cases/docs/openapi/paths/api@cases@status.yaml deleted file mode 100644 index d930c00b6dc72..0000000000000 --- a/x-pack/platform/plugins/shared/cases/docs/openapi/paths/api@cases@status.yaml +++ /dev/null @@ -1,32 +0,0 @@ -get: - summary: Get case status summary - operationId: getCaseStatusDefaultSpace - description: > - Returns the number of cases that are open, closed, and in progress. - Deprecated in 8.1.0. This API is deprecated and will be removed in a future release; use the find cases API instead. - You must have `read` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana feature privileges, depending on the owner of the cases you're seeking. - deprecated: true - tags: - - cases - parameters: - - $ref: '../components/parameters/owner_filter.yaml' - responses: - '200': - description: Indicates a successful call. - content: - application/json: - schema: - type: object - properties: - count_closed_cases: - type: integer - count_in_progress_cases: - type: integer - count_open_cases: - type: integer - '401': - description: Authorization information is missing or invalid. - content: - application/json: - schema: - $ref: '../components/schemas/4xx_response.yaml' diff --git a/x-pack/platform/plugins/shared/cases/docs/openapi/paths/api@cases@{caseid}@user_actions.yaml b/x-pack/platform/plugins/shared/cases/docs/openapi/paths/api@cases@{caseid}@user_actions.yaml deleted file mode 100644 index 049f1ee895c2c..0000000000000 --- a/x-pack/platform/plugins/shared/cases/docs/openapi/paths/api@cases@{caseid}@user_actions.yaml +++ /dev/null @@ -1,29 +0,0 @@ -get: - summary: Get case activity - description: > - Returns all user activity for a case. - Deprecated in 8.1.0. This API is deprecated and will be removed in a future release; use the find user actions API instead. - You must have `read` privileges for the **Cases** feature in the - **Management**, **Observability**, or **Security** section of the Kibana - feature privileges, depending on the owner of the case you're seeking. - deprecated: true - operationId: getCaseActivityDefaultSpace - tags: - - cases - parameters: - - $ref: '../components/parameters/case_id.yaml' - responses: - '200': - description: Indicates a successful call. - content: - application/json: - schema: - type: array - items: - $ref: '../components/schemas/user_actions_response_properties.yaml' - '401': - description: Authorization information is missing or invalid. - content: - application/json: - schema: - $ref: '../components/schemas/4xx_response.yaml' diff --git a/x-pack/platform/plugins/shared/cases/server/routes/api/get_external_routes.ts b/x-pack/platform/plugins/shared/cases/server/routes/api/get_external_routes.ts index aff6dcffc22f6..6ed6dab570c9d 100644 --- a/x-pack/platform/plugins/shared/cases/server/routes/api/get_external_routes.ts +++ b/x-pack/platform/plugins/shared/cases/server/routes/api/get_external_routes.ts @@ -14,8 +14,6 @@ import { patchCaseRoute } from './cases/patch_cases'; import { postCaseRoute } from './cases/post_case'; import { pushCaseRoute } from './cases/push_case'; import { getReportersRoute } from './cases/reporters/get_reporters'; -import { getStatusRoute } from './stats/get_status'; -import { getUserActionsRoute } from './user_actions/get_all_user_actions'; import type { CaseRoute } from './types'; import { getTagsRoute } from './cases/tags/get_tags'; import { deleteAllCommentsRoute } from './comments/delete_all_comments'; @@ -48,8 +46,6 @@ export const getExternalRoutes = ({ postCaseRoute, pushCaseRoute, findUserActionsRoute, - getUserActionsRoute({ isServerless, docLinks }), - getStatusRoute({ isServerless, docLinks }), getCasesByAlertIdRoute, getReportersRoute, getTagsRoute, diff --git a/x-pack/platform/plugins/shared/cases/server/routes/api/stats/get_status.test.ts b/x-pack/platform/plugins/shared/cases/server/routes/api/stats/get_status.test.ts deleted file mode 100644 index 18cdbb90f0bd3..0000000000000 --- a/x-pack/platform/plugins/shared/cases/server/routes/api/stats/get_status.test.ts +++ /dev/null @@ -1,39 +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 { getStatusRoute } from './get_status'; -import { docLinksServiceMock } from '@kbn/core/server/mocks'; - -describe('getStatusRoute', () => { - const docLinks = docLinksServiceMock.createSetupContract(); - - it('marks the endpoint internal in serverless', async () => { - const router = getStatusRoute({ isServerless: true, docLinks }); - - expect(router.routerOptions?.access).toBe('internal'); - expect(router.routerOptions?.deprecated).toMatchInlineSnapshot( - { - documentationUrl: expect.stringMatching(/#breaking-201004$/), - }, - ` - Object { - "documentationUrl": StringMatching /#breaking-201004\\$/, - "reason": Object { - "type": "remove", - }, - "severity": "warning", - } - ` - ); - }); - - it('marks the endpoint public in non-serverless', async () => { - const router = getStatusRoute({ isServerless: false, docLinks }); - - expect(router.routerOptions?.access).toBe('public'); - }); -}); diff --git a/x-pack/platform/plugins/shared/cases/server/routes/api/stats/get_status.ts b/x-pack/platform/plugins/shared/cases/server/routes/api/stats/get_status.ts deleted file mode 100644 index 2d4fe5a1ca01b..0000000000000 --- a/x-pack/platform/plugins/shared/cases/server/routes/api/stats/get_status.ts +++ /dev/null @@ -1,66 +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 { DocLinksServiceSetup } from '@kbn/core/server'; -import type { CaseRoute } from '../types'; - -import { CASE_STATUS_URL } from '../../../../common/constants'; -import { createCaseError } from '../../../common/error'; -import { createCasesRoute } from '../create_cases_route'; -import type { statsApiV1 } from '../../../../common/types/api'; -import { DEFAULT_CASES_ROUTE_SECURITY } from '../constants'; - -/** - * @deprecated since version 8.1.0 - */ -export const getStatusRoute = ({ - isServerless, - docLinks, -}: { - isServerless?: boolean; - docLinks: DocLinksServiceSetup; -}): CaseRoute => - createCasesRoute({ - method: 'get', - path: CASE_STATUS_URL, - security: DEFAULT_CASES_ROUTE_SECURITY, - options: { deprecated: true }, - routerOptions: { - access: isServerless ? 'internal' : 'public', - summary: `Get case status summary`, - tags: ['oas-tag:cases'], - description: - 'Returns the number of cases that are open, closed, and in progress in the default space.', - // You must have `read` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana feature privileges, depending on the owner of the cases you're seeking. - deprecated: { - documentationUrl: docLinks.links.cases.legacyApiDeprecations, - severity: 'warning', - reason: { - type: 'remove', - }, - }, - }, - handler: async ({ context, request, response }) => { - try { - const caseContext = await context.cases; - const client = await caseContext.getCasesClient(); - - const res: statsApiV1.CasesStatusResponse = await client.metrics.getStatusTotalsByType( - request.query as statsApiV1.CasesStatusRequest - ); - - return response.ok({ - body: res, - }); - } catch (error) { - throw createCaseError({ - message: `Failed to get status stats in route: ${error}`, - error, - }); - } - }, - }); diff --git a/x-pack/platform/plugins/shared/cases/server/routes/api/user_actions/get_all_user_actions.test.ts b/x-pack/platform/plugins/shared/cases/server/routes/api/user_actions/get_all_user_actions.test.ts deleted file mode 100644 index cfc6531e8297b..0000000000000 --- a/x-pack/platform/plugins/shared/cases/server/routes/api/user_actions/get_all_user_actions.test.ts +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { getUserActionsRoute } from './get_all_user_actions'; -import { docLinksServiceMock } from '@kbn/core/server/mocks'; - -describe('getUserActionsRoute', () => { - const docLinks = docLinksServiceMock.createSetupContract(); - - it('marks the endpoint internal in serverless', async () => { - const router = getUserActionsRoute({ isServerless: true, docLinks }); - - expect(router.routerOptions?.access).toBe('internal'); - expect(router.routerOptions?.deprecated).toMatchInlineSnapshot( - { - documentationUrl: expect.stringMatching(/#breaking-201004$/), - }, - ` - Object { - "documentationUrl": StringMatching /#breaking-201004\\$/, - "reason": Object { - "newApiMethod": "GET", - "newApiPath": "/api/cases//user_actions/_find", - "type": "migrate", - }, - "severity": "warning", - } - ` - ); - }); - - it('marks the endpoint public in non-serverless', async () => { - const router = getUserActionsRoute({ isServerless: false, docLinks }); - - expect(router.routerOptions?.access).toBe('public'); - }); -}); diff --git a/x-pack/platform/plugins/shared/cases/server/routes/api/user_actions/get_all_user_actions.ts b/x-pack/platform/plugins/shared/cases/server/routes/api/user_actions/get_all_user_actions.ts deleted file mode 100644 index 427d5ffc18eef..0000000000000 --- a/x-pack/platform/plugins/shared/cases/server/routes/api/user_actions/get_all_user_actions.ts +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { schema } from '@kbn/config-schema'; - -import type { DocLinksServiceSetup } from '@kbn/core/server'; -import type { userActionApiV1 } from '../../../../common/types/api'; -import { CASE_USER_ACTIONS_URL } from '../../../../common/constants'; -import { createCaseError } from '../../../common/error'; -import { createCasesRoute } from '../create_cases_route'; -import { DEFAULT_CASES_ROUTE_SECURITY } from '../constants'; - -/** - * @deprecated since version 8.1.0 - */ -export const getUserActionsRoute = ({ - isServerless, - docLinks, -}: { - isServerless?: boolean; - docLinks: DocLinksServiceSetup; -}) => - createCasesRoute({ - method: 'get', - path: CASE_USER_ACTIONS_URL, - security: DEFAULT_CASES_ROUTE_SECURITY, - params: { - params: schema.object({ - case_id: schema.string(), - }), - }, - options: { deprecated: true }, - routerOptions: { - access: isServerless ? 'internal' : 'public', - summary: 'Get case activity', - description: `Returns all user activity for a case.`, - // You must have `read` privileges for the **Cases** feature in the **Management**, **Observability**, or **Security** section of the Kibana feature privileges, depending on the owner of the case you're seeking. - tags: ['oas-tag:cases'], - deprecated: { - documentationUrl: docLinks.links.cases.legacyApiDeprecations, - severity: 'warning', - reason: { - type: 'migrate', - newApiMethod: 'GET', - newApiPath: '/api/cases//user_actions/_find', - }, - }, - }, - handler: async ({ context, request, response }) => { - try { - const caseContext = await context.cases; - const casesClient = await caseContext.getCasesClient(); - const caseId = request.params.case_id; - - const res: userActionApiV1.CaseUserActionsDeprecatedResponse = - await casesClient.userActions.getAll({ caseId }); - - return response.ok({ - body: res, - }); - } catch (error) { - throw createCaseError({ - message: `Failed to retrieve case user actions in route case id: ${request.params.case_id}: ${error}`, - error, - }); - } - }, - }); diff --git a/x-pack/platform/plugins/shared/event_log/README.md b/x-pack/platform/plugins/shared/event_log/README.md index 7d192517db65d..769c681603bff 100644 --- a/x-pack/platform/plugins/shared/event_log/README.md +++ b/x-pack/platform/plugins/shared/event_log/README.md @@ -166,7 +166,11 @@ Below is a document in the expected structure, with descriptions of the fields: total_search_duration_ms: "total time spent performing ES searches as measured by Kibana; includes network latency and time spent serializing/deserializing request/response", total_indexing_duration_ms: "total time spent indexing documents during current rule execution cycle", total_enrichment_duration_ms: "total time spent enriching documents during current rule execution cycle", - execution_gap_duration_s: "duration in seconds of execution gap" + execution_gap_duration_s: "duration in seconds of execution gap", + gap_range: { + gte: "Gap range start date", + lte: "Gap range end date", + } } } } diff --git a/x-pack/platform/plugins/shared/event_log/generated/mappings.json b/x-pack/platform/plugins/shared/event_log/generated/mappings.json index 110cc3b6665f9..4bd9d5e5a5b44 100644 --- a/x-pack/platform/plugins/shared/event_log/generated/mappings.json +++ b/x-pack/platform/plugins/shared/event_log/generated/mappings.json @@ -325,6 +325,51 @@ "type": "keyword", "ignore_above": 1024 }, + "gap": { + "properties": { + "status": { + "type": "keyword", + "ignore_above": 1024 + }, + "range": { + "type": "date_range", + "format": "strict_date_optional_time||epoch_millis" + }, + "filled_intervals": { + "type": "date_range", + "format": "strict_date_optional_time||epoch_millis", + "meta": { + "isArray": "true" + } + }, + "unfilled_intervals": { + "format": "strict_date_optional_time||epoch_millis", + "type": "date_range", + "meta": { + "isArray": "true" + } + }, + "in_progress_intervals": { + "format": "strict_date_optional_time||epoch_millis", + "type": "date_range", + "meta": { + "isArray": "true" + } + }, + "total_gap_duration_ms": { + "type": "long" + }, + "filled_duration_ms": { + "type": "long" + }, + "unfilled_duration_ms": { + "type": "long" + }, + "in_progress_duration_ms": { + "type": "long" + } + } + }, "execution": { "properties": { "uuid": { @@ -392,6 +437,10 @@ "execution_gap_duration_s": { "type": "long" }, + "gap_range": { + "type": "date_range", + "format": "strict_date_optional_time||epoch_millis" + }, "rule_type_run_duration_ms": { "type": "long" }, diff --git a/x-pack/platform/plugins/shared/event_log/generated/schemas.ts b/x-pack/platform/plugins/shared/event_log/generated/schemas.ts index ef3e9c7facbf9..0e8ae6187fc58 100644 --- a/x-pack/platform/plugins/shared/event_log/generated/schemas.ts +++ b/x-pack/platform/plugins/shared/event_log/generated/schemas.ts @@ -146,6 +146,19 @@ export const EventSchema = schema.maybe( rule: schema.maybe( schema.object({ consumer: ecsString(), + gap: schema.maybe( + schema.object({ + status: ecsString(), + range: ecsDateRange(), + filled_intervals: ecsDateRangeMulti(), + unfilled_intervals: ecsDateRangeMulti(), + in_progress_intervals: ecsDateRangeMulti(), + total_gap_duration_ms: ecsStringOrNumber(), + filled_duration_ms: ecsStringOrNumber(), + unfilled_duration_ms: ecsStringOrNumber(), + in_progress_duration_ms: ecsStringOrNumber(), + }) + ), execution: schema.maybe( schema.object({ uuid: ecsString(), @@ -175,6 +188,7 @@ export const EventSchema = schema.maybe( es_search_duration_ms: ecsStringOrNumber(), total_search_duration_ms: ecsStringOrNumber(), execution_gap_duration_s: ecsStringOrNumber(), + gap_range: ecsDateRange(), rule_type_run_duration_ms: ecsStringOrNumber(), process_alerts_duration_ms: ecsStringOrNumber(), trigger_actions_duration_ms: ecsStringOrNumber(), @@ -272,6 +286,18 @@ function ecsBoolean() { return schema.maybe(schema.boolean()); } +function ecsDateRangeBase() { + return schema.object({ gte: ecsDate(), lte: ecsDate() }); +} + +function ecsDateRange() { + return schema.maybe(ecsDateRangeBase()); +} + +function ecsDateRangeMulti() { + return schema.maybe(schema.arrayOf(ecsDateRangeBase())); +} + const ISO_DATE_PATTERN = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/; function validateDate(isoDate: string) { diff --git a/x-pack/platform/plugins/shared/event_log/scripts/create_schemas.js b/x-pack/platform/plugins/shared/event_log/scripts/create_schemas.js index 7e4dded27f1aa..ae195514e25bc 100755 --- a/x-pack/platform/plugins/shared/event_log/scripts/create_schemas.js +++ b/x-pack/platform/plugins/shared/event_log/scripts/create_schemas.js @@ -166,6 +166,15 @@ function generateSchemaLines(lineWriter, prop, mappings) { return; } + if (mappings.type === 'date_range') { + if (mappings.meta && mappings.meta.isArray === 'true') { + lineWriter.addLine(`${propKey}: ecsDateRangeMulti(),`); + } else { + lineWriter.addLine(`${propKey}: ecsDateRange(),`); + } + return; + } + // only handling objects for the rest of this function if (mappings.properties == null) { logError(`unknown properties to map: ${prop}: ${JSON.stringify(mappings)}`); @@ -333,6 +342,18 @@ function ecsBoolean() { return schema.maybe(schema.boolean()); } +function ecsDateRangeBase() { + return schema.object({ gte: ecsDate(), lte: ecsDate() }); +} + +function ecsDateRange() { + return schema.maybe(ecsDateRangeBase()); +} + +function ecsDateRangeMulti() { + return schema.maybe(schema.arrayOf(ecsDateRangeBase())); +} + const ISO_DATE_PATTERN = /^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}Z$/; function validateDate(isoDate: string) { diff --git a/x-pack/platform/plugins/shared/event_log/scripts/mappings.js b/x-pack/platform/plugins/shared/event_log/scripts/mappings.js index 349ed4903ae29..052ea5aa0cbb2 100644 --- a/x-pack/platform/plugins/shared/event_log/scripts/mappings.js +++ b/x-pack/platform/plugins/shared/event_log/scripts/mappings.js @@ -100,6 +100,42 @@ exports.EcsCustomPropertyMappings = { type: 'keyword', ignore_above: 1024, }, + gap: { + properties: { + status: { + type: 'keyword', + ignore_above: 1024, + }, + range: { + type: 'date_range', + format: 'strict_date_optional_time||epoch_millis', + }, + filled_intervals: { + type: 'date_range', + format: 'strict_date_optional_time||epoch_millis', + }, + unfilled_intervals: { + format: 'strict_date_optional_time||epoch_millis', + type: 'date_range', + }, + in_progress_intervals: { + format: 'strict_date_optional_time||epoch_millis', + type: 'date_range', + }, + total_gap_duration_ms: { + type: 'long', + }, + filled_duration_ms: { + type: 'long', + }, + unfilled_duration_ms: { + type: 'long', + }, + in_progress_duration_ms: { + type: 'long', + }, + }, + }, execution: { properties: { uuid: { @@ -167,6 +203,10 @@ exports.EcsCustomPropertyMappings = { execution_gap_duration_s: { type: 'long', }, + gap_range: { + type: 'date_range', + format: 'strict_date_optional_time||epoch_millis', + }, rule_type_run_duration_ms: { type: 'long', }, @@ -342,4 +382,7 @@ exports.EcsEventLogMultiValuedProperties = [ 'rule.author', 'kibana.space_ids', 'kibana.alert.maintenance_window_ids', + 'kibana.alert.rule.gap.in_progress_intervals', + 'kibana.alert.rule.gap.filled_intervals', + 'kibana.alert.rule.gap.unfilled_intervals', ]; diff --git a/x-pack/platform/plugins/shared/fleet/server/saved_objects/index.ts b/x-pack/platform/plugins/shared/fleet/server/saved_objects/index.ts index e6695fc5bb2e2..94292f9a28bd5 100644 --- a/x-pack/platform/plugins/shared/fleet/server/saved_objects/index.ts +++ b/x-pack/platform/plugins/shared/fleet/server/saved_objects/index.ts @@ -102,6 +102,7 @@ import { } from './migrations/to_v8_15_0'; import { backfillAgentPolicyToV4 } from './model_versions/agent_policy_v4'; import { backfillOutputPolicyToV7 } from './model_versions/outputs'; +import { packagePolicyV17AdvancedFieldsForEndpointV818 } from './model_versions/security_solution/v17_advanced_package_policy_fields'; /* * Saved object types and mappings @@ -826,6 +827,14 @@ export const getSavedObjectTypes = ( }, ], }, + '17': { + changes: [ + { + type: 'data_backfill', + backfillFn: packagePolicyV17AdvancedFieldsForEndpointV818, + }, + ], + }, }, migrations: { '7.10.0': migratePackagePolicyToV7100, @@ -911,6 +920,14 @@ export const getSavedObjectTypes = ( }, ], }, + '3': { + changes: [ + { + type: 'data_backfill', + backfillFn: packagePolicyV17AdvancedFieldsForEndpointV818, + }, + ], + }, }, }, [PACKAGES_SAVED_OBJECT_TYPE]: { diff --git a/x-pack/platform/plugins/shared/fleet/server/saved_objects/model_versions/security_solution/v17_advanced_package_policy_fields.test.ts b/x-pack/platform/plugins/shared/fleet/server/saved_objects/model_versions/security_solution/v17_advanced_package_policy_fields.test.ts new file mode 100644 index 0000000000000..a9a8a75514aba --- /dev/null +++ b/x-pack/platform/plugins/shared/fleet/server/saved_objects/model_versions/security_solution/v17_advanced_package_policy_fields.test.ts @@ -0,0 +1,182 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { 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 { set } from '@kbn/safer-lodash-set'; + +import { + PACKAGE_POLICY_SAVED_OBJECT_TYPE, + LEGACY_PACKAGE_POLICY_SAVED_OBJECT_TYPE, +} from '../../../../common/constants'; + +import { getSavedObjectTypes } from '../..'; + +import type { PackagePolicy } from '../../../../common'; + +describe('Defend integration advanced policy fields v8.18.0', () => { + describe.each` + title | soType | targetModelVersion + ${'original SO'} | ${LEGACY_PACKAGE_POLICY_SAVED_OBJECT_TYPE} | ${17} + ${'space aware SO'} | ${PACKAGE_POLICY_SAVED_OBJECT_TYPE} | ${3} + `( + 'for $title ($soType)', + ({ soType, targetModelVersion }: { soType: string; targetModelVersion: number }) => { + let migrator: ModelVersionTestMigrator; + let policyConfigSO: SavedObject; + + beforeEach(() => { + migrator = createModelVersionTestMigrator({ + type: getSavedObjectTypes()[soType], + }); + + policyConfigSO = { + id: 'mock-saved-object-id', + attributes: { + name: 'Some Policy Name', + package: { + name: 'endpoint', + title: '', + version: '', + }, + id: 'endpoint', + policy_id: '', + policy_ids: [], + enabled: true, + namespace: '', + revision: 0, + updated_at: '', + updated_by: '', + created_at: '', + created_by: '', + inputs: [ + { + type: 'endpoint', + enabled: true, + streams: [], + config: { + policy: { + value: { + windows: {}, + mac: {}, + linux: {}, + }, + }, + }, + }, + ], + }, + type: soType, + references: [], + }; + }); + + /** Builds object key paths for all parent objects + * + * @param path e.g. `advanced.events.optionName` + * @returns e.g. ['advanced', 'advanced.events'] + */ + const getParentObjectKeyPaths = (path: string): string[] => + path + .split('.') // ['advanced', 'events', 'optionName'] + .slice(0, -1) // ['advanced', 'events'] + .map((parentObject) => path.match(`^.*${parentObject}`)![0]); // ['advanced', 'advanced.events'] + + describe(`when updating to model version ${targetModelVersion}`, () => { + describe.each` + name | path | backfill + ${'aggregate_process'} | ${'advanced.events.aggregate_process'} | ${false} + ${'aggregate_network'} | ${'advanced.events.aggregate_network'} | ${false} + ${'set_extended_host_information'} | ${'advanced.set_extended_host_information'} | ${true} + ${'alerts.hash.md5'} | ${'advanced.alerts.hash.md5'} | ${true} + ${'alerts.hash.sha1'} | ${'advanced.alerts.hash.sha1'} | ${true} + ${'events.hash.md5'} | ${'advanced.events.hash.md5'} | ${true} + ${'events.hash.sha1'} | ${'advanced.events.hash.sha1'} | ${true} + `( + 'backfilling `$name` with `$backfill`', + ({ path, backfill }: { path: string; backfill: boolean }) => { + it('should backfill when there are no advanced options yet', () => { + const migratedPolicyConfigSO = migrator.migrate({ + document: policyConfigSO, + fromVersion: targetModelVersion - 1, + toVersion: targetModelVersion, + }); + + const migratedPolicyConfig = getConfig(migratedPolicyConfigSO); + + expectConfigToHave(migratedPolicyConfig, path, backfill); + }); + + it.each(getParentObjectKeyPaths(path))( + 'should backfill without modifying other options in parent object `%s`', + (parentObjectKeyPath) => { + const policyConfig = getConfig(policyConfigSO); + const dummyField = `${parentObjectKeyPath}.cheese`; + set(policyConfig.windows, dummyField, 'brie'); + set(policyConfig.mac, dummyField, 'maasdam'); + set(policyConfig.linux, dummyField, 'camambert'); + + const migratedPolicyConfigSO = migrator.migrate({ + document: policyConfigSO, + fromVersion: targetModelVersion - 1, + toVersion: targetModelVersion, + }); + + const migratedPolicyConfig = getConfig(migratedPolicyConfigSO); + + expectConfigToHave(migratedPolicyConfig, path, backfill); + expect(migratedPolicyConfig.windows).toHaveProperty(dummyField, 'brie'); + expect(migratedPolicyConfig.mac).toHaveProperty(dummyField, 'maasdam'); + expect(migratedPolicyConfig.linux).toHaveProperty(dummyField, 'camambert'); + } + ); + + it('should not backfill if field is already present', () => { + const policyConfig = getConfig(policyConfigSO); + set(policyConfig.windows, path, !backfill); + set(policyConfig.mac, path, !backfill); + set(policyConfig.linux, path, !backfill); + + const migratedPolicyConfigSO = migrator.migrate({ + document: policyConfigSO, + fromVersion: targetModelVersion - 1, + toVersion: targetModelVersion, + }); + + const migratedPolicyConfig = getConfig(migratedPolicyConfigSO); + + expectConfigToHave(migratedPolicyConfig, path, !backfill); + }); + } + ); + + it('should contain revision bump trigger', () => { + const migratedPolicyConfigSO = migrator.migrate({ + document: policyConfigSO, + fromVersion: targetModelVersion - 1, + toVersion: targetModelVersion, + }); + + expect(migratedPolicyConfigSO.attributes).toHaveProperty( + 'bump_agent_policy_revision', + true + ); + }); + }); + + const getConfig = (so: SavedObject) => + so.attributes.inputs[0].config?.policy.value; + + const expectConfigToHave = (config: any, path: string, value: string | boolean) => { + for (const os of ['windows', 'mac', 'linux']) { + expect(config[os]).toHaveProperty(path, value); + } + }; + } + ); +}); diff --git a/x-pack/platform/plugins/shared/fleet/server/saved_objects/model_versions/security_solution/v17_advanced_package_policy_fields.ts b/x-pack/platform/plugins/shared/fleet/server/saved_objects/model_versions/security_solution/v17_advanced_package_policy_fields.ts new file mode 100644 index 0000000000000..6675ae5a3df6f --- /dev/null +++ b/x-pack/platform/plugins/shared/fleet/server/saved_objects/model_versions/security_solution/v17_advanced_package_policy_fields.ts @@ -0,0 +1,65 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { + SavedObjectModelDataBackfillFn, + SavedObjectUnsanitizedDoc, +} from '@kbn/core-saved-objects-server'; + +import type { PackagePolicy } from '../../../../common'; + +export const packagePolicyV17AdvancedFieldsForEndpointV818: 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; + + for (const os of ['windows', 'mac', 'linux']) { + const policyPerOs = policy[os]; + + policyPerOs.advanced = { + set_extended_host_information: true, + ...policyPerOs.advanced, + + events: { + aggregate_process: false, + aggregate_network: false, + ...policyPerOs.advanced?.events, + + hash: { + md5: true, + sha1: true, + ...policyPerOs.advanced?.events?.hash, + }, + }, + + alerts: { + ...policyPerOs.advanced?.alerts, + + hash: { + md5: true, + sha1: true, + ...policyPerOs.advanced?.alerts?.hash, + }, + }, + }; + } + } + + return { + attributes: { ...updatedPackagePolicyDoc.attributes, bump_agent_policy_revision: true }, + }; +}; diff --git a/x-pack/platform/plugins/shared/fleet/server/services/agents/actions.test.ts b/x-pack/platform/plugins/shared/fleet/server/services/agents/actions.test.ts index 594d553bff941..96f83f844aad3 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/agents/actions.test.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/agents/actions.test.ts @@ -531,5 +531,39 @@ describe('Agent actions', () => { const actionsIds = ['action1:1', 'action2']; expect(await getAgentsByActionsIds(esClientMock, actionsIds)).toEqual([]); }); + + it('should find agents by passing actions Ids by querying actions results', async () => { + esClientMock.search.mockImplementation((params: any) => + params.index === '.fleet-actions' + ? ({ + hits: { + hits: [ + { + _source: { + action_id: 'action2', + agents: ['agent3'], + total: 2, + expiration: '2022-05-12T18:16:18.019Z', + type: 'UPGRADE', + }, + }, + ], + }, + } as any) + : { + hits: { + hits: [ + { + _source: { + agent_id: 'agent4', + }, + }, + ], + }, + } + ); + const actionsIds = ['action2']; + expect(await getAgentsByActionsIds(esClientMock, actionsIds)).toEqual(['agent3', 'agent4']); + }); }); }); diff --git a/x-pack/platform/plugins/shared/fleet/server/services/agents/actions.ts b/x-pack/platform/plugins/shared/fleet/server/services/agents/actions.ts index e3e291eb1ae18..ff1f56bdb1224 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/agents/actions.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/agents/actions.ts @@ -10,7 +10,7 @@ import type { ElasticsearchClient, SavedObjectsClientContract } from '@kbn/core/ import apm from 'elastic-apm-node'; import pMap from 'p-map'; -import { partition } from 'lodash'; +import { partition, uniq } from 'lodash'; import { appContextService } from '../app_context'; import type { @@ -446,7 +446,10 @@ export async function cancelAgentAction( } as AgentAction; } -async function getAgentActionsByIds(esClient: ElasticsearchClient, actionIds: string[]) { +async function getAgentActionsByIds( + esClient: ElasticsearchClient, + actionIds: string[] +): Promise { if (actionIds.length === 0) { return []; } @@ -464,6 +467,7 @@ async function getAgentActionsByIds(esClient: ElasticsearchClient, actionIds: st ], }, }, + _source: ['agents', 'total'], size: SO_SEARCH_LIMIT, }); @@ -473,6 +477,7 @@ async function getAgentActionsByIds(esClient: ElasticsearchClient, actionIds: st } const result: FleetServerAgentAction[] = []; + let total = 0; for (const hit of res.hits.hits) { auditLoggingService.writeCustomAuditLog({ @@ -483,9 +488,53 @@ async function getAgentActionsByIds(esClient: ElasticsearchClient, actionIds: st ...hit._source, id: hit._id, }); + total = hit._source?.total ?? 0; } - return result; + const agentIds: string[] = []; + if (result.length > 0) { + agentIds.push(...(result.flatMap((a) => a?.agents).filter((agent) => !!agent) as string[])); + } + + if (agentIds.length < total) { + const agentIdsFromResults = await getAgentIdsFromResults(esClient, actionIds); + return uniq([...agentIds, ...agentIdsFromResults]); + } + + return agentIds; +} + +async function getAgentIdsFromResults( + esClient: ElasticsearchClient, + actionIds: string[] +): Promise { + try { + const results = await esClient.search({ + index: AGENT_ACTIONS_RESULTS_INDEX, + ignore_unavailable: true, + query: { + bool: { + filter: [{ terms: { action_id: actionIds } }, { exists: { field: 'error' } }], + }, + }, + _source: ['agent_id'], + size: SO_SEARCH_LIMIT, + }); + + const resultAgentIds = new Set(); + for (const hit of results.hits.hits) { + resultAgentIds.add((hit._source as any)?.agent_id); + } + return Array.from(resultAgentIds); + } catch (err) { + if (err.statusCode === 404) { + // .fleet-actions-results does not yet exist + appContextService.getLogger().debug(err); + } else { + throw err; + } + } + return []; } export const getAgentsByActionsIds = async ( @@ -501,14 +550,7 @@ export const getAgentsByActionsIds = async ( (actionsId) => actionsId.split(':').length > 1 ); - const agentIds: string[] = []; - - const agentActions = await getAgentActionsByIds(esClient, agentActionIds); - if (agentActions.length > 0) { - agentIds.push( - ...(agentActions.flatMap((a) => a?.agents).filter((agent) => !!agent) as string[]) - ); - } + const agentIds: string[] = await getAgentActionsByIds(esClient, agentActionIds); const policyIds = agentPolicyActionIds.map((actionId) => actionId.split(':')[0]); const assignedAgentIds = await getAgentIdsForAgentPolicies(esClient, policyIds); diff --git a/x-pack/platform/plugins/shared/lens/common/expressions/map_to_columns/map_to_columns.test.ts b/x-pack/platform/plugins/shared/lens/common/expressions/map_to_columns/map_to_columns.test.ts index 530d3bf3121a1..9c39f7e245b14 100644 --- a/x-pack/platform/plugins/shared/lens/common/expressions/map_to_columns/map_to_columns.test.ts +++ b/x-pack/platform/plugins/shared/lens/common/expressions/map_to_columns/map_to_columns.test.ts @@ -330,5 +330,56 @@ describe('map_to_columns', () => { { a: 7, b: 8 }, ]); }); + + it('should handle correctly columns controlled by variables', async () => { + const input: Datatable = { + type: 'datatable', + columns: [ + { id: 'a', name: 'A', meta: { type: 'number' } }, + { id: 'b', name: 'B', meta: { type: 'number' } }, + { id: 'c', name: 'C', meta: { type: 'string' }, variable: 'field' }, + ], + rows: [ + { a: 1, b: 2, c: '3' }, + { a: 3, b: 4, c: '5' }, + { a: 5, b: 6, c: '7' }, + { a: 7, b: 8, c: '9' }, + ], + }; + + const idMap = { + a: [ + { + id: 'a', + label: 'A', + }, + ], + '?field': [ + { + id: 'field', + label: '?field', + variable: 'field', + }, + ], + }; + + const result = await mapToColumns.fn( + input, + { idMap: JSON.stringify(idMap), isTextBased: true }, + createMockExecutionContext() + ); + + expect(result.columns).toStrictEqual([ + { id: 'a', name: 'A', meta: { type: 'number', field: undefined, params: undefined } }, + { id: 'field', name: 'C', meta: { type: 'string' }, variable: 'field' }, + ]); + + expect(result.rows).toStrictEqual([ + { a: 1, field: '3' }, + { a: 3, field: '5' }, + { a: 5, field: '7' }, + { a: 7, field: '9' }, + ]); + }); }); }); diff --git a/x-pack/platform/plugins/shared/lens/common/expressions/map_to_columns/map_to_columns_fn_textbased.ts b/x-pack/platform/plugins/shared/lens/common/expressions/map_to_columns/map_to_columns_fn_textbased.ts index 1e6a869626ffd..8b662c7b47e65 100644 --- a/x-pack/platform/plugins/shared/lens/common/expressions/map_to_columns/map_to_columns_fn_textbased.ts +++ b/x-pack/platform/plugins/shared/lens/common/expressions/map_to_columns/map_to_columns_fn_textbased.ts @@ -5,14 +5,30 @@ * 2.0. */ +import { DatatableColumn } from '@kbn/expressions-plugin/common'; import type { OriginalColumn, MapToColumnsExpressionFunction } from './types'; export const mapToOriginalColumnsTextBased: MapToColumnsExpressionFunction['fn'] = ( data, { idMap: encodedIdMap } ) => { + const isOriginalColumn = (item: OriginalColumn | undefined): item is OriginalColumn => { + return !!item; + }; const idMap = JSON.parse(encodedIdMap) as Record; + // extract all the entries once + const idMapColEntries = Object.entries(idMap); + // create a lookup id => column + const colLookups = new Map(data.columns.map((c) => [c.id, c])); + + // now create a lookup to get the original columns for each variable + const colVariableLookups = new Map( + idMapColEntries.flatMap(([id, columns]) => + columns.filter(({ variable }) => variable).map(({ variable }) => [`${variable}`, columns]) + ) + ); + return { ...data, rows: data.rows.map((row) => { @@ -21,7 +37,17 @@ export const mapToOriginalColumnsTextBased: MapToColumnsExpressionFunction['fn'] for (const id in row) { if (id in idMap) { for (const cachedEntry of idMap[id]) { - mappedRow[cachedEntry.id] = row[id]; // <= I wrote idMap rather than mappedRow + mappedRow[cachedEntry.id] = row[id]; + } + } else { + const col = colLookups.get(id); + if (col?.variable) { + const originalColumn = colVariableLookups.get(col.variable); + if (originalColumn) { + for (const cachedEntry of originalColumn) { + mappedRow[cachedEntry.id] = row[id]; + } + } } } } @@ -29,9 +55,20 @@ export const mapToOriginalColumnsTextBased: MapToColumnsExpressionFunction['fn'] return mappedRow; }), columns: data.columns.flatMap((column) => { - if (!(column.id in idMap)) { + if (!(column.id in idMap) && !column.variable) { return []; } + if (column.variable) { + const originalColumn = idMapColEntries + .map(([_id, columns]) => columns.find((c) => c.variable === column.variable)) + .filter(isOriginalColumn); + + if (!originalColumn) { + return []; + } + + return originalColumn.map((c) => ({ ...column, id: c.id })); + } return idMap[column.id].map((originalColumn) => ({ ...column, id: originalColumn.id, diff --git a/x-pack/platform/plugins/shared/lens/common/expressions/map_to_columns/types.ts b/x-pack/platform/plugins/shared/lens/common/expressions/map_to_columns/types.ts index f7559a539910b..8993d4f1d68b9 100644 --- a/x-pack/platform/plugins/shared/lens/common/expressions/map_to_columns/types.ts +++ b/x-pack/platform/plugins/shared/lens/common/expressions/map_to_columns/types.ts @@ -8,7 +8,12 @@ import { Datatable, ExpressionFunctionDefinition } from '@kbn/expressions-plugin/common'; import { SerializedFieldFormat } from '@kbn/field-formats-plugin/common'; -export type OriginalColumn = { id: string; label: string; format?: SerializedFieldFormat } & ( +export type OriginalColumn = { + id: string; + label: string; + variable?: string; + format?: SerializedFieldFormat; +} & ( | { operationType: 'date_histogram'; sourceField: string } | { operationType: string; sourceField: never } ); diff --git a/x-pack/platform/plugins/shared/lens/kibana.jsonc b/x-pack/platform/plugins/shared/lens/kibana.jsonc index 012a077abb122..c4f9dd5a5dcf4 100644 --- a/x-pack/platform/plugins/shared/lens/kibana.jsonc +++ b/x-pack/platform/plugins/shared/lens/kibana.jsonc @@ -1,9 +1,7 @@ { "type": "plugin", "id": "@kbn/lens-plugin", - "owner": [ - "@elastic/kibana-visualizations" - ], + "owner": ["@elastic/kibana-visualizations"], "group": "platform", "visibility": "shared", "description": "Visualization editor allowing to quickly and easily configure compelling visualizations to use on dashboards and canvas workpads. Exposes components to embed visualizations and link into the Lens editor from within other apps in Kibana.", @@ -11,10 +9,7 @@ "id": "lens", "browser": true, "server": true, - "configPath": [ - "xpack", - "lens" - ], + "configPath": ["xpack", "lens"], "requiredPlugins": [ "data", "dataViews", @@ -62,10 +57,8 @@ "fieldFormats", "charts", "esqlDataGrid", - "esql" + "esql", ], - "extraPublicDirs": [ - "common/constants" - ] + "extraPublicDirs": ["common/constants"] } -} \ No newline at end of file +} diff --git a/x-pack/platform/plugins/shared/lens/public/app_plugin/shared/edit_on_the_fly/get_edit_lens_configuration.tsx b/x-pack/platform/plugins/shared/lens/public/app_plugin/shared/edit_on_the_fly/get_edit_lens_configuration.tsx index dedd34c24cb53..8d3d835bf5e0a 100644 --- a/x-pack/platform/plugins/shared/lens/public/app_plugin/shared/edit_on_the_fly/get_edit_lens_configuration.tsx +++ b/x-pack/platform/plugins/shared/lens/public/app_plugin/shared/edit_on_the_fly/get_edit_lens_configuration.tsx @@ -155,6 +155,7 @@ export async function getEditLensConfiguration( onApply, onCancel, hideTimeFilterInfo, + parentApi, }: EditLensConfigurationProps) => { if (!lensServices || !datasourceMap || !visualizationMap) { return ; @@ -225,6 +226,8 @@ export async function getEditLensConfiguration( onApply, onCancel, hideTimeFilterInfo, + parentApi, + panelId, }; return ( diff --git a/x-pack/platform/plugins/shared/lens/public/app_plugin/shared/edit_on_the_fly/helpers.ts b/x-pack/platform/plugins/shared/lens/public/app_plugin/shared/edit_on_the_fly/helpers.ts index c0280af595041..b0d5a89a707b9 100644 --- a/x-pack/platform/plugins/shared/lens/public/app_plugin/shared/edit_on_the_fly/helpers.ts +++ b/x-pack/platform/plugins/shared/lens/public/app_plugin/shared/edit_on_the_fly/helpers.ts @@ -9,8 +9,10 @@ import { getESQLAdHocDataview, getESQLResults, formatESQLColumns, + mapVariableToColumn, } from '@kbn/esql-utils'; import { type AggregateQuery, buildEsQuery } from '@kbn/es-query'; +import type { ESQLControlVariable } from '@kbn/esql-validation-autocomplete'; import type { ESQLRow } from '@kbn/es-types'; import { getLensAttributesFromSuggestion } from '@kbn/visualization-utils'; import type { DataViewSpec } from '@kbn/data-views-plugin/public'; @@ -48,7 +50,8 @@ export const getGridAttrs = async ( query: AggregateQuery, adHocDataViews: DataViewSpec[], deps: LensPluginStartDependencies, - abortController?: AbortController + abortController?: AbortController, + esqlVariables: ESQLControlVariable[] = [] ): Promise => { const indexPattern = getIndexPatternFromESQLQuery(query.esql); const dataViewSpec = adHocDataViews.find((adHoc) => { @@ -68,6 +71,7 @@ export const getGridAttrs = async ( filter, dropNullColumns: true, timeRange: deps.data.query.timefilter.timefilter.getAbsoluteTime(), + variables: esqlVariables, }); const columns = formatESQLColumns(results.response.columns); @@ -85,28 +89,38 @@ export const getSuggestions = async ( datasourceMap: DatasourceMap, visualizationMap: VisualizationMap, adHocDataViews: DataViewSpec[], - setErrors: (errors: Error[]) => void, + setErrors?: (errors: Error[]) => void, abortController?: AbortController, - setDataGridAttrs?: (attrs: ESQLDataGridAttrs) => void + setDataGridAttrs?: (attrs: ESQLDataGridAttrs) => void, + esqlVariables: ESQLControlVariable[] = [], + shouldUpdateAttrs = true ) => { try { const { dataView, columns, rows } = await getGridAttrs( query, adHocDataViews, deps, - abortController + abortController, + esqlVariables ); + const updatedWithVariablesColumns = esqlVariables.length + ? mapVariableToColumn(query.esql, esqlVariables, columns) + : columns; setDataGridAttrs?.({ rows, dataView, - columns, + columns: updatedWithVariablesColumns, }); + if (!shouldUpdateAttrs) { + return; + } + const context = { dataViewSpec: dataView?.toSpec(false), fieldName: '', - textBasedColumns: columns, + textBasedColumns: updatedWithVariablesColumns, query, }; @@ -124,9 +138,15 @@ export const getSuggestions = async ( suggestion: firstSuggestion, dataView, }) as TypedLensSerializedState['attributes']; - return attrs; + return { + ...attrs, + state: { + ...attrs.state, + needsRefresh: false, + }, + }; } catch (e) { - setErrors([e]); + setErrors?.([e]); } return undefined; }; diff --git a/x-pack/platform/plugins/shared/lens/public/app_plugin/shared/edit_on_the_fly/lens_configuration_flyout.tsx b/x-pack/platform/plugins/shared/lens/public/app_plugin/shared/edit_on_the_fly/lens_configuration_flyout.tsx index 8c8693cd7c76d..8bdff81f37142 100644 --- a/x-pack/platform/plugins/shared/lens/public/app_plugin/shared/edit_on_the_fly/lens_configuration_flyout.tsx +++ b/x-pack/platform/plugins/shared/lens/public/app_plugin/shared/edit_on_the_fly/lens_configuration_flyout.tsx @@ -28,6 +28,7 @@ import { getLanguageDisplayName, } from '@kbn/es-query'; import type { AggregateQuery, Query } from '@kbn/es-query'; +import { useStateFromPublishingSubject } from '@kbn/presentation-publishing'; import { ESQLLangEditor } from '@kbn/esql/public'; import { DefaultInspectorAdapters } from '@kbn/expressions-plugin/common'; import type { TypedLensSerializedState } from '../../../react_embeddable/types'; @@ -47,11 +48,13 @@ import { import { LayerConfiguration } from './layer_configuration_section'; import type { EditConfigPanelProps } from './types'; import { FlyoutWrapper } from './flyout_wrapper'; -import { getSuggestions, getGridAttrs, type ESQLDataGridAttrs } from './helpers'; +import { getSuggestions, type ESQLDataGridAttrs } from './helpers'; import { SuggestionPanel } from '../../../editor_frame_service/editor_frame/suggestion_panel'; import { useApplicationUserMessages } from '../../get_application_user_messages'; import { trackSaveUiCounterEvents } from '../../../lens_ui_telemetry'; import { ESQLDataGridAccordion } from './esql_data_grid_accordion'; +import { isApiESQLVariablesCompatible } from '../../../react_embeddable/types'; +import { useESQLVariables } from './use_esql_variables'; export function LensEditConfigurationFlyout({ attributes, @@ -77,12 +80,15 @@ export function LensEditConfigurationFlyout({ onApply: onApplyCallback, onCancel: onCancelCallback, hideTimeFilterInfo, + parentApi, + panelId, }: EditConfigPanelProps) { const euiTheme = useEuiTheme(); const previousAttributes = useRef(attributes); const previousAdapters = useRef | undefined>(lensAdapters); const prevQuery = useRef(attributes.state.query); const [query, setQuery] = useState(attributes.state.query); + const [errors, setErrors] = useState(); const [isInlineFlyoutVisible, setIsInlineFlyoutVisible] = useState(true); const [isLayerAccordionOpen, setIsLayerAccordionOpen] = useState(true); @@ -94,6 +100,17 @@ export function LensEditConfigurationFlyout({ const datasourceState = attributes.state.datasourceStates[datasourceId]; const activeDatasource = datasourceMap[datasourceId]; + const esqlVariables = useStateFromPublishingSubject( + isApiESQLVariablesCompatible(parentApi) ? parentApi?.esqlVariables$ : undefined + ); + + const { onSaveControl, onCancelControl } = useESQLVariables({ + parentApi, + panelId, + attributes, + closeFlyout, + }); + const { datasourceStates, visualization, isLoading, annotationGroups, searchSessionId } = useLensSelector((state) => state.lens); // use the latest activeId, but fallback to attributes @@ -139,27 +156,6 @@ export function LensEditConfigurationFlyout({ return () => s?.unsubscribe(); }, [dispatch, dataLoading$, layers]); - useEffect(() => { - const abortController = new AbortController(); - const getESQLGridAttrs = async () => { - if (!dataGridAttrs && isOfAggregateQueryType(query)) { - const { dataView, columns, rows } = await getGridAttrs( - query, - adHocDataViews, - startDependencies, - abortController - ); - - setDataGridAttrs({ - rows, - dataView, - columns, - }); - } - }; - getESQLGridAttrs(); - }, [adHocDataViews, dataGridAttrs, query, startDependencies]); - const attributesChanged: boolean = useMemo(() => { const previousAttrs = previousAttributes.current; @@ -323,7 +319,7 @@ export function LensEditConfigurationFlyout({ }); const runQuery = useCallback( - async (q: AggregateQuery, abortController?: AbortController) => { + async (q: AggregateQuery, abortController?: AbortController, shouldUpdateAttrs?: boolean) => { const attrs = await getSuggestions( q, startDependencies, @@ -332,7 +328,9 @@ export function LensEditConfigurationFlyout({ adHocDataViews, setErrors, abortController, - setDataGridAttrs + setDataGridAttrs, + esqlVariables, + shouldUpdateAttrs ); if (attrs) { setCurrentAttributes?.(attrs); @@ -349,9 +347,33 @@ export function LensEditConfigurationFlyout({ adHocDataViews, setCurrentAttributes, updateSuggestion, + esqlVariables, ] ); + useEffect(() => { + const abortController = new AbortController(); + const initializeChart = async () => { + if (isOfAggregateQueryType(query) && !dataGridAttrs) { + try { + await runQuery(query, abortController, Boolean(attributes.state.needsRefresh)); + } catch (e) { + setErrors([e]); + prevQuery.current = query; + } + } + }; + initializeChart(); + }, [ + adHocDataViews, + runQuery, + esqlVariables, + query, + startDependencies, + dataGridAttrs, + attributes.state.needsRefresh, + ]); + const isSaveable = useMemo(() => { if (!attributesChanged) { return false; @@ -508,6 +530,7 @@ export function LensEditConfigurationFlyout({ : undefined } editorIsInline + supportsControls hideRunQueryText onTextLangQuerySubmit={async (q, a) => { // do not run the suggestions if the query is the same as the previous one @@ -519,6 +542,9 @@ export function LensEditConfigurationFlyout({ isDisabled={false} allowQueryCancellation isLoading={isVisualizationLoading} + onSaveControl={onSaveControl} + onCancelControl={onCancelControl} + esqlVariables={esqlVariables} /> )} @@ -554,9 +580,8 @@ export function LensEditConfigurationFlyout({
{i18n.translate('xpack.lens.config.visualizationConfigurationLabel', { @@ -601,13 +626,12 @@ export function LensEditConfigurationFlyout({ grow={isSuggestionsAccordionOpen ? 1 : false} data-test-subj="InlineEditingSuggestions" css={css` - border-top: ${euiThemeVars.euiBorderThin}; - border-bottom: ${euiThemeVars.euiBorderThin}; - padding-left: ${euiThemeVars.euiSize}; - padding-right: ${euiThemeVars.euiSize}; - .euiAccordion__childWrapper { - flex: ${isSuggestionsAccordionOpen ? 1 : 'none'} - } + border-top: ${euiThemeVars.euiBorderThin}; + border-bottom: ${euiThemeVars.euiBorderThin}; + padding-left: ${euiThemeVars.euiSize}; + padding-right: ${euiThemeVars.euiSize}; + .euiAccordion__childWrapper { + flex: ${isSuggestionsAccordionOpen ? 1 : 'none'}; } `} > diff --git a/x-pack/platform/plugins/shared/lens/public/app_plugin/shared/edit_on_the_fly/types.ts b/x-pack/platform/plugins/shared/lens/public/app_plugin/shared/edit_on_the_fly/types.ts index d31a518cf80e8..55e51ddac68ac 100644 --- a/x-pack/platform/plugins/shared/lens/public/app_plugin/shared/edit_on_the_fly/types.ts +++ b/x-pack/platform/plugins/shared/lens/public/app_plugin/shared/edit_on_the_fly/types.ts @@ -86,6 +86,8 @@ export interface EditConfigPanelProps { // in cases where the embeddable is not filtered by time // (e.g. through unified search) set this property to true hideTimeFilterInfo?: boolean; + /** The dashboard api, important for creating controls from the ES|QL editor */ + parentApi?: unknown; } export interface LayerConfigurationProps { diff --git a/x-pack/platform/plugins/shared/lens/public/app_plugin/shared/edit_on_the_fly/use_esql_variables.ts b/x-pack/platform/plugins/shared/lens/public/app_plugin/shared/edit_on_the_fly/use_esql_variables.ts new file mode 100644 index 0000000000000..9a1623749adec --- /dev/null +++ b/x-pack/platform/plugins/shared/lens/public/app_plugin/shared/edit_on_the_fly/use_esql_variables.ts @@ -0,0 +1,82 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { useMemo, useCallback } from 'react'; +import { v4 as uuidv4 } from 'uuid'; +import { useStateFromPublishingSubject } from '@kbn/presentation-publishing'; +import { + isApiESQLVariablesCompatible, + TypedLensSerializedState, +} from '../../../react_embeddable/types'; + +export const useESQLVariables = ({ + parentApi, + attributes, + panelId, + closeFlyout, +}: { + parentApi: unknown; + attributes: TypedLensSerializedState['attributes']; + panelId?: string; + closeFlyout?: () => void; +}) => { + const dashboardPanels = useStateFromPublishingSubject( + isApiESQLVariablesCompatible(parentApi) ? parentApi?.children$ : undefined + ); + const controlGroupApi = useStateFromPublishingSubject( + isApiESQLVariablesCompatible(parentApi) ? parentApi?.controlGroupApi$ : undefined + ); + + const panel = useMemo(() => { + if (!panelId) { + return; + } + return dashboardPanels?.[panelId] as { + updateAttributes: (attributes: TypedLensSerializedState['attributes']) => void; + onEdit: () => Promise; + }; + }, [dashboardPanels, panelId]); + + const onSaveControl = useCallback( + async (controlState: Record, updatedQuery: string) => { + if (!panelId) { + return; + } + + // add a new control + controlGroupApi?.addNewPanel({ + panelType: 'esqlControl', + initialState: { + ...controlState, + id: uuidv4(), + }, + }); + if (panel && updatedQuery) { + panel.updateAttributes({ + ...attributes, + state: { + ...attributes.state, + query: { esql: updatedQuery }, + needsRefresh: true, + }, + }); + // open the edit flyout to continue editing + await panel.onEdit(); + } + }, + [attributes, controlGroupApi, panel, panelId] + ); + + const onCancelControl = useCallback(() => { + closeFlyout?.(); + if (panel) { + panel.onEdit(); + } + }, [closeFlyout, panel]); + + return { onSaveControl, onCancelControl }; +}; diff --git a/x-pack/platform/plugins/shared/lens/public/datasources/form_based/layer_settings.tsx b/x-pack/platform/plugins/shared/lens/public/datasources/form_based/layer_settings.tsx index f40b316c8ce78..fecf71f3f2151 100644 --- a/x-pack/platform/plugins/shared/lens/public/datasources/form_based/layer_settings.tsx +++ b/x-pack/platform/plugins/shared/lens/public/datasources/form_based/layer_settings.tsx @@ -17,7 +17,41 @@ import { IgnoreGlobalFilterRowControl } from '../../shared_components/ignore_glo import { trackUiCounterEvents } from '../../lens_ui_telemetry'; import { ExperimentalBadge } from '../../shared_components'; -const samplingValues = [0.00001, 0.0001, 0.001, 0.01, 0.1, 1]; +const samplingValues = [ + { + label: '.001%', + value: 0.00001, + accessibleLabel: i18n.translate( + 'xpack.lens.randomSampling.ui.sliderControl.tickLabels.0.00001', + { + defaultMessage: 'Point zero zero one percent, most performant', + } + ), + }, + { + label: '.01%', + value: 0.0001, + }, + { + label: '.1%', + value: 0.001, + }, + { + label: '1%', + value: 0.01, + }, + { + label: '10%', + value: 0.1, + }, + { + label: '100%', + value: 1, + accessibleLabel: i18n.translate('xpack.lens.randomSampling.ui.sliderControl.tickLabels.1', { + defaultMessage: 'One hundred percent, most accurate', + }), + }, +]; export function LayerSettingsPanel({ state, @@ -26,7 +60,7 @@ export function LayerSettingsPanel({ }: DatasourceLayerSettingsProps) { const isSamplingValueDisabled = !isSamplingValueEnabled(state.layers[layerId]); const currentValue = isSamplingValueDisabled - ? samplingValues[samplingValues.length - 1] + ? samplingValues[samplingValues.length - 1].value : state.layers[layerId].sampling; return ( diff --git a/x-pack/platform/plugins/shared/lens/public/datasources/text_based/components/dimension_editor.tsx b/x-pack/platform/plugins/shared/lens/public/datasources/text_based/components/dimension_editor.tsx index bfaf056f6089d..705d9002b8650 100644 --- a/x-pack/platform/plugins/shared/lens/public/datasources/text_based/components/dimension_editor.tsx +++ b/x-pack/platform/plugins/shared/lens/public/datasources/text_based/components/dimension_editor.tsx @@ -61,9 +61,10 @@ export function TextBasedDimensionEditor(props: TextBasedDimensionEditorProps) { const hasNumberTypeColumns = table.columns?.some(isNumeric); const columns = table.columns.map((col) => { return { - id: col.id, - name: col.name, + id: col.variable ?? col.id, + name: col.variable ? `?${col.variable}` : col.name, meta: col?.meta ?? { type: 'number' }, + variable: col.variable, compatible: props.isMetricDimension && hasNumberTypeColumns ? props.filterOperations({ @@ -127,12 +128,13 @@ export function TextBasedDimensionEditor(props: TextBasedDimensionEditorProps) { existingFields={allColumns ?? []} selectedField={selectedField} onChoose={(choice) => { - const meta = allColumns?.find((f) => f.name === choice.field)?.meta; + const column = allColumns?.find((f) => f.name === choice.field); const newColumn = { columnId: props.columnId, fieldName: choice.field, + meta: column?.meta, + variable: column?.variable, label: choice.field, - meta, }; return props.setState( !selectedField @@ -155,7 +157,12 @@ export function TextBasedDimensionEditor(props: TextBasedDimensionEditorProps) { columns: props.state.layers[props.layerId].columns.map((col) => col.columnId !== props.columnId ? col - : { ...col, fieldName: choice.field, meta } + : { + ...col, + fieldName: choice.field, + meta: column?.meta, + variable: column?.variable, + } ), }, }, diff --git a/x-pack/platform/plugins/shared/lens/public/datasources/text_based/dnd/on_drop.test.ts b/x-pack/platform/plugins/shared/lens/public/datasources/text_based/dnd/on_drop.test.ts index 025a51ff14c51..0e42138f2f3eb 100644 --- a/x-pack/platform/plugins/shared/lens/public/datasources/text_based/dnd/on_drop.test.ts +++ b/x-pack/platform/plugins/shared/lens/public/datasources/text_based/dnd/on_drop.test.ts @@ -23,6 +23,7 @@ describe('onDrop', () => { id: f.columnId, name: f.fieldName, meta: f?.meta, + ...(f.columnId === 'products.base_price' && { variable: 'field' }), } as DatatableColumn; }) ); @@ -130,6 +131,50 @@ describe('onDrop', () => { }) ); }); + it('should add the column when dropping a field controlled by a variable', () => { + const props = { + ...defaultProps, + source: { + field: 'field', + id: 'field', + humanData: { + label: '?field', + }, + }, + target: { + layerId: 'first', + groupId: 'x', + isNewColumn: true, + indexPatternId: '9de9a3c2-ae98-4180-b019-4d208e516b70', + humanData: { + groupLabel: 'Vertical axis', + layerNumber: 1, + position: 1, + label: 'Empty dimension', + nextLabel: '?field', + canDuplicate: false, + }, + columnId: 'empty', + id: 'empty', + }, + dropType: 'field_add' as DropType, + } as unknown as DatasourceDimensionDropHandlerProps; + const expectedColumns = [ + column1, + column2, + column3, + { columnId: 'empty', fieldName: '?field', meta: { type: 'number' }, variable: 'field' }, + ]; + expect(onDrop(props)).toEqual( + expect.objectContaining({ + layers: { + first: expect.objectContaining({ + columns: expectedColumns, + }), + }, + }) + ); + }); it('should replace the column with the field', () => { const props = { ...defaultProps, @@ -157,6 +202,33 @@ describe('onDrop', () => { }) ); }); + it('should replace the column with the field if the field is controlled by a variable', () => { + const props = { + ...defaultProps, + source: { + field: 'field', + id: 'field', + humanData: { + label: '?field', + }, + }, + dropType: 'field_replace' as DropType, + }; + const expectedColumns = [ + column1, + column2, + { columnId: 'columnId3', fieldName: '?field', meta: { type: 'number' }, variable: 'field' }, + ]; + expect(onDrop(props)).toEqual( + expect.objectContaining({ + layers: { + first: expect.objectContaining({ + columns: expectedColumns, + }), + }, + }) + ); + }); it('should duplicate the dimension if dropType is duplicate_compatible', () => { const props = { ...defaultProps, diff --git a/x-pack/platform/plugins/shared/lens/public/datasources/text_based/dnd/on_drop.ts b/x-pack/platform/plugins/shared/lens/public/datasources/text_based/dnd/on_drop.ts index 5dc90cd4b4a21..bc3cea77a429a 100644 --- a/x-pack/platform/plugins/shared/lens/public/datasources/text_based/dnd/on_drop.ts +++ b/x-pack/platform/plugins/shared/lens/public/datasources/text_based/dnd/on_drop.ts @@ -30,12 +30,13 @@ export const onDrop = (props: DatasourceDimensionDropHandlerProps f.columnId === source.id); + const sourceField = allColumns.find((f) => f.columnId === source.id || f.variable === source.id); const targetField = allColumns.find((f) => f.columnId === target.columnId); const newColumn = { columnId: target.columnId, - fieldName: sourceField?.fieldName ?? '', + fieldName: sourceField?.variable ? `?${sourceField.variable}` : sourceField?.fieldName ?? '', meta: sourceField?.meta, + variable: sourceField?.variable, }; let columns: TextBasedLayerColumn[] | undefined; diff --git a/x-pack/platform/plugins/shared/lens/public/datasources/text_based/text_based_languages.tsx b/x-pack/platform/plugins/shared/lens/public/datasources/text_based/text_based_languages.tsx index 6a9471e174e80..2fdcfe4eacee8 100644 --- a/x-pack/platform/plugins/shared/lens/public/datasources/text_based/text_based_languages.tsx +++ b/x-pack/platform/plugins/shared/lens/public/datasources/text_based/text_based_languages.tsx @@ -234,8 +234,9 @@ export function getTextBasedDatasource({ c?.meta?.type ); return { - columnId: c.id, - fieldName: c.name, + columnId: c.variable ?? c.id, + fieldName: c.variable ? `?${c.variable}` : c.name, + variable: c.variable, meta: c.meta, // makes non-number fields to act as metrics, used for datatable suggestions ...(inMetricDimension && { diff --git a/x-pack/platform/plugins/shared/lens/public/datasources/text_based/to_expression.ts b/x-pack/platform/plugins/shared/lens/public/datasources/text_based/to_expression.ts index d1ef206ad5b57..114be587bac0e 100644 --- a/x-pack/platform/plugins/shared/lens/public/datasources/text_based/to_expression.ts +++ b/x-pack/platform/plugins/shared/lens/public/datasources/text_based/to_expression.ts @@ -27,6 +27,7 @@ function getExpressionForLayer( idMapper[col.fieldName].push({ id: col.columnId, label: col.customLabel ? col.label : col.fieldName, + variable: col?.variable, } as OriginalColumn); } else { idMapper = { @@ -35,6 +36,7 @@ function getExpressionForLayer( { id: col.columnId, label: col.customLabel ? col.label : col.fieldName, + variable: col?.variable, } as OriginalColumn, ], }; diff --git a/x-pack/platform/plugins/shared/lens/public/datasources/text_based/types.ts b/x-pack/platform/plugins/shared/lens/public/datasources/text_based/types.ts index 4516a4e46a412..54b37ff1fc117 100644 --- a/x-pack/platform/plugins/shared/lens/public/datasources/text_based/types.ts +++ b/x-pack/platform/plugins/shared/lens/public/datasources/text_based/types.ts @@ -20,6 +20,7 @@ export interface TextBasedLayerColumn { }; meta?: DatatableColumn['meta']; inMetricDimension?: boolean; + variable?: string; } export interface TextBasedField { diff --git a/x-pack/platform/plugins/shared/lens/public/datasources/text_based/utils.test.ts b/x-pack/platform/plugins/shared/lens/public/datasources/text_based/utils.test.ts index 72ee6869e811a..d1bef18be1c61 100644 --- a/x-pack/platform/plugins/shared/lens/public/datasources/text_based/utils.test.ts +++ b/x-pack/platform/plugins/shared/lens/public/datasources/text_based/utils.test.ts @@ -144,6 +144,76 @@ describe('Text based languages utils', () => { }, ]); }); + + it('should maintain the variable info if it exists', async () => { + const existingOnLayer = [ + { + fieldName: 'time', + columnId: 'time', + meta: { + type: 'date', + }, + }, + { + fieldName: 'bytes', + columnId: 'bytes', + meta: { + type: 'number', + }, + }, + ] as TextBasedLayerColumn[]; + const columnsFromQuery = [ + { + name: 'timestamp', + id: 'timestamp', + meta: { + type: 'date', + }, + }, + { + name: 'bytes', + id: 'bytes', + meta: { + type: 'number', + }, + }, + { + name: 'memory', + id: 'memory', + meta: { + type: 'number', + }, + variable: 'field1', + }, + ] as DatatableColumn[]; + const allColumns = getAllColumns(existingOnLayer, columnsFromQuery); + expect(allColumns).toStrictEqual([ + { + fieldName: 'bytes', + columnId: 'bytes', + meta: { + type: 'number', + }, + }, + { + fieldName: 'timestamp', + columnId: 'timestamp', + label: 'timestamp', + meta: { + type: 'date', + }, + }, + { + fieldName: 'memory', + columnId: 'memory', + label: 'memory', + meta: { + type: 'number', + }, + variable: 'field1', + }, + ]); + }); }); describe('getStateFromAggregateQuery', () => { diff --git a/x-pack/platform/plugins/shared/lens/public/datasources/text_based/utils.ts b/x-pack/platform/plugins/shared/lens/public/datasources/text_based/utils.ts index ec8b1cc7645e9..3e375ab419d24 100644 --- a/x-pack/platform/plugins/shared/lens/public/datasources/text_based/utils.ts +++ b/x-pack/platform/plugins/shared/lens/public/datasources/text_based/utils.ts @@ -57,6 +57,7 @@ export const getAllColumns = ( fieldName: c.id, label: c.name, meta: c.meta, + ...(c.variable ? { variable: c.variable } : {}), })), ]; const uniqueIds: string[] = []; diff --git a/x-pack/platform/plugins/shared/lens/public/editor_frame_service/editor_frame/config_panel/chart_switch/chart_switch_popover.tsx b/x-pack/platform/plugins/shared/lens/public/editor_frame_service/editor_frame/config_panel/chart_switch/chart_switch_popover.tsx index bc2fdfbf35813..31ae3257b8301 100644 --- a/x-pack/platform/plugins/shared/lens/public/editor_frame_service/editor_frame/config_panel/chart_switch/chart_switch_popover.tsx +++ b/x-pack/platform/plugins/shared/lens/public/editor_frame_service/editor_frame/config_panel/chart_switch/chart_switch_popover.tsx @@ -38,6 +38,7 @@ export const ChartSwitchPopover = memo(function ChartSwitchPopover( initialFocus=".lnsChartSwitch__popoverPanel" panelClassName="lnsChartSwitch__popoverPanel" panelPaddingSize="none" + repositionOnScroll button={ { + ref?.focus({ preventScroll: true }); + }, className: 'lnsChartSwitch__search', 'data-test-subj': 'lnsChartSwitchSearch', onChange: setSearchTerm, diff --git a/x-pack/platform/plugins/shared/lens/public/editor_frame_service/editor_frame/suggestion_panel.tsx b/x-pack/platform/plugins/shared/lens/public/editor_frame_service/editor_frame/suggestion_panel.tsx index 024dba800011a..989abb55e8ada 100644 --- a/x-pack/platform/plugins/shared/lens/public/editor_frame_service/editor_frame/suggestion_panel.tsx +++ b/x-pack/platform/plugins/shared/lens/public/editor_frame_service/editor_frame/suggestion_panel.tsx @@ -522,9 +522,8 @@ export function SuggestionPanel({

; internalReferences?: SavedObjectReference[]; }; diff --git a/x-pack/platform/plugins/shared/lens/public/react_embeddable/data_loader.ts b/x-pack/platform/plugins/shared/lens/public/react_embeddable/data_loader.ts index 52657cd8b68a8..4bc24c514c534 100644 --- a/x-pack/platform/plugins/shared/lens/public/react_embeddable/data_loader.ts +++ b/x-pack/platform/plugins/shared/lens/public/react_embeddable/data_loader.ts @@ -6,8 +6,10 @@ */ import type { DefaultInspectorAdapters } from '@kbn/expressions-plugin/common'; +import { apiPublishesESQLVariables } from '@kbn/esql-variables-types'; import { apiPublishesUnifiedSearch, fetch$ } from '@kbn/presentation-publishing'; import { type KibanaExecutionContext } from '@kbn/core/public'; +import { ESQLControlVariable } from '@kbn/esql-validation-autocomplete'; import { BehaviorSubject, type Subscription, @@ -18,6 +20,7 @@ import { merge, tap, map, + of, } from 'rxjs'; import fastIsEqual from 'fast-deep-equal'; import { pick } from 'lodash'; @@ -41,6 +44,7 @@ const blockingMessageDisplayLocations: UserMessagesDisplayLocationId[] = [ ]; type ReloadReason = + | 'ESQLvariables' | 'attributes' | 'savedObjectId' | 'overrides' @@ -48,7 +52,7 @@ type ReloadReason = | 'viewMode' | 'searchContext'; -function getSearchContext(parentApi: unknown) { +function getSearchContext(parentApi: unknown, esqlVariables: ESQLControlVariable[] = []) { const unifiedSearch$ = apiPublishesUnifiedSearch(parentApi) ? pick(parentApi, 'filters$', 'query$', 'timeslice$', 'timeRange$') : { @@ -59,6 +63,7 @@ function getSearchContext(parentApi: unknown) { }; return { + esqlVariables, filters: unifiedSearch$.filters$.getValue(), query: unifiedSearch$.query$.getValue(), timeRange: unifiedSearch$.timeRange$.getValue(), @@ -186,9 +191,11 @@ export function loadEmbeddableData( callbacks ); + const esqlVariables = internalApi?.esqlVariables$?.getValue(); + const searchContext = getMergedSearchContext( currentState, - getSearchContext(parentApi), + getSearchContext(parentApi, esqlVariables), api.timeRange$, parentApi, services @@ -249,9 +256,15 @@ export function loadEmbeddableData( return pipe(distinctUntilChanged(fastIsEqual), skip(1)); } + // Read ESQL variables from the parent if it provides them + const esqlVariables$ = apiPublishesESQLVariables(parentApi) + ? parentApi.esqlVariables$ + : of([] as ESQLControlVariable[]); + const mergedSubscriptions = merge( // on search context change, reload fetch$(api).pipe(map(() => 'searchContext' as ReloadReason)), + esqlVariables$.pipe(map(() => 'ESQLvariables' as ReloadReason)), // On state change, reload // this is used to refresh the chart on inline editing // just make sure to avoid to rerender if there's no substantial change diff --git a/x-pack/platform/plugins/shared/lens/public/react_embeddable/expressions/merged_search_context.ts b/x-pack/platform/plugins/shared/lens/public/react_embeddable/expressions/merged_search_context.ts index 5b467dd706a69..5dc59a28eec97 100644 --- a/x-pack/platform/plugins/shared/lens/public/react_embeddable/expressions/merged_search_context.ts +++ b/x-pack/platform/plugins/shared/lens/public/react_embeddable/expressions/merged_search_context.ts @@ -4,7 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ - +import type { ESQLControlVariable } from '@kbn/esql-validation-autocomplete'; import type { DataPublicPluginStart, FilterManager } from '@kbn/data-plugin/public'; import { type AggregateQuery, @@ -24,6 +24,7 @@ export interface MergedSearchContext { query: Array; filters: Filter[]; disableWarningToasts: boolean; + esqlVariables?: ESQLControlVariable[]; } export function getMergedSearchContext( @@ -32,10 +33,12 @@ export function getMergedSearchContext( filters, query, timeRange, + esqlVariables, }: { filters?: Filter[]; query?: Query | AggregateQuery; timeRange?: TimeRange; + esqlVariables?: ESQLControlVariable[]; }, customTimeRange$: PublishingSubject, parentApi: unknown, @@ -60,6 +63,7 @@ export function getMergedSearchContext( const timeRangeToRender = customTimeRange ?? timesliceTimeRange ?? timeRange; const context = { + esqlVariables, now: data.nowProvider.get().getTime(), timeRange: timeRangeToRender, query: [attributes.state.query].filter(nonNullable), diff --git a/x-pack/platform/plugins/shared/lens/public/react_embeddable/initializers/initialize_edit.tsx b/x-pack/platform/plugins/shared/lens/public/react_embeddable/initializers/initialize_edit.tsx index c4e4b547dc70e..a9c00596fbeb5 100644 --- a/x-pack/platform/plugins/shared/lens/public/react_embeddable/initializers/initialize_edit.tsx +++ b/x-pack/platform/plugins/shared/lens/public/react_embeddable/initializers/initialize_edit.tsx @@ -163,7 +163,8 @@ export function initializeEditApi( inspectorApi, startDependencies, navigateToLensEditor, - uuid + uuid, + parentApi ); /** diff --git a/x-pack/platform/plugins/shared/lens/public/react_embeddable/initializers/initialize_internal_api.ts b/x-pack/platform/plugins/shared/lens/public/react_embeddable/initializers/initialize_internal_api.ts index 280fa1a2b6e9c..7b2cb38b36e87 100644 --- a/x-pack/platform/plugins/shared/lens/public/react_embeddable/initializers/initialize_internal_api.ts +++ b/x-pack/platform/plugins/shared/lens/public/react_embeddable/initializers/initialize_internal_api.ts @@ -7,6 +7,7 @@ import { BehaviorSubject } from 'rxjs'; import { initializeTitleManager } from '@kbn/presentation-publishing'; +import { apiPublishesESQLVariables } from '@kbn/esql-variables-types'; import type { DataView } from '@kbn/data-views-plugin/common'; import { buildObservableVariable, createEmptyLensState } from '../helper'; import type { @@ -66,12 +67,17 @@ export function initializeInternalApi( activeData: undefined, }); + const [esqlVariables$] = buildObservableVariable( + apiPublishesESQLVariables(parentApi) ? parentApi.esqlVariables$ : [] + ); + // No need to expose anything at public API right now, that would happen later on // where each initializer will pick what it needs and publish it return { attributes$, overrides$, disableTriggers$, + esqlVariables$, dataLoading$, hasRenderCompleted$, expressionParams$, diff --git a/x-pack/platform/plugins/shared/lens/public/react_embeddable/inline_editing/setup_inline_editing.tsx b/x-pack/platform/plugins/shared/lens/public/react_embeddable/inline_editing/setup_inline_editing.tsx index e37e671132964..c7ef545a546b7 100644 --- a/x-pack/platform/plugins/shared/lens/public/react_embeddable/inline_editing/setup_inline_editing.tsx +++ b/x-pack/platform/plugins/shared/lens/public/react_embeddable/inline_editing/setup_inline_editing.tsx @@ -50,7 +50,8 @@ export function prepareInlineEditPanel( stateTransfer: EmbeddableStateTransfer, skipAppLeave?: boolean ) => () => Promise, - uuid?: string + uuid?: string, + parentApi?: unknown ) { return async function openConfigPanel({ onApply, @@ -137,6 +138,7 @@ export function prepareInlineEditPanel( } }} hideTimeFilterInfo={hideTimeFilterInfo} + parentApi={parentApi} /> ); }; diff --git a/x-pack/platform/plugins/shared/lens/public/react_embeddable/types.ts b/x-pack/platform/plugins/shared/lens/public/react_embeddable/types.ts index 5c9700123962b..8758152a54f0d 100644 --- a/x-pack/platform/plugins/shared/lens/public/react_embeddable/types.ts +++ b/x-pack/platform/plugins/shared/lens/public/react_embeddable/types.ts @@ -13,6 +13,7 @@ import type { TimeRange, } from '@kbn/es-query'; import type { Adapters, InspectorOptions } from '@kbn/inspector-plugin/public'; +import type { ESQLControlVariable } from '@kbn/esql-validation-autocomplete'; import type { HasEditCapabilities, HasLibraryTransforms, @@ -417,6 +418,7 @@ export type LensInternalApi = Simplify< Pick & PublishesDataViews & VisualizationContextHelper & { + esqlVariables$: PublishingSubject; attributes$: PublishingSubject; overrides$: PublishingSubject; disableTriggers$: PublishingSubject; @@ -523,3 +525,24 @@ export type LensByReferenceInput = Omit; export type TypedLensByValueInput = Omit; export type LensEmbeddableInput = LensByValueInput | LensByReferenceInput; export type LensEmbeddableOutput = LensApi; + +export interface ControlGroupApi { + addNewPanel: (panelState: Record) => void; +} + +interface ESQLVariablesCompatibleDashboardApi { + esqlVariables$: PublishingSubject; + controlGroupApi$: PublishingSubject; + children$: PublishingSubject<{ [key: string]: unknown }>; +} + +export const isApiESQLVariablesCompatible = ( + api: unknown | null +): api is ESQLVariablesCompatibleDashboardApi => { + return Boolean( + api && + (api as ESQLVariablesCompatibleDashboardApi)?.esqlVariables$ !== undefined && + (api as ESQLVariablesCompatibleDashboardApi)?.controlGroupApi$ !== undefined && + (api as ESQLVariablesCompatibleDashboardApi)?.children$ !== undefined + ); +}; diff --git a/x-pack/platform/plugins/shared/lens/public/shared_components/dataview_picker/dataview_picker.tsx b/x-pack/platform/plugins/shared/lens/public/shared_components/dataview_picker/dataview_picker.tsx index e1de5e9b6527d..1530fc4885228 100644 --- a/x-pack/platform/plugins/shared/lens/public/shared_components/dataview_picker/dataview_picker.tsx +++ b/x-pack/platform/plugins/shared/lens/public/shared_components/dataview_picker/dataview_picker.tsx @@ -46,6 +46,7 @@ export function ChangeIndexPattern({ panelProps={{ ['data-test-subj']: 'lnsChangeIndexPatternPopover', }} + repositionOnScroll isOpen={isPopoverOpen} closePopover={() => setPopoverIsOpen(false)} display="block" diff --git a/x-pack/platform/plugins/shared/lens/tsconfig.json b/x-pack/platform/plugins/shared/lens/tsconfig.json index c74a55a56ea88..c856a3dff581d 100644 --- a/x-pack/platform/plugins/shared/lens/tsconfig.json +++ b/x-pack/platform/plugins/shared/lens/tsconfig.json @@ -119,6 +119,8 @@ "@kbn/core-chrome-browser", "@kbn/core-capabilities-common", "@kbn/presentation-panel-plugin", + "@kbn/esql-validation-autocomplete", + "@kbn/esql-variables-types", ], "exclude": ["target/**/*"] } diff --git a/x-pack/platform/plugins/shared/maps/common/migrations/set_ems_tms_default_modes.test.ts b/x-pack/platform/plugins/shared/maps/common/migrations/set_ems_tms_default_modes.test.ts index 5aab4e24c8ba6..0549db96d1fda 100644 --- a/x-pack/platform/plugins/shared/maps/common/migrations/set_ems_tms_default_modes.test.ts +++ b/x-pack/platform/plugins/shared/maps/common/migrations/set_ems_tms_default_modes.test.ts @@ -5,6 +5,10 @@ * 2.0. */ +import { + DEFAULT_EMS_ROADMAP_DESATURATED_ID, + DEFAULT_EMS_ROADMAP_ID, +} from '@kbn/maps-ems-plugin/common'; import { setEmsTmsDefaultModes } from './set_ems_tms_default_modes'; describe('setEmsTmsDefaultModes', () => { @@ -31,7 +35,7 @@ describe('setEmsTmsDefaultModes', () => { }; expect(setEmsTmsDefaultModes({ attributes })).toEqual({ title: 'my map', - layerListJSON: '[{"sourceDescriptor":{"type":"EMS_TMS","lightModeDefault":"road_map"}}]', + layerListJSON: `[{"sourceDescriptor":{"type":"EMS_TMS","lightModeDefault":"${DEFAULT_EMS_ROADMAP_ID}"}}]`, }); }); @@ -41,7 +45,7 @@ describe('setEmsTmsDefaultModes', () => { { sourceDescriptor: { type: 'EMS_TMS', - lightModeDefault: 'road_map_desaturated', + lightModeDefault: DEFAULT_EMS_ROADMAP_DESATURATED_ID, }, }, ]); @@ -51,8 +55,7 @@ describe('setEmsTmsDefaultModes', () => { }; expect(setEmsTmsDefaultModes({ attributes })).toEqual({ title: 'my map', - layerListJSON: - '[{"sourceDescriptor":{"type":"EMS_TMS","lightModeDefault":"road_map_desaturated"}}]', + layerListJSON: `[{"sourceDescriptor":{"type":"EMS_TMS","lightModeDefault":"${DEFAULT_EMS_ROADMAP_DESATURATED_ID}"}}]`, }); }); }); diff --git a/x-pack/platform/plugins/shared/maps/common/migrations/set_ems_tms_default_modes.ts b/x-pack/platform/plugins/shared/maps/common/migrations/set_ems_tms_default_modes.ts index e31eb02fbc262..58ff7cbcba49f 100644 --- a/x-pack/platform/plugins/shared/maps/common/migrations/set_ems_tms_default_modes.ts +++ b/x-pack/platform/plugins/shared/maps/common/migrations/set_ems_tms_default_modes.ts @@ -5,6 +5,7 @@ * 2.0. */ +import { DEFAULT_EMS_ROADMAP_ID } from '@kbn/maps-ems-plugin/common'; import { SOURCE_TYPES } from '../constants'; import { LayerDescriptor, EMSTMSSourceDescriptor } from '../descriptor_types'; import type { MapAttributes } from '../content_management'; @@ -34,7 +35,7 @@ export function setEmsTmsDefaultModes({ const sourceDescriptor = layerDescriptor.sourceDescriptor as EMSTMSSourceDescriptor; // auto select bright tiles for EMS_TMS layers created before 8.0.0 if (!sourceDescriptor.lightModeDefault) { - sourceDescriptor.lightModeDefault = 'road_map'; + sourceDescriptor.lightModeDefault = DEFAULT_EMS_ROADMAP_ID; } } }); diff --git a/x-pack/platform/plugins/shared/maps/public/classes/layers/create_basemap_layer_descriptor.test.ts b/x-pack/platform/plugins/shared/maps/public/classes/layers/create_basemap_layer_descriptor.test.ts index 933e3d06c96ae..6f6cf45abb517 100644 --- a/x-pack/platform/plugins/shared/maps/public/classes/layers/create_basemap_layer_descriptor.test.ts +++ b/x-pack/platform/plugins/shared/maps/public/classes/layers/create_basemap_layer_descriptor.test.ts @@ -26,6 +26,11 @@ jest.mock('uuid', () => ({ v4: jest.fn().mockReturnValue('12345'), })); +import { + DEFAULT_EMS_DARKMAP_ID, + DEFAULT_EMS_ROADMAP_DESATURATED_ID, + DEFAULT_EMS_ROADMAP_ID, +} from '@kbn/maps-ems-plugin/common'; import { createBasemapLayerDescriptor } from './create_basemap_layer_descriptor'; describe('kibana.yml configured with map.tilemap.url', () => { @@ -65,9 +70,9 @@ describe('EMS is enabled', () => { }; // eslint-disable-next-line @typescript-eslint/no-var-requires require('../../kibana_services').getEmsTileLayerId = () => ({ - bright: 'road_map', - desaturated: 'road_map_desaturated', - dark: 'dark_map', + bright: DEFAULT_EMS_ROADMAP_ID, + desaturated: DEFAULT_EMS_ROADMAP_DESATURATED_ID, + dark: DEFAULT_EMS_DARKMAP_ID, }); }); @@ -84,7 +89,7 @@ describe('EMS is enabled', () => { sourceDescriptor: { id: undefined, isAutoSelect: true, - lightModeDefault: 'road_map_desaturated', + lightModeDefault: DEFAULT_EMS_ROADMAP_DESATURATED_ID, type: 'EMS_TMS', }, style: { type: 'EMS_VECTOR_TILE', color: '' }, diff --git a/x-pack/platform/plugins/shared/maps/public/classes/sources/ems_tms_source/ems_tms_source.tsx b/x-pack/platform/plugins/shared/maps/public/classes/sources/ems_tms_source/ems_tms_source.tsx index 6b37c604c3a04..83276d64d9402 100644 --- a/x-pack/platform/plugins/shared/maps/public/classes/sources/ems_tms_source/ems_tms_source.tsx +++ b/x-pack/platform/plugins/shared/maps/public/classes/sources/ems_tms_source/ems_tms_source.tsx @@ -7,6 +7,7 @@ import React from 'react'; import { i18n } from '@kbn/i18n'; +import { DEFAULT_EMS_ROADMAP_ID } from '@kbn/maps-ems-plugin/common'; import { AbstractSource, SourceEditorArgs } from '../source'; import { ITMSSource } from '../tms_source'; import { getEmsTmsServices } from '../../../util'; @@ -46,9 +47,10 @@ export class EMSTMSSource extends AbstractSource implements ITMSSource { isAutoSelect: typeof descriptor.isAutoSelect !== 'undefined' ? descriptor.isAutoSelect : false, lightModeDefault: - typeof descriptor.lightModeDefault !== 'undefined' - ? descriptor.lightModeDefault - : getEmsTileLayerId().desaturated, + descriptor.lightModeDefault === undefined || + descriptor.lightModeDefault !== DEFAULT_EMS_ROADMAP_ID + ? getEmsTileLayerId().desaturated + : DEFAULT_EMS_ROADMAP_ID, }; } diff --git a/x-pack/platform/plugins/shared/maps/public/kibana_services.ts b/x-pack/platform/plugins/shared/maps/public/kibana_services.ts index ea31df8734ade..181876de0e77b 100644 --- a/x-pack/platform/plugins/shared/maps/public/kibana_services.ts +++ b/x-pack/platform/plugins/shared/maps/public/kibana_services.ts @@ -9,6 +9,10 @@ import type { CoreStart } from '@kbn/core/public'; import type { EMSSettings } from '@kbn/maps-ems-plugin/common/ems_settings'; import { MapsEmsPluginPublicStart } from '@kbn/maps-ems-plugin/public'; import { BehaviorSubject } from 'rxjs'; +import { + EMS_DARKMAP_BOREALIS_ID, + EMS_ROADMAP_BOREALIS_DESATURATED_ID, +} from '@kbn/maps-ems-plugin/common'; import type { MapsConfigType } from '../server/config'; import type { MapsPluginStartDependencies } from './plugin'; @@ -116,6 +120,17 @@ export const getEMSSettings: () => EMSSettings = () => { return emsSettings; }; -export const getEmsTileLayerId = () => mapsEms.config.emsTileLayerId; +export const getEmsTileLayerId = () => { + // To be updated unce Borealis is the only theme available + if (coreStart.theme.getTheme().name !== 'borealis') { + return mapsEms.config.emsTileLayerId; + } else { + return { + ...mapsEms.config.emsTileLayerId, + dark: EMS_DARKMAP_BOREALIS_ID, + desaturated: EMS_ROADMAP_BOREALIS_DESATURATED_ID, + }; + } +}; export const getShareService = () => pluginsStart.share; diff --git a/x-pack/platform/plugins/shared/maps/server/sample_data/ecommerce_saved_objects.js b/x-pack/platform/plugins/shared/maps/server/sample_data/ecommerce_saved_objects.js index 9169c107100b1..4b527d38838f8 100644 --- a/x-pack/platform/plugins/shared/maps/server/sample_data/ecommerce_saved_objects.js +++ b/x-pack/platform/plugins/shared/maps/server/sample_data/ecommerce_saved_objects.js @@ -7,6 +7,7 @@ import { i18n } from '@kbn/i18n'; import { emsWorldLayerId } from '../../common/constants'; +import { DEFAULT_EMS_ROADMAP_DESATURATED_ID } from '@kbn/maps-ems-plugin/common'; const layerList = [ { @@ -15,7 +16,7 @@ const layerList = [ sourceDescriptor: { type: 'EMS_TMS', isAutoSelect: true, - lightModeDefault: 'road_map_desaturated', + lightModeDefault: DEFAULT_EMS_ROADMAP_DESATURATED_ID, }, visible: true, style: {}, diff --git a/x-pack/platform/plugins/shared/maps/server/sample_data/flights_saved_objects.js b/x-pack/platform/plugins/shared/maps/server/sample_data/flights_saved_objects.js index 645eb0a90e560..3f8808ccad73a 100644 --- a/x-pack/platform/plugins/shared/maps/server/sample_data/flights_saved_objects.js +++ b/x-pack/platform/plugins/shared/maps/server/sample_data/flights_saved_objects.js @@ -6,6 +6,7 @@ */ import { i18n } from '@kbn/i18n'; +import { DEFAULT_EMS_ROADMAP_DESATURATED_ID } from '@kbn/maps-ems-plugin/common'; const layerList = [ { @@ -14,7 +15,7 @@ const layerList = [ sourceDescriptor: { type: 'EMS_TMS', isAutoSelect: true, - lightModeDefault: 'road_map_desaturated', + lightModeDefault: DEFAULT_EMS_ROADMAP_DESATURATED_ID, }, visible: true, style: {}, diff --git a/x-pack/platform/plugins/shared/maps/server/sample_data/web_logs_saved_objects.js b/x-pack/platform/plugins/shared/maps/server/sample_data/web_logs_saved_objects.js index 07724e3dfd072..57cb21e700a4d 100644 --- a/x-pack/platform/plugins/shared/maps/server/sample_data/web_logs_saved_objects.js +++ b/x-pack/platform/plugins/shared/maps/server/sample_data/web_logs_saved_objects.js @@ -7,6 +7,7 @@ import { i18n } from '@kbn/i18n'; import { emsWorldLayerId } from '../../common/constants'; +import { DEFAULT_EMS_ROADMAP_DESATURATED_ID } from '@kbn/maps-ems-plugin/common'; const layerList = [ { @@ -15,7 +16,7 @@ const layerList = [ sourceDescriptor: { type: 'EMS_TMS', isAutoSelect: true, - lightModeDefault: 'road_map_desaturated', + lightModeDefault: DEFAULT_EMS_ROADMAP_DESATURATED_ID, }, visible: true, style: {}, diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/.storybook/jest_setup.js b/x-pack/platform/plugins/shared/observability_ai_assistant/.storybook/jest_setup.js similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/.storybook/jest_setup.js rename to x-pack/platform/plugins/shared/observability_ai_assistant/.storybook/jest_setup.js diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/.storybook/main.js b/x-pack/platform/plugins/shared/observability_ai_assistant/.storybook/main.js similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/.storybook/main.js rename to x-pack/platform/plugins/shared/observability_ai_assistant/.storybook/main.js diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/.storybook/preview.js b/x-pack/platform/plugins/shared/observability_ai_assistant/.storybook/preview.js similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/.storybook/preview.js rename to x-pack/platform/plugins/shared/observability_ai_assistant/.storybook/preview.js diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/README.md b/x-pack/platform/plugins/shared/observability_ai_assistant/README.md similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/README.md rename to x-pack/platform/plugins/shared/observability_ai_assistant/README.md diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/TRACING.md b/x-pack/platform/plugins/shared/observability_ai_assistant/TRACING.md similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/TRACING.md rename to x-pack/platform/plugins/shared/observability_ai_assistant/TRACING.md diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/common/capabilities.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/common/capabilities.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/common/capabilities.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/common/capabilities.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/common/conversation_complete.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/common/conversation_complete.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/common/conversation_complete.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/common/conversation_complete.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/common/convert_messages_for_inference.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/common/convert_messages_for_inference.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/common/convert_messages_for_inference.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/common/convert_messages_for_inference.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/common/feature.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/common/feature.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/common/feature.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/common/feature.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/common/functions/function_visibility.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/common/functions/function_visibility.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/common/functions/function_visibility.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/common/functions/function_visibility.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/common/functions/types.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/common/functions/types.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/common/functions/types.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/common/functions/types.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/common/functions/visualize_esql.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/common/functions/visualize_esql.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/common/functions/visualize_esql.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/common/functions/visualize_esql.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/common/index.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/common/index.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/common/index.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/common/index.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/common/rule_connector.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/common/rule_connector.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/common/rule_connector.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/common/rule_connector.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/common/types.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/common/types.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/common/types.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/common/types.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/common/ui_settings/settings_keys.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/common/ui_settings/settings_keys.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/common/ui_settings/settings_keys.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/common/ui_settings/settings_keys.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/common/utils/concatenate_chat_completion_chunks.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/common/utils/concatenate_chat_completion_chunks.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/common/utils/concatenate_chat_completion_chunks.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/common/utils/concatenate_chat_completion_chunks.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/common/utils/create_function_request_message.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/common/utils/create_function_request_message.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/common/utils/create_function_request_message.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/common/utils/create_function_request_message.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/common/utils/create_function_response_message.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/common/utils/create_function_response_message.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/common/utils/create_function_response_message.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/common/utils/create_function_response_message.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/common/utils/emit_with_concatenated_message.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/common/utils/emit_with_concatenated_message.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/common/utils/emit_with_concatenated_message.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/common/utils/emit_with_concatenated_message.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/common/utils/filter_function_definitions.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/common/utils/filter_function_definitions.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/common/utils/filter_function_definitions.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/common/utils/filter_function_definitions.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/common/utils/get_bucket_size/calculate_auto.js b/x-pack/platform/plugins/shared/observability_ai_assistant/common/utils/get_bucket_size/calculate_auto.js similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/common/utils/get_bucket_size/calculate_auto.js rename to x-pack/platform/plugins/shared/observability_ai_assistant/common/utils/get_bucket_size/calculate_auto.js diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/common/utils/get_bucket_size/index.test.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/common/utils/get_bucket_size/index.test.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/common/utils/get_bucket_size/index.test.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/common/utils/get_bucket_size/index.test.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/common/utils/get_bucket_size/index.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/common/utils/get_bucket_size/index.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/common/utils/get_bucket_size/index.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/common/utils/get_bucket_size/index.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/common/utils/get_bucket_size/unit_to_seconds.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/common/utils/get_bucket_size/unit_to_seconds.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/common/utils/get_bucket_size/unit_to_seconds.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/common/utils/get_bucket_size/unit_to_seconds.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/common/utils/short_id_table.test.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/common/utils/short_id_table.test.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/common/utils/short_id_table.test.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/common/utils/short_id_table.test.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/common/utils/short_id_table.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/common/utils/short_id_table.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/common/utils/short_id_table.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/common/utils/short_id_table.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/common/utils/throw_serialized_chat_completion_errors.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/common/utils/throw_serialized_chat_completion_errors.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/common/utils/throw_serialized_chat_completion_errors.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/common/utils/throw_serialized_chat_completion_errors.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/common/utils/until_aborted.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/common/utils/until_aborted.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/common/utils/until_aborted.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/common/utils/until_aborted.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/common/utils/with_token_budget.test.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/common/utils/with_token_budget.test.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/common/utils/with_token_budget.test.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/common/utils/with_token_budget.test.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/common/utils/with_token_budget.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/common/utils/with_token_budget.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/common/utils/with_token_budget.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/common/utils/with_token_budget.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/common/utils/without_token_count_events.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/common/utils/without_token_count_events.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/common/utils/without_token_count_events.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/common/utils/without_token_count_events.ts diff --git a/x-pack/platform/plugins/shared/observability_ai_assistant/jest.config.js b/x-pack/platform/plugins/shared/observability_ai_assistant/jest.config.js new file mode 100644 index 0000000000000..6450d281b38a7 --- /dev/null +++ b/x-pack/platform/plugins/shared/observability_ai_assistant/jest.config.js @@ -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. + */ + +module.exports = { + preset: '@kbn/test', + rootDir: '../../../../..', + roots: [ + '/x-pack/platform/plugins/shared/observability_ai_assistant/public', + '/x-pack/platform/plugins/shared/observability_ai_assistant/common', + '/x-pack/platform/plugins/shared/observability_ai_assistant/server', + ], + setupFiles: [ + '/x-pack/platform/plugins/shared/observability_ai_assistant/.storybook/jest_setup.js', + ], + collectCoverage: true, + collectCoverageFrom: [ + '/x-pack/platform/plugins/shared/observability_ai_assistant/{common,public,server}/**/*.{js,ts,tsx}', + ], + + coverageReporters: ['html'], +}; diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/kibana.jsonc b/x-pack/platform/plugins/shared/observability_ai_assistant/kibana.jsonc similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/kibana.jsonc rename to x-pack/platform/plugins/shared/observability_ai_assistant/kibana.jsonc diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/analytics/index.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/public/analytics/index.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/analytics/index.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/public/analytics/index.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/analytics/schemas/chat_feedback.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/public/analytics/schemas/chat_feedback.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/analytics/schemas/chat_feedback.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/public/analytics/schemas/chat_feedback.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/analytics/schemas/common.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/public/analytics/schemas/common.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/analytics/schemas/common.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/public/analytics/schemas/common.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/analytics/schemas/insight_feedback.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/public/analytics/schemas/insight_feedback.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/analytics/schemas/insight_feedback.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/public/analytics/schemas/insight_feedback.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/analytics/schemas/insight_response.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/public/analytics/schemas/insight_response.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/analytics/schemas/insight_response.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/public/analytics/schemas/insight_response.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/analytics/schemas/user_sent_prompt.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/public/analytics/schemas/user_sent_prompt.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/analytics/schemas/user_sent_prompt.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/public/analytics/schemas/user_sent_prompt.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/analytics/telemetry_event_type.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/public/analytics/telemetry_event_type.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/analytics/telemetry_event_type.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/public/analytics/telemetry_event_type.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/api/index.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/public/api/index.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/api/index.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/public/api/index.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/assets/elastic_ai_assistant.png b/x-pack/platform/plugins/shared/observability_ai_assistant/public/assets/elastic_ai_assistant.png similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/assets/elastic_ai_assistant.png rename to x-pack/platform/plugins/shared/observability_ai_assistant/public/assets/elastic_ai_assistant.png diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/assets/illustration.png b/x-pack/platform/plugins/shared/observability_ai_assistant/public/assets/illustration.png similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/assets/illustration.png rename to x-pack/platform/plugins/shared/observability_ai_assistant/public/assets/illustration.png diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/assets/illustration.svg b/x-pack/platform/plugins/shared/observability_ai_assistant/public/assets/illustration.svg similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/assets/illustration.svg rename to x-pack/platform/plugins/shared/observability_ai_assistant/public/assets/illustration.svg diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/components/buttons/feedback_buttons.tsx b/x-pack/platform/plugins/shared/observability_ai_assistant/public/components/buttons/feedback_buttons.tsx similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/components/buttons/feedback_buttons.tsx rename to x-pack/platform/plugins/shared/observability_ai_assistant/public/components/buttons/feedback_buttons.tsx diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/components/buttons/regenerate_response_button.stories.tsx b/x-pack/platform/plugins/shared/observability_ai_assistant/public/components/buttons/regenerate_response_button.stories.tsx similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/components/buttons/regenerate_response_button.stories.tsx rename to x-pack/platform/plugins/shared/observability_ai_assistant/public/components/buttons/regenerate_response_button.stories.tsx diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/components/buttons/regenerate_response_button.tsx b/x-pack/platform/plugins/shared/observability_ai_assistant/public/components/buttons/regenerate_response_button.tsx similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/components/buttons/regenerate_response_button.tsx rename to x-pack/platform/plugins/shared/observability_ai_assistant/public/components/buttons/regenerate_response_button.tsx diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/components/buttons/start_chat_button.stories.tsx b/x-pack/platform/plugins/shared/observability_ai_assistant/public/components/buttons/start_chat_button.stories.tsx similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/components/buttons/start_chat_button.stories.tsx rename to x-pack/platform/plugins/shared/observability_ai_assistant/public/components/buttons/start_chat_button.stories.tsx diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/components/buttons/start_chat_button.tsx b/x-pack/platform/plugins/shared/observability_ai_assistant/public/components/buttons/start_chat_button.tsx similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/components/buttons/start_chat_button.tsx rename to x-pack/platform/plugins/shared/observability_ai_assistant/public/components/buttons/start_chat_button.tsx diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/components/buttons/stop_generating_button.stories.tsx b/x-pack/platform/plugins/shared/observability_ai_assistant/public/components/buttons/stop_generating_button.stories.tsx similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/components/buttons/stop_generating_button.stories.tsx rename to x-pack/platform/plugins/shared/observability_ai_assistant/public/components/buttons/stop_generating_button.stories.tsx diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/components/buttons/stop_generating_button.tsx b/x-pack/platform/plugins/shared/observability_ai_assistant/public/components/buttons/stop_generating_button.tsx similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/components/buttons/stop_generating_button.tsx rename to x-pack/platform/plugins/shared/observability_ai_assistant/public/components/buttons/stop_generating_button.tsx diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/components/chat/chat_item_controls.tsx b/x-pack/platform/plugins/shared/observability_ai_assistant/public/components/chat/chat_item_controls.tsx similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/components/chat/chat_item_controls.tsx rename to x-pack/platform/plugins/shared/observability_ai_assistant/public/components/chat/chat_item_controls.tsx diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/components/chat/types.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/public/components/chat/types.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/components/chat/types.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/public/components/chat/types.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/components/connector_selector/connector_selector_base.stories.tsx b/x-pack/platform/plugins/shared/observability_ai_assistant/public/components/connector_selector/connector_selector_base.stories.tsx similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/components/connector_selector/connector_selector_base.stories.tsx rename to x-pack/platform/plugins/shared/observability_ai_assistant/public/components/connector_selector/connector_selector_base.stories.tsx diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/components/connector_selector/connector_selector_base.tsx b/x-pack/platform/plugins/shared/observability_ai_assistant/public/components/connector_selector/connector_selector_base.tsx similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/components/connector_selector/connector_selector_base.tsx rename to x-pack/platform/plugins/shared/observability_ai_assistant/public/components/connector_selector/connector_selector_base.tsx diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/components/insight/actions_menu.tsx b/x-pack/platform/plugins/shared/observability_ai_assistant/public/components/insight/actions_menu.tsx similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/components/insight/actions_menu.tsx rename to x-pack/platform/plugins/shared/observability_ai_assistant/public/components/insight/actions_menu.tsx diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/components/insight/insight.tsx b/x-pack/platform/plugins/shared/observability_ai_assistant/public/components/insight/insight.tsx similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/components/insight/insight.tsx rename to x-pack/platform/plugins/shared/observability_ai_assistant/public/components/insight/insight.tsx diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/components/insight/insight_base.stories.tsx b/x-pack/platform/plugins/shared/observability_ai_assistant/public/components/insight/insight_base.stories.tsx similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/components/insight/insight_base.stories.tsx rename to x-pack/platform/plugins/shared/observability_ai_assistant/public/components/insight/insight_base.stories.tsx diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/components/insight/insight_base.tsx b/x-pack/platform/plugins/shared/observability_ai_assistant/public/components/insight/insight_base.tsx similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/components/insight/insight_base.tsx rename to x-pack/platform/plugins/shared/observability_ai_assistant/public/components/insight/insight_base.tsx diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/components/insight/insight_error.tsx b/x-pack/platform/plugins/shared/observability_ai_assistant/public/components/insight/insight_error.tsx similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/components/insight/insight_error.tsx rename to x-pack/platform/plugins/shared/observability_ai_assistant/public/components/insight/insight_error.tsx diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/components/message_panel/esql_code_block.stories.tsx b/x-pack/platform/plugins/shared/observability_ai_assistant/public/components/message_panel/esql_code_block.stories.tsx similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/components/message_panel/esql_code_block.stories.tsx rename to x-pack/platform/plugins/shared/observability_ai_assistant/public/components/message_panel/esql_code_block.stories.tsx diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/components/message_panel/esql_code_block.tsx b/x-pack/platform/plugins/shared/observability_ai_assistant/public/components/message_panel/esql_code_block.tsx similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/components/message_panel/esql_code_block.tsx rename to x-pack/platform/plugins/shared/observability_ai_assistant/public/components/message_panel/esql_code_block.tsx diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/components/message_panel/failed_to_load_response.tsx b/x-pack/platform/plugins/shared/observability_ai_assistant/public/components/message_panel/failed_to_load_response.tsx similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/components/message_panel/failed_to_load_response.tsx rename to x-pack/platform/plugins/shared/observability_ai_assistant/public/components/message_panel/failed_to_load_response.tsx diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/components/message_panel/message_panel.stories.tsx b/x-pack/platform/plugins/shared/observability_ai_assistant/public/components/message_panel/message_panel.stories.tsx similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/components/message_panel/message_panel.stories.tsx rename to x-pack/platform/plugins/shared/observability_ai_assistant/public/components/message_panel/message_panel.stories.tsx diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/components/message_panel/message_panel.tsx b/x-pack/platform/plugins/shared/observability_ai_assistant/public/components/message_panel/message_panel.tsx similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/components/message_panel/message_panel.tsx rename to x-pack/platform/plugins/shared/observability_ai_assistant/public/components/message_panel/message_panel.tsx diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/components/message_panel/message_text.tsx b/x-pack/platform/plugins/shared/observability_ai_assistant/public/components/message_panel/message_text.tsx similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/components/message_panel/message_text.tsx rename to x-pack/platform/plugins/shared/observability_ai_assistant/public/components/message_panel/message_text.tsx diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/components/missing_credentials_callout.tsx b/x-pack/platform/plugins/shared/observability_ai_assistant/public/components/missing_credentials_callout.tsx similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/components/missing_credentials_callout.tsx rename to x-pack/platform/plugins/shared/observability_ai_assistant/public/components/missing_credentials_callout.tsx diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/context/observability_ai_assistant_chat_service_context.tsx b/x-pack/platform/plugins/shared/observability_ai_assistant/public/context/observability_ai_assistant_chat_service_context.tsx similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/context/observability_ai_assistant_chat_service_context.tsx rename to x-pack/platform/plugins/shared/observability_ai_assistant/public/context/observability_ai_assistant_chat_service_context.tsx diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/context/observability_ai_assistant_multipane_flyout_context.tsx b/x-pack/platform/plugins/shared/observability_ai_assistant/public/context/observability_ai_assistant_multipane_flyout_context.tsx similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/context/observability_ai_assistant_multipane_flyout_context.tsx rename to x-pack/platform/plugins/shared/observability_ai_assistant/public/context/observability_ai_assistant_multipane_flyout_context.tsx diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/context/observability_ai_assistant_provider.tsx b/x-pack/platform/plugins/shared/observability_ai_assistant/public/context/observability_ai_assistant_provider.tsx similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/context/observability_ai_assistant_provider.tsx rename to x-pack/platform/plugins/shared/observability_ai_assistant/public/context/observability_ai_assistant_provider.tsx diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/hooks/use_abortable_async.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/public/hooks/use_abortable_async.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/hooks/use_abortable_async.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/public/hooks/use_abortable_async.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/hooks/use_chat.test.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/public/hooks/use_chat.test.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/hooks/use_chat.test.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/public/hooks/use_chat.test.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/hooks/use_chat.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/public/hooks/use_chat.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/hooks/use_chat.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/public/hooks/use_chat.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/hooks/use_flyout_state.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/public/hooks/use_flyout_state.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/hooks/use_flyout_state.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/public/hooks/use_flyout_state.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/hooks/use_genai_connectors.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/public/hooks/use_genai_connectors.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/hooks/use_genai_connectors.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/public/hooks/use_genai_connectors.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/hooks/use_kibana.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/public/hooks/use_kibana.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/hooks/use_kibana.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/public/hooks/use_kibana.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/hooks/use_observability_ai_assistant.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/public/hooks/use_observability_ai_assistant.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/hooks/use_observability_ai_assistant.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/public/hooks/use_observability_ai_assistant.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/hooks/use_observability_ai_assistant_chat_service.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/public/hooks/use_observability_ai_assistant_chat_service.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/hooks/use_observability_ai_assistant_chat_service.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/public/hooks/use_observability_ai_assistant_chat_service.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/hooks/use_once.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/public/hooks/use_once.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/hooks/use_once.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/public/hooks/use_once.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/index.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/public/index.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/index.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/public/index.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/mock.tsx b/x-pack/platform/plugins/shared/observability_ai_assistant/public/mock.tsx similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/mock.tsx rename to x-pack/platform/plugins/shared/observability_ai_assistant/public/mock.tsx diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/plugin.tsx b/x-pack/platform/plugins/shared/observability_ai_assistant/public/plugin.tsx similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/plugin.tsx rename to x-pack/platform/plugins/shared/observability_ai_assistant/public/plugin.tsx diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/service/complete.test.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/public/service/complete.test.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/service/complete.test.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/public/service/complete.test.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/service/complete.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/public/service/complete.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/service/complete.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/public/service/complete.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/service/create_chat_service.test.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/public/service/create_chat_service.test.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/service/create_chat_service.test.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/public/service/create_chat_service.test.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/service/create_chat_service.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/public/service/create_chat_service.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/service/create_chat_service.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/public/service/create_chat_service.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/service/create_mock_chat_service.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/public/service/create_mock_chat_service.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/service/create_mock_chat_service.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/public/service/create_mock_chat_service.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/service/create_service.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/public/service/create_service.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/service/create_service.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/public/service/create_service.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/service/default_starter_prompts.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/public/service/default_starter_prompts.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/service/default_starter_prompts.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/public/service/default_starter_prompts.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/storybook_mock.tsx b/x-pack/platform/plugins/shared/observability_ai_assistant/public/storybook_mock.tsx similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/storybook_mock.tsx rename to x-pack/platform/plugins/shared/observability_ai_assistant/public/storybook_mock.tsx diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/types.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/public/types.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/types.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/public/types.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/utils/builders.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/public/utils/builders.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/utils/builders.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/public/utils/builders.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/utils/create_function_response_error.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/public/utils/create_function_response_error.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/utils/create_function_response_error.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/public/utils/create_function_response_error.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/utils/create_screen_context_action.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/public/utils/create_screen_context_action.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/utils/create_screen_context_action.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/public/utils/create_screen_context_action.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/utils/get_connectors_management_href.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/public/utils/get_connectors_management_href.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/utils/get_connectors_management_href.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/public/utils/get_connectors_management_href.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/utils/get_contextual_insight_messages.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/public/utils/get_contextual_insight_messages.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/utils/get_contextual_insight_messages.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/public/utils/get_contextual_insight_messages.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/utils/get_models_management_href.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/public/utils/get_models_management_href.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/utils/get_models_management_href.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/public/utils/get_models_management_href.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/utils/readable_stream_reader_into_observable.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/public/utils/readable_stream_reader_into_observable.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/utils/readable_stream_reader_into_observable.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/public/utils/readable_stream_reader_into_observable.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/utils/storybook_decorator.tsx b/x-pack/platform/plugins/shared/observability_ai_assistant/public/utils/storybook_decorator.tsx similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public/utils/storybook_decorator.tsx rename to x-pack/platform/plugins/shared/observability_ai_assistant/public/utils/storybook_decorator.tsx diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/analytics/recall_ranking.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/server/analytics/recall_ranking.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/analytics/recall_ranking.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/server/analytics/recall_ranking.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/config.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/server/config.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/config.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/server/config.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/functions/context.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/server/functions/context.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/functions/context.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/server/functions/context.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/functions/elasticsearch.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/server/functions/elasticsearch.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/functions/elasticsearch.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/server/functions/elasticsearch.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/functions/execute_connector.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/server/functions/execute_connector.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/functions/execute_connector.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/server/functions/execute_connector.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/functions/get_dataset_info/get_relevant_field_names.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/server/functions/get_dataset_info/get_relevant_field_names.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/functions/get_dataset_info/get_relevant_field_names.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/server/functions/get_dataset_info/get_relevant_field_names.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/functions/get_dataset_info/index.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/server/functions/get_dataset_info/index.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/functions/get_dataset_info/index.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/server/functions/get_dataset_info/index.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/functions/index.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/server/functions/index.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/functions/index.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/server/functions/index.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/functions/kibana.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/server/functions/kibana.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/functions/kibana.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/server/functions/kibana.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/functions/summarize.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/server/functions/summarize.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/functions/summarize.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/server/functions/summarize.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/index.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/server/index.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/index.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/server/index.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/plugin.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/server/plugin.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/plugin.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/server/plugin.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/routes/chat/route.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/server/routes/chat/route.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/routes/chat/route.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/server/routes/chat/route.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/routes/connectors/route.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/server/routes/connectors/route.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/routes/connectors/route.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/server/routes/connectors/route.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/routes/conversations/route.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/server/routes/conversations/route.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/routes/conversations/route.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/server/routes/conversations/route.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/routes/create_observability_ai_assistant_server_route.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/server/routes/create_observability_ai_assistant_server_route.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/routes/create_observability_ai_assistant_server_route.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/server/routes/create_observability_ai_assistant_server_route.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/routes/functions/route.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/server/routes/functions/route.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/routes/functions/route.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/server/routes/functions/route.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/routes/get_global_observability_ai_assistant_route_repository.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/server/routes/get_global_observability_ai_assistant_route_repository.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/routes/get_global_observability_ai_assistant_route_repository.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/server/routes/get_global_observability_ai_assistant_route_repository.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/routes/knowledge_base/route.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/server/routes/knowledge_base/route.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/routes/knowledge_base/route.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/server/routes/knowledge_base/route.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/routes/register_routes.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/server/routes/register_routes.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/routes/register_routes.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/server/routes/register_routes.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/routes/runtime_types.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/server/routes/runtime_types.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/routes/runtime_types.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/server/routes/runtime_types.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/routes/types.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/server/routes/types.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/routes/types.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/server/routes/types.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/chat_function_client/index.test.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/chat_function_client/index.test.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/chat_function_client/index.test.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/server/service/chat_function_client/index.test.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/chat_function_client/index.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/chat_function_client/index.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/chat_function_client/index.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/server/service/chat_function_client/index.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/client/get_context_function_request_if_needed.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/client/get_context_function_request_if_needed.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/client/get_context_function_request_if_needed.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/server/service/client/get_context_function_request_if_needed.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/client/index.test.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/client/index.test.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/client/index.test.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/server/service/client/index.test.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/client/index.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/client/index.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/client/index.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/server/service/client/index.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/client/instrumentation/get_langtrace_span_attributes.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/client/instrumentation/get_langtrace_span_attributes.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/client/instrumentation/get_langtrace_span_attributes.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/server/service/client/instrumentation/get_langtrace_span_attributes.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/client/instrumentation/get_langtrace_tracer.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/client/instrumentation/get_langtrace_tracer.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/client/instrumentation/get_langtrace_tracer.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/server/service/client/instrumentation/get_langtrace_tracer.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/client/instrumentation/init_langtrace.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/client/instrumentation/init_langtrace.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/client/instrumentation/init_langtrace.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/server/service/client/instrumentation/init_langtrace.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/client/instrumentation/lang_tracer.test.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/client/instrumentation/lang_tracer.test.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/client/instrumentation/lang_tracer.test.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/server/service/client/instrumentation/lang_tracer.test.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/client/instrumentation/lang_tracer.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/client/instrumentation/lang_tracer.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/client/instrumentation/lang_tracer.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/server/service/client/instrumentation/lang_tracer.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/client/operators/catch_function_not_found_error.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/client/operators/catch_function_not_found_error.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/client/operators/catch_function_not_found_error.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/server/service/client/operators/catch_function_not_found_error.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/client/operators/continue_conversation.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/client/operators/continue_conversation.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/client/operators/continue_conversation.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/server/service/client/operators/continue_conversation.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/client/operators/convert_inference_events_to_streaming_events.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/client/operators/convert_inference_events_to_streaming_events.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/client/operators/convert_inference_events_to_streaming_events.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/server/service/client/operators/convert_inference_events_to_streaming_events.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/client/operators/debug.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/client/operators/debug.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/client/operators/debug.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/server/service/client/operators/debug.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/client/operators/extract_messages.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/client/operators/extract_messages.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/client/operators/extract_messages.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/server/service/client/operators/extract_messages.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/client/operators/extract_token_count.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/client/operators/extract_token_count.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/client/operators/extract_token_count.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/server/service/client/operators/extract_token_count.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/client/operators/fail_on_non_existing_function_call.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/client/operators/fail_on_non_existing_function_call.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/client/operators/fail_on_non_existing_function_call.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/server/service/client/operators/fail_on_non_existing_function_call.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/client/operators/get_generated_title.test.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/client/operators/get_generated_title.test.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/client/operators/get_generated_title.test.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/server/service/client/operators/get_generated_title.test.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/client/operators/get_generated_title.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/client/operators/get_generated_title.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/client/operators/get_generated_title.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/server/service/client/operators/get_generated_title.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/client/operators/hide_token_count_events.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/client/operators/hide_token_count_events.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/client/operators/hide_token_count_events.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/server/service/client/operators/hide_token_count_events.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/client/operators/instrument_and_count_tokens.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/client/operators/instrument_and_count_tokens.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/client/operators/instrument_and_count_tokens.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/server/service/client/operators/instrument_and_count_tokens.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/conversation_component_template.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/conversation_component_template.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/conversation_component_template.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/server/service/conversation_component_template.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/index.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/index.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/index.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/server/service/index.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/inference_endpoint.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/inference_endpoint.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/inference_endpoint.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/server/service/inference_endpoint.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/kb_component_template.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/kb_component_template.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/kb_component_template.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/server/service/kb_component_template.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/knowledge_base_service/get_elser_model_id.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/knowledge_base_service/get_elser_model_id.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/knowledge_base_service/get_elser_model_id.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/server/service/knowledge_base_service/get_elser_model_id.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/knowledge_base_service/index.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/knowledge_base_service/index.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/knowledge_base_service/index.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/server/service/knowledge_base_service/index.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/knowledge_base_service/recall_from_search_connectors.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/knowledge_base_service/recall_from_search_connectors.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/knowledge_base_service/recall_from_search_connectors.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/server/service/knowledge_base_service/recall_from_search_connectors.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/setup_conversation_and_kb_index_assets.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/setup_conversation_and_kb_index_assets.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/setup_conversation_and_kb_index_assets.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/server/service/setup_conversation_and_kb_index_assets.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/task_manager_definitions/register_migrate_knowledge_base_entries_task.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/task_manager_definitions/register_migrate_knowledge_base_entries_task.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/task_manager_definitions/register_migrate_knowledge_base_entries_task.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/server/service/task_manager_definitions/register_migrate_knowledge_base_entries_task.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/types.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/types.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/types.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/server/service/types.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/util/catch_function_limit_exceeded_error.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/util/catch_function_limit_exceeded_error.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/util/catch_function_limit_exceeded_error.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/server/service/util/catch_function_limit_exceeded_error.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/util/create_server_side_function_response_error.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/util/create_server_side_function_response_error.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/util/create_server_side_function_response_error.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/server/service/util/create_server_side_function_response_error.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/util/flush_buffer.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/util/flush_buffer.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/util/flush_buffer.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/server/service/util/flush_buffer.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/util/get_access_query.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/util/get_access_query.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/util/get_access_query.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/server/service/util/get_access_query.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/util/get_category_query.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/util/get_category_query.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/util/get_category_query.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/server/service/util/get_category_query.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/util/get_system_message_from_instructions.test.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/util/get_system_message_from_instructions.test.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/util/get_system_message_from_instructions.test.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/server/service/util/get_system_message_from_instructions.test.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/util/get_system_message_from_instructions.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/util/get_system_message_from_instructions.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/util/get_system_message_from_instructions.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/server/service/util/get_system_message_from_instructions.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/util/observable_into_openai_stream.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/util/observable_into_openai_stream.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/util/observable_into_openai_stream.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/server/service/util/observable_into_openai_stream.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/util/observable_into_stream.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/util/observable_into_stream.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/util/observable_into_stream.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/server/service/util/observable_into_stream.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/util/replace_system_message.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/util/replace_system_message.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/util/replace_system_message.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/server/service/util/replace_system_message.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/util/stream_into_observable.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/util/stream_into_observable.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/util/stream_into_observable.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/server/service/util/stream_into_observable.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/util/with_assistant_span.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/util/with_assistant_span.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/service/util/with_assistant_span.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/server/service/util/with_assistant_span.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/types.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/server/types.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/types.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/server/types.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/utils/recall/parse_suggestion_scores.test.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/server/utils/recall/parse_suggestion_scores.test.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/utils/recall/parse_suggestion_scores.test.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/server/utils/recall/parse_suggestion_scores.test.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/utils/recall/parse_suggestion_scores.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/server/utils/recall/parse_suggestion_scores.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/utils/recall/parse_suggestion_scores.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/server/utils/recall/parse_suggestion_scores.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/utils/recall/recall_and_score.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/server/utils/recall/recall_and_score.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/utils/recall/recall_and_score.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/server/utils/recall/recall_and_score.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/utils/recall/score_suggestions.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/server/utils/recall/score_suggestions.ts similarity index 100% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server/utils/recall/score_suggestions.ts rename to x-pack/platform/plugins/shared/observability_ai_assistant/server/utils/recall/score_suggestions.ts diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/tsconfig.json b/x-pack/platform/plugins/shared/observability_ai_assistant/tsconfig.json similarity index 94% rename from x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/tsconfig.json rename to x-pack/platform/plugins/shared/observability_ai_assistant/tsconfig.json index 1f484e645912c..823bc57019294 100644 --- a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/tsconfig.json +++ b/x-pack/platform/plugins/shared/observability_ai_assistant/tsconfig.json @@ -1,10 +1,10 @@ { - "extends": "../../../../../../tsconfig.base.json", + "extends": "../../../../../tsconfig.base.json", "compilerOptions": { "outDir": "target/types" }, "include": [ - "../../../../../typings/**/*", + "../../../../typings/**/*", "common/**/*", "public/**/*", "scripts/**/*", diff --git a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/jest.config.js b/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/jest.config.js deleted file mode 100644 index 4ff20cb91d531..0000000000000 --- a/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/jest.config.js +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -module.exports = { - preset: '@kbn/test', - rootDir: '../../../../../..', - roots: [ - '/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/public', - '/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/common', - '/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/server', - ], - setupFiles: [ - '/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/.storybook/jest_setup.js', - ], - collectCoverage: true, - collectCoverageFrom: [ - '/x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant/{common,public,server}/**/*.{js,ts,tsx}', - ], - - coverageReporters: ['html'], -}; diff --git a/x-pack/platform/plugins/shared/task_manager/server/integration_tests/removed_types.test.ts b/x-pack/platform/plugins/shared/task_manager/server/integration_tests/removed_types.test.ts index 390c426e9c69f..96d25eb80feea 100644 --- a/x-pack/platform/plugins/shared/task_manager/server/integration_tests/removed_types.test.ts +++ b/x-pack/platform/plugins/shared/task_manager/server/integration_tests/removed_types.test.ts @@ -28,8 +28,7 @@ jest.mock('../monitoring/workload_statistics', () => { }; }); -// FLAKY: https://github.com/elastic/kibana/issues/194208 -describe.skip('unrecognized task types', () => { +describe('unrecognized task types', () => { let esServer: TestElasticsearchUtils; let kibanaServer: TestKibanaUtils; let taskManagerPlugin: TaskManagerStartContract; @@ -113,6 +112,10 @@ describe.skip('unrecognized task types', () => { taskIdsToRemove.push(removeTypeId); taskIdsToRemove.push(notRegisteredTypeId); + // To be sure that the background task that marks removed tasks as unrecognized has run after the tasks were created + const runSoonResponse = await taskManagerPlugin.runSoon('mark_removed_tasks_as_unrecognized'); + expect(runSoonResponse).toEqual({ id: 'mark_removed_tasks_as_unrecognized' }); + await retry(async () => { const task = await getTask(kibanaServer.coreStart.elasticsearch.client.asInternalUser); expect(task?._source?.task?.status).toBe('unrecognized'); diff --git a/x-pack/solutions/observability/plugins/infra/server/saved_objects/inventory_view/inventory_view_saved_object.test.ts b/x-pack/solutions/observability/plugins/infra/server/saved_objects/inventory_view/inventory_view_saved_object.test.ts new file mode 100644 index 0000000000000..af29eb91b5f8e --- /dev/null +++ b/x-pack/solutions/observability/plugins/infra/server/saved_objects/inventory_view/inventory_view_saved_object.test.ts @@ -0,0 +1,61 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import { + createModelVersionTestMigrator, + type ModelVersionTestMigrator, +} from '@kbn/core-test-helpers-model-versions'; + +import { inventoryViewSavedObjectType } from './inventory_view_saved_object'; + +describe('invetoryViewSavedObject model version transformation', () => { + let migrator: ModelVersionTestMigrator; + beforeEach(() => { + migrator = createModelVersionTestMigrator({ type: inventoryViewSavedObjectType }); + }); + + describe('model veresion 2', () => { + const inventoryViewV2 = { + id: 'someId', + type: 'inventory-view', + attributes: { + metric: { type: 'cpu' }, + sort: { by: 'name', direction: 'desc' }, + groupBy: [], + nodeType: 'host', + view: 'map', + customOptions: [], + customMetrics: [], + boundsOverride: { min: 0, max: 1 }, + autoBounds: true, + accountId: '', + region: '', + autoReload: false, + filterQuery: { expression: '', kind: 'kuery' }, + legend: { palette: 'cool', reverseColors: false, steps: 18 }, + timelineOpen: false, + name: 'test', + }, + references: [], + }; + + it('should clamp legend.steps to 18 when converting from v1 to v2', () => { + const inventoryViewV1 = JSON.parse(JSON.stringify(inventoryViewV2)); + inventoryViewV1.attributes.legend.steps = 20; + const migrated = migrator.migrate({ + document: { + ...inventoryViewV1, + attributes: { + ...inventoryViewV1.attributes, + }, + }, + fromVersion: 1, + toVersion: 2, + }); + expect(migrated.attributes).toEqual(inventoryViewV2.attributes); + }); + }); +}); diff --git a/x-pack/solutions/observability/plugins/infra/server/saved_objects/inventory_view/inventory_view_saved_object.ts b/x-pack/solutions/observability/plugins/infra/server/saved_objects/inventory_view/inventory_view_saved_object.ts index f9c4c4d354024..5cbe9a876e222 100644 --- a/x-pack/solutions/observability/plugins/infra/server/saved_objects/inventory_view/inventory_view_saved_object.ts +++ b/x-pack/solutions/observability/plugins/infra/server/saved_objects/inventory_view/inventory_view_saved_object.ts @@ -5,6 +5,7 @@ * 2.0. */ +import { schema } from '@kbn/config-schema'; import { fold } from 'fp-ts/lib/Either'; import { pipe } from 'fp-ts/lib/pipeable'; import type { SavedObject, SavedObjectsType } from '@kbn/core/server'; @@ -21,6 +22,11 @@ const getInventoryViewTitle = (savedObject: SavedObject) => ) ); +const schemaV1 = schema.object({}, { unknowns: 'allow' }); +const schemaV2 = schema.object({ + legend: schema.object({ steps: schema.number({ max: 18, min: 2 }) }), +}); + export const inventoryViewSavedObjectType: SavedObjectsType = { name: inventoryViewSavedObjectName, hidden: false, @@ -36,4 +42,31 @@ export const inventoryViewSavedObjectType: SavedObjectsType = { dynamic: false, properties: {}, }, + modelVersions: { + 1: { + changes: [], + schemas: { + create: schemaV1, + }, + }, + 2: { + changes: [ + { + type: 'unsafe_transform', + transformFn: (document) => { + if (document.attributes.legend.steps > 18) { + document.attributes.legend.steps = 18; + } else if (document.attributes.legend.steps < 2) { + document.attributes.legend.steps = 2; + } + return { document }; + }, + }, + ], + schemas: { + forwardCompatibility: schemaV2.extends({}, { unknowns: 'ignore' }), + create: schemaV2, + }, + }, + }, }; diff --git a/x-pack/solutions/observability/plugins/infra/tsconfig.json b/x-pack/solutions/observability/plugins/infra/tsconfig.json index 41dbf66ffe78f..78b37f62b9f40 100644 --- a/x-pack/solutions/observability/plugins/infra/tsconfig.json +++ b/x-pack/solutions/observability/plugins/infra/tsconfig.json @@ -115,7 +115,8 @@ "@kbn/config", "@kbn/observability-utils-common", "@kbn/charts-theme", - "@kbn/response-ops-rule-params" + "@kbn/response-ops-rule-params", + "@kbn/core-test-helpers-model-versions" ], "exclude": ["target/**/*"] } diff --git a/x-pack/solutions/observability/plugins/investigate_app/.storybook/mock_kibana_services.ts b/x-pack/solutions/observability/plugins/investigate_app/.storybook/mock_kibana_services.ts index e6a6589ca660f..3cdf520ca648f 100644 --- a/x-pack/solutions/observability/plugins/investigate_app/.storybook/mock_kibana_services.ts +++ b/x-pack/solutions/observability/plugins/investigate_app/.storybook/mock_kibana_services.ts @@ -8,6 +8,7 @@ import { setKibanaServices } from '@kbn/esql/public/kibana_services'; import { coreMock } from '@kbn/core/public/mocks'; import { dataViewPluginMocks } from '@kbn/data-views-plugin/public/mocks'; import { expressionsPluginMock } from '@kbn/expressions-plugin/public/mocks'; +import { uiActionsPluginMock } from '@kbn/ui-actions-plugin/public/mocks'; import type { Storage } from '@kbn/kibana-utils-plugin/public'; class LocalStorageMock { @@ -34,9 +35,18 @@ const storage = new LocalStorageMock({}) as unknown as Storage; setKibanaServices( { getJoinIndicesAutocomplete: async () => ({ indices: [] }), + variablesService: { + esqlVariables: [], + areSuggestionsEnabled: false, + enableSuggestions: () => undefined, + disableSuggestions: () => undefined, + clearVariables: () => undefined, + addVariable: () => undefined, + }, }, coreMock.createStart(), dataViewPluginMocks.createStartContract(), expressionsPluginMock.createStartContract(), - storage + storage, + uiActionsPluginMock.createStartContract() ); diff --git a/x-pack/solutions/observability/plugins/observability/public/application/index.tsx b/x-pack/solutions/observability/plugins/observability/public/application/index.tsx index 54b8b4044e64e..e19e729f39053 100644 --- a/x-pack/solutions/observability/plugins/observability/public/application/index.tsx +++ b/x-pack/solutions/observability/plugins/observability/public/application/index.tsx @@ -8,6 +8,7 @@ import React from 'react'; import ReactDOM from 'react-dom'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; +import { PerformanceContextProvider } from '@kbn/ebt-tools'; import { i18n } from '@kbn/i18n'; import { Router, Routes, Route } from '@kbn/shared-ux-router'; import { AppMountParameters, APP_WRAPPER_CLASS, CoreStart } from '@kbn/core/public'; @@ -111,10 +112,12 @@ export const renderApp = ({ - - - - + + + + + + diff --git a/x-pack/solutions/observability/plugins/observability/public/pages/alert_details/alert_details.test.tsx b/x-pack/solutions/observability/plugins/observability/public/pages/alert_details/alert_details.test.tsx index be62ae6377bc6..17b13cc6f140f 100644 --- a/x-pack/solutions/observability/plugins/observability/public/pages/alert_details/alert_details.test.tsx +++ b/x-pack/solutions/observability/plugins/observability/public/pages/alert_details/alert_details.test.tsx @@ -6,6 +6,7 @@ */ import { casesPluginMock } from '@kbn/cases-plugin/public/mocks'; +import { usePerformanceContext } from '@kbn/ebt-tools'; import { __IntlProvider as IntlProvider } from '@kbn/i18n-react'; import * as useUiSettingHook from '@kbn/kibana-react-plugin/public/ui_settings/use_ui_setting'; import { observabilityAIAssistantPluginMock } from '@kbn/observability-ai-assistant-plugin/public/mock'; @@ -61,6 +62,7 @@ const mockKibana = () => { basePath: { prepend: jest.fn(), }, + get: jest.fn().mockReturnValue({ alertContext: [] }), }, observabilityAIAssistant: mockObservabilityAIAssistant, theme: {}, @@ -82,7 +84,9 @@ jest.mock('../../hooks/use_fetch_rule', () => { }; }); jest.mock('@kbn/observability-shared-plugin/public'); +jest.mock('@kbn/ebt-tools'); +const usePerformanceContextMock = usePerformanceContext as jest.Mock; const useFetchAlertDetailMock = useFetchAlertDetail as jest.Mock; const useParamsMock = useParams as jest.Mock; const useLocationMock = useLocation as jest.Mock; @@ -90,8 +94,9 @@ const useHistoryMock = useHistory as jest.Mock; const useBreadcrumbsMock = useBreadcrumbs as jest.Mock; const TagsListMock = TagsList as jest.Mock; -const chance = new Chance(); +usePerformanceContextMock.mockReturnValue({ onPageReady: jest.fn() }); +const chance = new Chance(); const params = { alertId: chance.guid(), }; diff --git a/x-pack/solutions/observability/plugins/observability/public/pages/alert_details/alert_details.tsx b/x-pack/solutions/observability/plugins/observability/public/pages/alert_details/alert_details.tsx index 9403090b1e213..6b9a5cb3480a9 100644 --- a/x-pack/solutions/observability/plugins/observability/public/pages/alert_details/alert_details.tsx +++ b/x-pack/solutions/observability/plugins/observability/public/pages/alert_details/alert_details.tsx @@ -7,6 +7,7 @@ import React, { useEffect, useState } from 'react'; import { useHistory, useLocation, useParams } from 'react-router-dom'; +import { usePerformanceContext } from '@kbn/ebt-tools'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; import { @@ -95,6 +96,7 @@ export function AlertDetails() { uiSettings, serverless, } = useKibana().services; + const { onPageReady } = usePerformanceContext(); const { search } = useLocation(); const history = useHistory(); @@ -181,6 +183,12 @@ export function AlertDetails() { setAlertStatus(ALERT_STATUS_UNTRACKED); }; + useEffect(() => { + if (!isLoading && !!alertDetail && activeTabId === OVERVIEW_TAB_ID) { + onPageReady(); + } + }, [onPageReady, alertDetail, isLoading, activeTabId]); + if (isLoading) { return ; } diff --git a/x-pack/solutions/observability/plugins/observability/public/pages/alerts/alerts.test.tsx b/x-pack/solutions/observability/plugins/observability/public/pages/alerts/alerts.test.tsx index 33dc64f35ee31..0b5b57c6b5362 100644 --- a/x-pack/solutions/observability/plugins/observability/public/pages/alerts/alerts.test.tsx +++ b/x-pack/solutions/observability/plugins/observability/public/pages/alerts/alerts.test.tsx @@ -5,6 +5,7 @@ * 2.0. */ +import { usePerformanceContext } from '@kbn/ebt-tools'; import { EuiThemeProvider as ThemeProvider } from '@elastic/eui'; import { MAINTENANCE_WINDOW_FEATURE_ID } from '@kbn/alerting-plugin/common/maintenance_window'; import { fetchActiveMaintenanceWindows } from '@kbn/alerts-ui-shared/src/maintenance_window_callout/api'; @@ -21,6 +22,7 @@ import { useLocation } from 'react-router-dom'; import * as dataContext from '../../hooks/use_has_data'; import * as pluginContext from '../../hooks/use_plugin_context'; import { ObservabilityPublicPluginsStart } from '../../plugin'; +import { useGetAvailableRulesWithDescriptions } from '../../hooks/use_get_available_rules_with_descriptions'; import { createObservabilityRuleTypeRegistryMock } from '../../rules/observability_rule_type_registry_mock'; import { kibanaStartMock } from '../../utils/kibana_react.mock'; import { AlertsPage } from './alerts'; @@ -54,6 +56,11 @@ jest.mock('../../utils/kibana_react', () => ({ const useLocationMock = useLocation as jest.Mock; +jest.mock('@kbn/ebt-tools'); + +const usePerformanceContextMock = usePerformanceContext as jest.Mock; +usePerformanceContextMock.mockReturnValue({ onPageReady: jest.fn() }); + jest.mock('@kbn/kibana-react-plugin/public', () => ({ __esModule: true, useKibana: jest.fn(() => mockUseKibanaReturnValue), @@ -110,6 +117,18 @@ jest.mock('../../hooks/use_has_data', () => ({ const { useTimeBuckets } = jest.requireMock('../../hooks/use_time_buckets'); const { useHasData } = jest.requireMock('../../hooks/use_has_data'); +jest.mock('../../hooks/use_get_available_rules_with_descriptions'); + +const ruleDescriptions = [ + { + id: 'observability.rules.custom_threshold', + name: 'Custom threshold', + description: 'Alert when any Observability data type reaches or exceeds a given value.', + }, +]; +const useGetAvailableRulesWithDescriptionsMock = useGetAvailableRulesWithDescriptions as jest.Mock; +useGetAvailableRulesWithDescriptionsMock.mockReturnValue(ruleDescriptions); + const queryClient = new QueryClient({ defaultOptions: { queries: { diff --git a/x-pack/solutions/observability/plugins/observability/public/pages/alerts/alerts.tsx b/x-pack/solutions/observability/plugins/observability/public/pages/alerts/alerts.tsx index 64013c1762f1a..4fe112028d57c 100644 --- a/x-pack/solutions/observability/plugins/observability/public/pages/alerts/alerts.tsx +++ b/x-pack/solutions/observability/plugins/observability/public/pages/alerts/alerts.tsx @@ -9,8 +9,10 @@ import React, { useEffect, useMemo, useState } from 'react'; import { BrushEndListener, XYBrushEvent } from '@elastic/charts'; import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import { BoolQuery, Filter } from '@kbn/es-query'; +import { usePerformanceContext } from '@kbn/ebt-tools'; import { i18n } from '@kbn/i18n'; import { loadRuleAggregations } from '@kbn/triggers-actions-ui-plugin/public'; +import type { TableUpdateHandlerArgs } from '@kbn/triggers-actions-ui-plugin/public/types'; import { useBreadcrumbs } from '@kbn/observability-shared-plugin/public'; import { MaintenanceWindowCallout } from '@kbn/alerts-ui-shared'; import { DEFAULT_APP_CATEGORIES } from '@kbn/core-application-common'; @@ -77,6 +79,7 @@ function InternalAlertsPage() { }, uiSettings, } = kibanaServices; + const { onPageReady } = usePerformanceContext(); const { toasts } = notifications; const { query: { @@ -94,6 +97,21 @@ function InternalAlertsPage() { const ruleTypesWithDescriptions = useGetAvailableRulesWithDescriptions(); + const onUpdate = ({ isLoading, totalCount }: TableUpdateHandlerArgs) => { + if (!isLoading) { + onPageReady({ + customMetrics: { + key1: 'total_alert_count', + value1: totalCount, + }, + meta: { + rangeFrom: alertSearchBarStateProps.rangeFrom, + rangeTo: alertSearchBarStateProps.rangeTo, + }, + }); + } + }; + useEffect(() => { return setScreenContext?.({ data: ruleTypesWithDescriptions.map((rule) => ({ @@ -299,6 +317,7 @@ function InternalAlertsPage() { initialPageSize={ALERTS_PER_PAGE} cellContext={{ observabilityRuleTypeRegistry }} alertsTableConfigurationRegistry={alertsTableConfigurationRegistry} + onUpdate={onUpdate} /> ); }} diff --git a/x-pack/solutions/observability/plugins/observability/tsconfig.json b/x-pack/solutions/observability/plugins/observability/tsconfig.json index 0d8d34ed76377..d78e468013be7 100644 --- a/x-pack/solutions/observability/plugins/observability/tsconfig.json +++ b/x-pack/solutions/observability/plugins/observability/tsconfig.json @@ -113,7 +113,8 @@ "@kbn/logging-mocks", "@kbn/response-ops-rule-form", "@kbn/streams-plugin", - "@kbn/data-service" + "@kbn/data-service", + "@kbn/ebt-tools" ], "exclude": ["target/**/*"] } diff --git a/x-pack/solutions/observability/plugins/observability_onboarding/common/telemetry_events.ts b/x-pack/solutions/observability/plugins/observability_onboarding/common/telemetry_events.ts index ca84d0a6f0379..26b5aefbad5c2 100644 --- a/x-pack/solutions/observability/plugins/observability_onboarding/common/telemetry_events.ts +++ b/x-pack/solutions/observability/plugins/observability_onboarding/common/telemetry_events.ts @@ -7,19 +7,23 @@ import type { EventTypeOpts, SchemaValue } from '@elastic/ebt/client'; -interface ObservabilityOnboardingIntegrationTelemetryFields { - installSource: string; - pkgName: string; - pkgVersion: string; - title: string; -} - interface FlowEventFields { - flow?: string; - step?: string; - step_status?: string; + flow_type: string; + flow_id: string; + step: string; + step_status: string; step_message?: string; - uses_legacy_onboarding_page: boolean; + payload?: { + integrations?: Array<{ + installSource: string; + pkgName: string; + pkgVersion: string; + title: string; + }>; + agentId?: string; + os?: string; + arch?: string; + }; } type ObservabilityOnboardingTelemetryEvent = EventTypeOpts; @@ -27,26 +31,29 @@ type ObservabilityOnboardingTelemetryEvent = EventTypeOpts; export const OBSERVABILITY_ONBOARDING_TELEMETRY_EVENT: ObservabilityOnboardingTelemetryEvent = { eventType: 'observability_onboarding', schema: { - flow: { + flow_type: { type: 'keyword', _meta: { description: - "The current onboarding flow user is going through (e.g. 'system_logs', 'nginx'). If not present, user is on the landing screen.", - optional: true, + "The current onboarding flow type user is going through (e.g. 'autoDetect', 'logFiles', 'kubernetes'). If not present, user is on the landing screen.", + }, + }, + flow_id: { + type: 'keyword', + _meta: { + description: 'Unique identifier of the current onboarding session', }, }, step: { type: 'keyword', _meta: { description: 'The current step in the onboarding flow.', - optional: true, }, }, step_status: { type: 'keyword', _meta: { description: 'The status of the step in the onboarding flow.', - optional: true, }, }, step_message: { @@ -56,10 +63,62 @@ export const OBSERVABILITY_ONBOARDING_TELEMETRY_EVENT: ObservabilityOnboardingTe optional: true, }, }, - uses_legacy_onboarding_page: { - type: 'boolean', + payload: { + properties: { + integrations: { + type: 'array', + items: { + properties: { + installSource: { + type: 'keyword', + _meta: { + description: + 'The source of the package used to create the integration. Usually "registry" or "custom".', + }, + }, + pkgName: { + type: 'keyword', + _meta: { + description: 'The name of the package used to create the integration.', + }, + }, + pkgVersion: { + type: 'keyword', + _meta: { + description: 'The version of the package used to create the integration.', + }, + }, + title: { type: 'keyword', _meta: { description: 'The visual name of the package.' } }, + }, + }, + _meta: { + optional: true, + }, + }, + agentId: { + type: 'keyword', + _meta: { + description: 'The ID of the Elastic Agent installed on the host.', + optional: true, + }, + }, + os: { + type: 'keyword', + _meta: { + description: 'OS used by the host.', + optional: true, + }, + }, + arch: { + type: 'keyword', + _meta: { + description: 'Architecture used by the host.', + optional: true, + }, + }, + }, _meta: { - description: 'Whether the user is using the legacy onboarding page or the new one', + optional: true, }, }, }, @@ -87,48 +146,6 @@ export const OBSERVABILITY_ONBOARDING_FEEDBACK_TELEMETRY_EVENT: EventTypeOpts<{ }, }; -type ObservabilityOnboardingAutodetectTelemetryEvent = EventTypeOpts< - FlowEventFields & { - integrations?: ObservabilityOnboardingIntegrationTelemetryFields[]; - } ->; - -export const OBSERVABILITY_ONBOARDING_AUTODETECT_TELEMETRY_EVENT: ObservabilityOnboardingAutodetectTelemetryEvent = - { - eventType: 'observability_onboarding_autodetect', - schema: { - ...OBSERVABILITY_ONBOARDING_TELEMETRY_EVENT.schema, - integrations: { - type: 'array', - items: { - properties: { - installSource: { - type: 'keyword', - _meta: { - description: - 'The source of the package used to create the integration. Usually "registry" or "custom".', - }, - }, - pkgName: { - type: 'keyword', - _meta: { - description: 'The name of the package used to create the integration.', - }, - }, - pkgVersion: { - type: 'keyword', - _meta: { description: 'The version of the package used to create the integration.' }, - }, - title: { type: 'keyword', _meta: { description: 'The visual name of the package.' } }, - }, - }, - _meta: { - optional: true, - }, - }, - }, - }; - interface OnboardingFirehoseFlowEventContext { selectedCreateStackOption?: string; cloudServiceProvider?: string; diff --git a/x-pack/solutions/observability/plugins/observability_onboarding/public/application/app.tsx b/x-pack/solutions/observability/plugins/observability_onboarding/public/application/app.tsx index 688d4cc3ce9bb..c2163bda2f2da 100644 --- a/x-pack/solutions/observability/plugins/observability_onboarding/public/application/app.tsx +++ b/x-pack/solutions/observability/plugins/observability_onboarding/public/application/app.tsx @@ -15,7 +15,6 @@ import { RedirectAppLinks } from '@kbn/shared-ux-link-redirect-app'; import { Router } from '@kbn/shared-ux-router'; import React from 'react'; import ReactDOM from 'react-dom'; -import { OBSERVABILITY_ONBOARDING_TELEMETRY_EVENT } from '../../common/telemetry_events'; import { AppContext, ConfigSchema, ObservabilityOnboardingAppServices } from '..'; import { ObservabilityOnboardingHeaderActionMenu } from './shared/header_action_menu'; import { @@ -53,10 +52,6 @@ export function ObservabilityOnboardingAppRoot({ context, }; - core.analytics.reportEvent(OBSERVABILITY_ONBOARDING_TELEMETRY_EVENT.eventType, { - uses_legacy_onboarding_page: false, - }); - return (
diff --git a/x-pack/solutions/observability/plugins/observability_onboarding/public/application/quickstart_flows/auto_detect/auto_detect_panel.tsx b/x-pack/solutions/observability/plugins/observability_onboarding/public/application/quickstart_flows/auto_detect/auto_detect_panel.tsx index 47282ba9b8d69..6b5fc0e4eaf17 100644 --- a/x-pack/solutions/observability/plugins/observability_onboarding/public/application/quickstart_flows/auto_detect/auto_detect_panel.tsx +++ b/x-pack/solutions/observability/plugins/observability_onboarding/public/application/quickstart_flows/auto_detect/auto_detect_panel.tsx @@ -32,7 +32,6 @@ import { GetStartedPanel } from '../shared/get_started_panel'; import { isSupportedLogo, LogoIcon } from '../../shared/logo_icon'; import { FeedbackButtons } from '../shared/feedback_buttons'; import { ObservabilityOnboardingContextValue } from '../../../plugin'; -import { useAutoDetectTelemetry } from './use_auto_detect_telemetry'; import { SupportedIntegrationsList } from './supported_integrations_list'; export const AutoDetectPanel: FunctionComponent = () => { @@ -43,16 +42,6 @@ export const AutoDetectPanel: FunctionComponent = () => { services: { share }, } = useKibana(); - useAutoDetectTelemetry( - status, - installedIntegrations.map(({ title, pkgName, pkgVersion, installSource }) => ({ - title, - pkgName, - pkgVersion, - installSource, - })) - ); - if (error) { return ; } diff --git a/x-pack/solutions/observability/plugins/observability_onboarding/public/application/quickstart_flows/auto_detect/use_auto_detect_telemetry.test.ts b/x-pack/solutions/observability/plugins/observability_onboarding/public/application/quickstart_flows/auto_detect/use_auto_detect_telemetry.test.ts deleted file mode 100644 index f77db3b8aad3d..0000000000000 --- a/x-pack/solutions/observability/plugins/observability_onboarding/public/application/quickstart_flows/auto_detect/use_auto_detect_telemetry.test.ts +++ /dev/null @@ -1,115 +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 { renderHook } from '@testing-library/react'; -import { useKibana } from '@kbn/kibana-react-plugin/public'; -import { useAutoDetectTelemetry } from './use_auto_detect_telemetry'; -import { ObservabilityOnboardingFlowStatus } from './get_onboarding_status'; -import { OBSERVABILITY_ONBOARDING_AUTODETECT_TELEMETRY_EVENT } from '../../../../common/telemetry_events'; - -jest.mock('@kbn/kibana-react-plugin/public', () => ({ - useKibana: jest.fn(), -})); - -describe('useAutoDetectTelemetry', () => { - let reportEventMock: any; - - beforeEach(() => { - reportEventMock = jest.fn(); - (useKibana as jest.Mock).mockReturnValue({ - services: { - analytics: { - reportEvent: reportEventMock, - }, - }, - }); - }); - - afterEach(() => { - jest.clearAllMocks(); - }); - - it(`should report "awaiting_data" event when status is "awaitingData"`, () => { - const expectedIntegration = { - installSource: 'source1', - pkgName: 'pkgName1', - pkgVersion: 'pkgVersion1', - title: 'title', - }; - renderHook(() => useAutoDetectTelemetry('awaitingData', [expectedIntegration])); - - expect(reportEventMock).toHaveBeenCalledWith( - OBSERVABILITY_ONBOARDING_AUTODETECT_TELEMETRY_EVENT.eventType, - { - uses_legacy_onboarding_page: false, - flow: 'auto_detect', - step: 'awaiting_data', - integrations: [expectedIntegration], - } - ); - }); - - it(`should report "data_shipped" event when status is "dataReceived"`, () => { - const expectedIntegration = { - installSource: 'source2', - pkgName: 'pkgName2', - pkgVersion: 'pkgVersion2', - title: 'title2', - }; - renderHook(() => useAutoDetectTelemetry('dataReceived', [expectedIntegration])); - - // The effect runs after initial render - expect(reportEventMock).toHaveBeenCalledWith( - OBSERVABILITY_ONBOARDING_AUTODETECT_TELEMETRY_EVENT.eventType, - { - uses_legacy_onboarding_page: false, - flow: 'auto_detect', - step: 'data_shipped', - integrations: [expectedIntegration], - } - ); - }); - - it('should not report the same event more than once', () => { - const expectedIntegration = { - installSource: 'source1', - pkgName: 'pkgName1', - pkgVersion: 'pkgVersion1', - title: 'title', - }; - const { rerender } = renderHook( - ({ status }: { status: ObservabilityOnboardingFlowStatus }) => - useAutoDetectTelemetry(status, [expectedIntegration]), - { initialProps: { status: 'awaitingData' } } - ); - - expect(reportEventMock).toHaveBeenCalledWith( - OBSERVABILITY_ONBOARDING_AUTODETECT_TELEMETRY_EVENT.eventType, - { - uses_legacy_onboarding_page: false, - flow: 'auto_detect', - step: 'awaiting_data', - integrations: [expectedIntegration], - } - ); - - rerender({ status: 'awaitingData' }); - expect(reportEventMock).toHaveBeenCalledTimes(1); - - rerender({ status: 'dataReceived' }); - expect(reportEventMock).toHaveBeenCalledWith( - OBSERVABILITY_ONBOARDING_AUTODETECT_TELEMETRY_EVENT.eventType, - { - uses_legacy_onboarding_page: false, - flow: 'auto_detect', - step: 'data_shipped', - integrations: [expectedIntegration], - } - ); - expect(reportEventMock).toHaveBeenCalledTimes(2); - }); -}); diff --git a/x-pack/solutions/observability/plugins/observability_onboarding/public/application/quickstart_flows/auto_detect/use_auto_detect_telemetry.ts b/x-pack/solutions/observability/plugins/observability_onboarding/public/application/quickstart_flows/auto_detect/use_auto_detect_telemetry.ts deleted file mode 100644 index 8fb4df118ebaf..0000000000000 --- a/x-pack/solutions/observability/plugins/observability_onboarding/public/application/quickstart_flows/auto_detect/use_auto_detect_telemetry.ts +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { useEffect, useState } from 'react'; -import { useKibana } from '@kbn/kibana-react-plugin/public'; -import { ObservabilityOnboardingFlowStatus } from './get_onboarding_status'; -import { OBSERVABILITY_ONBOARDING_AUTODETECT_TELEMETRY_EVENT } from '../../../../common/telemetry_events'; - -interface IntegrationFields { - installSource: string; - pkgName: string; - pkgVersion: string; - title: string; -} - -export function useAutoDetectTelemetry( - status: ObservabilityOnboardingFlowStatus, - integrations: IntegrationFields[] -) { - const [waitingMessageSent, setWaitingMessageSent] = useState(false); - const [dataShippedMessageSent, setDataShippedMessageSent] = useState(false); - const { - services: { analytics }, - } = useKibana(); - - useEffect(() => { - if (status === 'awaitingData' && !waitingMessageSent) { - analytics?.reportEvent(OBSERVABILITY_ONBOARDING_AUTODETECT_TELEMETRY_EVENT.eventType, { - uses_legacy_onboarding_page: false, - flow: 'auto_detect', - step: 'awaiting_data', - integrations, - }); - setWaitingMessageSent(true); - } - if (status === 'dataReceived' && !dataShippedMessageSent) { - analytics?.reportEvent(OBSERVABILITY_ONBOARDING_AUTODETECT_TELEMETRY_EVENT.eventType, { - uses_legacy_onboarding_page: false, - flow: 'auto_detect', - step: 'data_shipped', - integrations, - }); - setDataShippedMessageSent(true); - } - }, [analytics, dataShippedMessageSent, integrations, status, waitingMessageSent]); -} diff --git a/x-pack/solutions/observability/plugins/observability_onboarding/public/application/quickstart_flows/auto_detect/use_onboarding_flow.tsx b/x-pack/solutions/observability/plugins/observability_onboarding/public/application/quickstart_flows/auto_detect/use_onboarding_flow.tsx index 7434141a76d35..c6aae1f3e959e 100644 --- a/x-pack/solutions/observability/plugins/observability_onboarding/public/application/quickstart_flows/auto_detect/use_onboarding_flow.tsx +++ b/x-pack/solutions/observability/plugins/observability_onboarding/public/application/quickstart_flows/auto_detect/use_onboarding_flow.tsx @@ -9,6 +9,8 @@ import useInterval from 'react-use/lib/useInterval'; import { useKibana } from '@kbn/kibana-react-plugin/public'; import useAsync from 'react-use/lib/useAsync'; import { type AssetSOObject, type GetBulkAssetsResponse } from '@kbn/fleet-plugin/common'; +import { useEffect, useState } from 'react'; +import { OBSERVABILITY_ONBOARDING_TELEMETRY_EVENT } from '../../../../common/telemetry_events'; import { FETCH_STATUS, useFetcher } from '../../../hooks/use_fetcher'; import { getOnboardingStatus } from './get_onboarding_status'; import { getInstalledIntegrations } from './get_installed_integrations'; @@ -32,8 +34,9 @@ export const DASHBOARDS = { export function useOnboardingFlow() { const { - services: { fleet }, + services: { fleet, analytics }, } = useKibana(); + const [dataReceivedTelemetrySent, setDataReceivedTelemetrySent] = useState(false); // Create onboarding session const { data, error, refetch } = useFetcher( @@ -105,6 +108,18 @@ export function useOnboardingFlow() { progressStatus === FETCH_STATUS.SUCCESS && status !== 'dataReceived' ? 3000 : null ); + useEffect(() => { + if (status === 'dataReceived' && !dataReceivedTelemetrySent) { + setDataReceivedTelemetrySent(true); + analytics.reportEvent(OBSERVABILITY_ONBOARDING_TELEMETRY_EVENT.eventType, { + flow_type: 'autoDetect', + flow_id: onboardingId, + step: 'logs-ingest', + step_status: 'complete', + }); + } + }, [analytics, dataReceivedTelemetrySent, onboardingId, status]); + return { data, error, diff --git a/x-pack/solutions/observability/plugins/observability_onboarding/public/application/quickstart_flows/custom_logs/install_elastic_agent.tsx b/x-pack/solutions/observability/plugins/observability_onboarding/public/application/quickstart_flows/custom_logs/install_elastic_agent.tsx index e297bd2076536..ae07e39cf7c8d 100644 --- a/x-pack/solutions/observability/plugins/observability_onboarding/public/application/quickstart_flows/custom_logs/install_elastic_agent.tsx +++ b/x-pack/solutions/observability/plugins/observability_onboarding/public/application/quickstart_flows/custom_logs/install_elastic_agent.tsx @@ -10,6 +10,7 @@ import { i18n } from '@kbn/i18n'; import { useKibana } from '@kbn/kibana-react-plugin/public'; import { default as React, useCallback, useEffect, useState } from 'react'; import { type LogsLocatorParams, LOGS_LOCATOR_ID } from '@kbn/logs-shared-plugin/common'; +import { OBSERVABILITY_ONBOARDING_TELEMETRY_EVENT } from '../../../../common/telemetry_events'; import { ObservabilityOnboardingPluginSetupDeps } from '../../../plugin'; import { useWizard } from '.'; import { FETCH_STATUS, useFetcher } from '../../../hooks/use_fetcher'; @@ -26,14 +27,14 @@ import { StepModal } from '../shared/step_panel'; import { ApiKeyBanner } from './api_key_banner'; import { WindowsInstallStep } from '../shared/windows_install_step'; import { TroubleshootingLink } from '../shared/troubleshooting_link'; -import { useFlowProgressTelemetry } from '../../../hooks/use_flow_progress_telemetry'; const defaultDatasetName = ''; export function InstallElasticAgent() { const { - services: { share }, + services: { share, analytics }, } = useKibana(); + const [dataReceivedTelemetrySent, setDataReceivedTelemetrySent] = useState(false); const logsLocator = share.url.locators.get(LOGS_LOCATOR_ID); @@ -181,8 +182,6 @@ export function InstallElasticAgent() { } }, [progressSucceded, refetchProgress]); - useFlowProgressTelemetry(progressData?.progress, 'custom_logs'); - const getCheckLogsStep = useCallback(() => { const progress = progressData?.progress; if (progress) { @@ -209,6 +208,19 @@ export function InstallElasticAgent() { const isInstallCompleted = progressData?.progress?.['ea-status']?.status === 'complete'; const autoDownloadConfigStatus = (progressData?.progress?.['ea-config']?.status ?? 'incomplete') as EuiStepStatus; + const isIngestCompleted = progressData?.progress?.['logs-ingest']?.status === 'complete'; + + useEffect(() => { + if (isIngestCompleted && !dataReceivedTelemetrySent) { + setDataReceivedTelemetrySent(true); + analytics?.reportEvent(OBSERVABILITY_ONBOARDING_TELEMETRY_EVENT.eventType, { + flow_type: 'logFiles', + flow_id: onboardingId, + step: 'logs-ingest', + step_status: 'complete', + }); + } + }, [analytics, dataReceivedTelemetrySent, isIngestCompleted, onboardingId]); return ( (undefined); const [checkDataStartTime] = useState(Date.now()); + const [dataReceivedTelemetrySent, setDataReceivedTelemetrySent] = useState(false); const { - services: { share }, + services: { share, analytics }, } = useKibana(); const dashboardLocator = share.url.locators.get(DASHBOARD_APP_LOCATOR); @@ -61,12 +58,16 @@ export function DataIngestStatus({ onboardingId }: Props) { }, [data?.hasData, refetch, status]); useEffect(() => { - if (data?.hasData === true) { - setProgress({ 'logs-ingest': { status: 'complete' } }); + if (data?.hasData === true && !dataReceivedTelemetrySent) { + setDataReceivedTelemetrySent(true); + analytics.reportEvent(OBSERVABILITY_ONBOARDING_TELEMETRY_EVENT.eventType, { + flow_type: 'kubernetes', + flow_id: onboardingId, + step: 'logs-ingest', + step_status: 'complete', + }); } - }, [data?.hasData]); - - useFlowProgressTelemetry(progress, onboardingId); + }, [analytics, data?.hasData, dataReceivedTelemetrySent, onboardingId]); const isTroubleshootingVisible = data?.hasData === false && Date.now() - checkDataStartTime > SHOW_TROUBLESHOOTING_DELAY; diff --git a/x-pack/solutions/observability/plugins/observability_onboarding/public/assets/auto_detect.sh b/x-pack/solutions/observability/plugins/observability_onboarding/public/assets/auto_detect.sh index 06f6a90f82a45..beff090673976 100755 --- a/x-pack/solutions/observability/plugins/observability_onboarding/public/assets/auto_detect.sh +++ b/x-pack/solutions/observability/plugins/observability_onboarding/public/assets/auto_detect.sh @@ -90,6 +90,34 @@ ensure_argument "$kibana_api_endpoint" "--kibana-url" ensure_argument "$onboarding_flow_id" "--id" ensure_argument "$elastic_agent_version" "--ea-version" +update_step_progress() { + local STEPNAME="$1" + local STATUS="$2" # "incomplete" | "complete" | "disabled" | "loading" | "warning" | "danger" | "current" + local MESSAGE=${3:-} + local PAYLOAD=${4:-} + local data="" + + MESSAGE=$(echo "$MESSAGE" | sed 's/"/\\"/g') + + if [ -z "$PAYLOAD" ]; then + data="{\"status\":\"${STATUS}\", \"message\":\"${MESSAGE}\"}" + else + data="{\"status\":\"${STATUS}\", \"message\":\"${MESSAGE}\", \"payload\":${PAYLOAD}}" + fi + curl --request POST \ + --url "${kibana_api_endpoint}/internal/observability_onboarding/flow/${onboarding_flow_id}/step/${STEPNAME}" \ + --header "Authorization: ApiKey ${install_api_key_encoded}" \ + --header "Content-Type: application/json" \ + --header "kbn-xsrf: true" \ + --header "x-elastic-internal-origin: Kibana" \ + --data "$data" \ + --output /dev/null \ + --no-progress-meter \ + --fail +} + +update_step_progress "logs-detect" "initialize" + known_integrations_list_string="" selected_known_integrations_array=() detected_patterns=() @@ -122,34 +150,12 @@ elif [ "${OS}" == "Darwin" ]; then fi elastic_agent_config_path=/Library/Elastic/Agent/elastic-agent.yml else + update_step_progress "logs-detect" "danger" "Unable to run auto-detect script on ${os} (${arch})" fail "This script is only supported on Linux and macOS" fi elastic_agent_artifact_name="elastic-agent-${elastic_agent_version}-${os}-${arch}" -update_step_progress() { - local STEPNAME="$1" - local STATUS="$2" # "incomplete" | "complete" | "disabled" | "loading" | "warning" | "danger" | "current" - local MESSAGE=${3:-} - local PAYLOAD=${4:-} - local data="" - if [ -z "$PAYLOAD" ]; then - data="{\"status\":\"${STATUS}\", \"message\":\"${MESSAGE}\"}" - else - data="{\"status\":\"${STATUS}\", \"message\":\"${MESSAGE}\", \"payload\":${PAYLOAD}}" - fi - curl --request POST \ - --url "${kibana_api_endpoint}/internal/observability_onboarding/flow/${onboarding_flow_id}/step/${STEPNAME}" \ - --header "Authorization: ApiKey ${install_api_key_encoded}" \ - --header "Content-Type: application/json" \ - --header "kbn-xsrf: true" \ - --header "x-elastic-internal-origin: Kibana" \ - --data "$data" \ - --output /dev/null \ - --no-progress-meter \ - --fail -} - download_elastic_agent() { local download_url="https://artifacts.elastic.co/downloads/beats/elastic-agent/${elastic_agent_artifact_name}.tar.gz" rm -rf "./${elastic_agent_artifact_name}" "./${elastic_agent_artifact_name}.tar.gz" @@ -244,7 +250,7 @@ backup_elastic_agent_config() { if [ "$?" -eq 0 ]; then printf "\n\e[32;1m✓\e[0m %s \e[36m%s\e[0m\n" "Backup saved to" "$backup_path" else - update_step_progress "ea-config" "warning" "Failed to backup existing configuration" + update_step_progress "ea-config" "danger" "Failed to backup existing configuration" fail "Failed to backup existing config - Try manually creating a backup or delete your existing config before re-running this script" fi else @@ -289,7 +295,7 @@ install_integrations() { if [ "$?" -eq 0 ]; then printf "\n\e[32;1m✓\e[0m %s\n" "Integrations installed" else - update_step_progress "ea-config" "warning" "Failed to install integrations" + update_step_progress "install-integrations" "danger" "Failed to install integrations" fail "Failed to install integrations" fi } @@ -318,7 +324,7 @@ apply_elastic_agent_config() { update_step_progress "ea-config" "complete" else - update_step_progress "ea-config" "warning" "Failed to configure Elastic Agent" + update_step_progress "ea-config" "danger" "Failed to configure Elastic Agent" fail "Failed to configure Elastic Agent" fi } @@ -588,7 +594,7 @@ generate_custom_integration_name() { } printf "\e[1m%s\e[0m\n" "Looking for log files..." -update_step_progress "logs-detect" "loading" +update_step_progress "logs-detect" "loading" "" "{\"os\": \"${os}\", \"arch\": \"${arch}\"}" detect_known_integrations # Check if LSOF_PATH is executable @@ -596,6 +602,7 @@ if [ -x "$LSOF_PATH" ]; then read_open_log_file_list build_unknown_log_file_patterns else + update_step_progress "logs-detect" "warning" "lsof is not available on the host" echo -e "\nlsof is required to detect custom log files. Looking for known integrations only." fi diff --git a/x-pack/solutions/observability/plugins/observability_onboarding/public/hooks/use_flow_progress_telemetry.test.tsx b/x-pack/solutions/observability/plugins/observability_onboarding/public/hooks/use_flow_progress_telemetry.test.tsx deleted file mode 100644 index 45ca17d878991..0000000000000 --- a/x-pack/solutions/observability/plugins/observability_onboarding/public/hooks/use_flow_progress_telemetry.test.tsx +++ /dev/null @@ -1,80 +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 { renderHook } from '@testing-library/react'; -import { useFlowProgressTelemetry } from './use_flow_progress_telemetry'; -import { useKibana } from './use_kibana'; - -jest.mock('./use_kibana', () => { - return { - useKibana: jest.fn().mockReturnValue({ - ...jest.requireActual('./use_kibana'), - services: { - analytics: { reportEvent: jest.fn() }, - }, - }), - }; -}); - -describe('useFlowProgressTelemetry', () => { - beforeEach(() => { - jest.clearAllMocks(); - }); - - it('does not trigger an event if there is no progress', () => { - const render = renderHook(() => ({ - analytics: useKibana().services.analytics, - flowProgress: useFlowProgressTelemetry(undefined, 'test-flow'), - })); - - expect(render.result.current.analytics.reportEvent).not.toHaveBeenCalled(); - }); - - it('triggers an event when there is a progress change', () => { - const render = renderHook(() => ({ - analytics: useKibana().services.analytics, - flowProgress: useFlowProgressTelemetry( - { 'ea-download': { status: 'complete' } }, - 'test-flow' - ), - })); - - expect(render.result.current.analytics.reportEvent).toHaveBeenCalledTimes(1); - expect(render.result.current.analytics.reportEvent).toHaveBeenCalledWith( - 'observability_onboarding', - { - uses_legacy_onboarding_page: false, - flow: 'test-flow', - step: 'ea-download', - step_status: 'complete', - } - ); - }); - - it('does not trigger an event for unsupported steps', () => { - const render = renderHook(() => ({ - analytics: useKibana().services.analytics, - flowProgress: useFlowProgressTelemetry({ 'ea-extract': { status: 'complete' } }, 'test-flow'), - })); - - expect(render.result.current.analytics.reportEvent).not.toHaveBeenCalled(); - }); - - it('does not trigger an event if the status of a step has not changed', () => { - const render = renderHook(() => ({ - analytics: useKibana().services.analytics, - flowProgress: useFlowProgressTelemetry( - { 'ea-download': { status: 'complete' } }, - 'test-flow' - ), - })); - - render.rerender(); - - expect(render.result.current.analytics.reportEvent).toHaveBeenCalledTimes(1); - }); -}); diff --git a/x-pack/solutions/observability/plugins/observability_onboarding/public/hooks/use_flow_progress_telemetry.ts b/x-pack/solutions/observability/plugins/observability_onboarding/public/hooks/use_flow_progress_telemetry.ts deleted file mode 100644 index a580055f8e3c7..0000000000000 --- a/x-pack/solutions/observability/plugins/observability_onboarding/public/hooks/use_flow_progress_telemetry.ts +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { useEffect, useState } from 'react'; -import { EuiStepsProps } from '@elastic/eui'; -import { type LogsFlowProgressStepId } from '../../common/logs_flow_progress_step_id'; -import { OBSERVABILITY_ONBOARDING_TELEMETRY_EVENT } from '../../common/telemetry_events'; -import { useKibana } from './use_kibana'; - -export type EuiStepStatus = EuiStepsProps['steps'][number]['status']; - -export type StepsProgress = Partial< - Record ->; - -const TRACKED_STEPS: LogsFlowProgressStepId[] = ['ea-download', 'ea-status', 'logs-ingest']; -const TRACKED_STATUSES: EuiStepStatus[] = ['danger', 'warning', 'complete']; - -export function useFlowProgressTelemetry(progress: StepsProgress | undefined, flowId: string) { - const { - services: { analytics }, - } = useKibana(); - const [previousReportedSteps] = useState>(new Map()); - - useEffect(() => { - if (!progress) { - return; - } - - TRACKED_STEPS.forEach((stepId) => { - const step = progress[stepId]; - - if ( - !step || - !TRACKED_STATUSES.includes(step.status) || - previousReportedSteps.get(stepId) === step.status - ) { - return; - } - - analytics.reportEvent(OBSERVABILITY_ONBOARDING_TELEMETRY_EVENT.eventType, { - uses_legacy_onboarding_page: false, - flow: flowId, - step: stepId, - step_status: step.status, - step_message: step.message, - }); - previousReportedSteps.set(stepId, step.status); - }); - }, [analytics, flowId, progress, previousReportedSteps]); -} diff --git a/x-pack/solutions/observability/plugins/observability_onboarding/public/plugin.ts b/x-pack/solutions/observability/plugins/observability_onboarding/public/plugin.ts index 0f0880dde4199..f36923ce33c2b 100644 --- a/x-pack/solutions/observability/plugins/observability_onboarding/public/plugin.ts +++ b/x-pack/solutions/observability/plugins/observability_onboarding/public/plugin.ts @@ -35,7 +35,6 @@ import { ConfigSchema } from '.'; import { OBSERVABILITY_ONBOARDING_FEEDBACK_TELEMETRY_EVENT, OBSERVABILITY_ONBOARDING_TELEMETRY_EVENT, - OBSERVABILITY_ONBOARDING_AUTODETECT_TELEMETRY_EVENT, OBSERVABILITY_ONBOARDING_FLOW_PROGRESS_TELEMETRY_EVENT, OBSERVABILITY_ONBOARDING_FLOW_ERROR_TELEMETRY_EVENT, OBSERVABILITY_ONBOARDING_FLOW_DATASET_DETECTED_TELEMETRY_EVENT, @@ -89,7 +88,7 @@ export class ObservabilityOnboardingPlugin order: 8500, euiIconType: 'logoObservability', category: DEFAULT_APP_CATEGORIES.observability, - keywords: [], + keywords: ['add data'], async mount(appMountParameters: AppMountParameters) { // Load application bundle and Get start service const [{ renderApp }, [coreStart, corePlugins]] = await Promise.all([ @@ -116,7 +115,7 @@ export class ObservabilityOnboardingPlugin }, }); }, - visibleIn: [], + visibleIn: ['globalSearch'], }); this.locators = { @@ -125,7 +124,6 @@ export class ObservabilityOnboardingPlugin core.analytics.registerEventType(OBSERVABILITY_ONBOARDING_TELEMETRY_EVENT); core.analytics.registerEventType(OBSERVABILITY_ONBOARDING_FEEDBACK_TELEMETRY_EVENT); - core.analytics.registerEventType(OBSERVABILITY_ONBOARDING_AUTODETECT_TELEMETRY_EVENT); core.analytics.registerEventType(OBSERVABILITY_ONBOARDING_FLOW_PROGRESS_TELEMETRY_EVENT); core.analytics.registerEventType(OBSERVABILITY_ONBOARDING_FLOW_ERROR_TELEMETRY_EVENT); core.analytics.registerEventType( diff --git a/x-pack/solutions/observability/plugins/observability_onboarding/server/plugin.ts b/x-pack/solutions/observability/plugins/observability_onboarding/server/plugin.ts index 60b33eb3dd601..2a9f282ed14b2 100644 --- a/x-pack/solutions/observability/plugins/observability_onboarding/server/plugin.ts +++ b/x-pack/solutions/observability/plugins/observability_onboarding/server/plugin.ts @@ -26,6 +26,7 @@ import { import { observabilityOnboardingFlow } from './saved_objects/observability_onboarding_status'; import { EsLegacyConfigService } from './services/es_legacy_config_service'; import { ObservabilityOnboardingConfig } from './config'; +import { OBSERVABILITY_ONBOARDING_TELEMETRY_EVENT } from '../common/telemetry_events'; export class ObservabilityOnboardingPlugin implements @@ -116,6 +117,8 @@ export class ObservabilityOnboardingPlugin isBeta: true, }); + core.analytics.registerEventType(OBSERVABILITY_ONBOARDING_TELEMETRY_EVENT); + return {}; } diff --git a/x-pack/solutions/observability/plugins/observability_onboarding/server/routes/flow/route.ts b/x-pack/solutions/observability/plugins/observability_onboarding/server/routes/flow/route.ts index 290e003d72661..d61e90c2ef4ed 100644 --- a/x-pack/solutions/observability/plugins/observability_onboarding/server/routes/flow/route.ts +++ b/x-pack/solutions/observability/plugins/observability_onboarding/server/routes/flow/route.ts @@ -15,6 +15,7 @@ import { import { dump } from 'js-yaml'; import { PackageDataStreamTypes, Output } from '@kbn/fleet-plugin/common/types'; import { transformOutputToFullPolicyOutput } from '@kbn/fleet-plugin/server/services/output_client'; +import { OBSERVABILITY_ONBOARDING_TELEMETRY_EVENT } from '../../../common/telemetry_events'; import { getObservabilityOnboardingFlow, saveObservabilityOnboardingFlow } from '../../lib/state'; import type { SavedObservabilityOnboardingFlow } from '../../saved_objects/observability_onboarding_status'; import { ObservabilityOnboardingFlow } from '../../saved_objects/observability_onboarding_status'; @@ -134,6 +135,16 @@ const stepProgressUpdateRoute = createObservabilityOnboardingServerRoute({ }, }, }); + + coreStart.analytics.reportEvent(OBSERVABILITY_ONBOARDING_TELEMETRY_EVENT.eventType, { + flow_type: observabilityOnboardingState.type, + flow_id: id, + step: name, + step_status: status, + step_message: message, + payload, + }); + return { name, status, message, payload }; }, }); @@ -415,6 +426,23 @@ const integrationsInstallRoute = createObservabilityOnboardingServerRoute({ }, }); + coreStart.analytics.reportEvent(OBSERVABILITY_ONBOARDING_TELEMETRY_EVENT.eventType, { + flow_type: savedObservabilityOnboardingState.type, + flow_id: params.path.onboardingId, + step: 'install-integrations', + step_status: 'complete', + payload: { + integrations: installedIntegrations.map( + ({ title, pkgName, pkgVersion, installSource }) => ({ + title, + pkgName, + pkgVersion, + installSource, + }) + ), + }, + }); + return response.ok({ headers: { 'content-type': 'application/x-tar', diff --git a/x-pack/solutions/observability/plugins/observability_onboarding/server/routes/types.ts b/x-pack/solutions/observability/plugins/observability_onboarding/server/routes/types.ts index 4a1e818995409..531caf436c5a5 100644 --- a/x-pack/solutions/observability/plugins/observability_onboarding/server/routes/types.ts +++ b/x-pack/solutions/observability/plugins/observability_onboarding/server/routes/types.ts @@ -76,6 +76,11 @@ export const IntegrationRT = t.intersection([ export type InstalledIntegration = t.TypeOf; +export const LogsDetectLoadingStepPayloadRT = t.type({ + os: t.string, + arch: t.string, +}); + export const ElasticAgentStepPayloadRT = t.type({ agentId: t.string, }); @@ -87,6 +92,7 @@ export const InstallIntegrationsStepPayloadRT = t.array(IntegrationRT); export type InstallIntegrationsStepPayload = t.TypeOf; export const StepProgressPayloadRT = t.union([ + LogsDetectLoadingStepPayloadRT, ElasticAgentStepPayloadRT, InstallIntegrationsStepPayloadRT, ]); diff --git a/x-pack/solutions/observability/plugins/observability_onboarding/server/saved_objects/observability_onboarding_status.ts b/x-pack/solutions/observability/plugins/observability_onboarding/server/saved_objects/observability_onboarding_status.ts index 03be370e6cf6b..81f5919a7c1ac 100644 --- a/x-pack/solutions/observability/plugins/observability_onboarding/server/saved_objects/observability_onboarding_status.ts +++ b/x-pack/solutions/observability/plugins/observability_onboarding/server/saved_objects/observability_onboarding_status.ts @@ -53,6 +53,11 @@ const SystemLogsStateSchema = schema.object({ namespace: schema.string(), }); +const LogsDetectLoadingStepPayloadSchema = schema.object({ + os: schema.string(), + arch: schema.string(), +}); + const ElasticAgentStepPayloadSchema = schema.object({ agentId: schema.string(), }); @@ -128,7 +133,11 @@ export const observabilityOnboardingFlow: SavedObjectsType = { status: schema.string(), message: schema.maybe(schema.string()), payload: schema.maybe( - schema.oneOf([ElasticAgentStepPayloadSchema, InstallIntegrationsStepPayloadSchema]) + schema.oneOf([ + ElasticAgentStepPayloadSchema, + InstallIntegrationsStepPayloadSchema, + LogsDetectLoadingStepPayloadSchema, + ]) ), }) ), diff --git a/x-pack/solutions/observability/plugins/slo/common/constants.ts b/x-pack/solutions/observability/plugins/slo/common/constants.ts index b47fecdbd3144..5599cd16a3f39 100644 --- a/x-pack/solutions/observability/plugins/slo/common/constants.ts +++ b/x-pack/solutions/observability/plugins/slo/common/constants.ts @@ -57,32 +57,25 @@ export const SLO_MODEL_VERSION = 2; export const SLO_RESOURCES_VERSION = 3.4; export const SLO_RESOURCES_VERSION_MAJOR = 3; -export const SLO_COMPONENT_TEMPLATE_MAPPINGS_NAME = '.slo-observability.sli-mappings'; -export const SLO_COMPONENT_TEMPLATE_SETTINGS_NAME = '.slo-observability.sli-settings'; - -export const SLO_INDEX_TEMPLATE_NAME = '.slo-observability.sli'; -export const SLO_INDEX_TEMPLATE_PATTERN = `.slo-observability.sli-*`; - -export const SLO_DESTINATION_INDEX_NAME = `.slo-observability.sli-v${SLO_RESOURCES_VERSION}`; -export const SLO_DESTINATION_INDEX_PATTERN = `.slo-observability.sli-v${SLO_RESOURCES_VERSION_MAJOR}*`; - -export const SLO_INGEST_PIPELINE_INDEX_NAME_PREFIX = `.slo-observability.sli-v${SLO_RESOURCES_VERSION}.`; - -export const SLO_SUMMARY_COMPONENT_TEMPLATE_MAPPINGS_NAME = '.slo-observability.summary-mappings'; -export const SLO_SUMMARY_COMPONENT_TEMPLATE_SETTINGS_NAME = '.slo-observability.summary-settings'; -export const SLO_SUMMARY_INDEX_TEMPLATE_NAME = '.slo-observability.summary'; -export const SLO_SUMMARY_INDEX_TEMPLATE_PATTERN = `.slo-observability.summary-*`; - -export const SLO_SUMMARY_DESTINATION_INDEX_NAME = `.slo-observability.summary-v${SLO_RESOURCES_VERSION}`; // store the summary document generated by transform -export const SLO_SUMMARY_TEMP_INDEX_NAME = `.slo-observability.summary-v${SLO_RESOURCES_VERSION}.temp`; // store the temporary summary document -export const SLO_SUMMARY_DESTINATION_INDEX_PATTERN = `.slo-observability.summary-v${SLO_RESOURCES_VERSION_MAJOR}*`; // include temp and non-temp summary indices +export const SLI_COMPONENT_TEMPLATE_MAPPINGS_NAME = '.slo-observability.sli-mappings'; +export const SLI_COMPONENT_TEMPLATE_SETTINGS_NAME = '.slo-observability.sli-settings'; +export const SLI_INDEX_TEMPLATE_NAME = '.slo-observability.sli'; +export const SLI_INDEX_TEMPLATE_PATTERN = `.slo-observability.sli-*`; +export const SLI_DESTINATION_INDEX_NAME = `.slo-observability.sli-v${SLO_RESOURCES_VERSION}`; +export const SLI_DESTINATION_INDEX_PATTERN = `.slo-observability.sli-v${SLO_RESOURCES_VERSION_MAJOR}*`; +export const SLI_INGEST_PIPELINE_INDEX_NAME_PREFIX = `.slo-observability.sli-v${SLO_RESOURCES_VERSION}.`; + +export const SUMMARY_COMPONENT_TEMPLATE_MAPPINGS_NAME = '.slo-observability.summary-mappings'; +export const SUMMARY_COMPONENT_TEMPLATE_SETTINGS_NAME = '.slo-observability.summary-settings'; +export const SUMMARY_INDEX_TEMPLATE_NAME = '.slo-observability.summary'; +export const SUMMARY_INDEX_TEMPLATE_PATTERN = `.slo-observability.summary-*`; +export const SUMMARY_DESTINATION_INDEX_NAME = `.slo-observability.summary-v${SLO_RESOURCES_VERSION}`; // store the summary document generated by transform +export const SUMMARY_TEMP_INDEX_NAME = `.slo-observability.summary-v${SLO_RESOURCES_VERSION}.temp`; // store the temporary summary document +export const SUMMARY_DESTINATION_INDEX_PATTERN = `.slo-observability.summary-v${SLO_RESOURCES_VERSION_MAJOR}*`; // include temp and non-temp summary indices export const getSLOTransformId = (sloId: string, sloRevision: number) => `slo-${sloId}-${sloRevision}`; -export const DEFAULT_SLO_PAGE_SIZE = 25; -export const DEFAULT_SLO_GROUPS_PAGE_SIZE = 25; - export const getSLOSummaryTransformId = (sloId: string, sloRevision: number) => `slo-summary-${sloId}-${sloRevision}`; @@ -97,3 +90,6 @@ export const SYNTHETICS_DEFAULT_GROUPINGS = ['monitor.name', 'observer.geo.name' // in hours export const DEFAULT_STALE_SLO_THRESHOLD_HOURS = 48; + +export const DEFAULT_SLO_PAGE_SIZE = 25; +export const DEFAULT_SLO_GROUPS_PAGE_SIZE = 25; diff --git a/x-pack/solutions/observability/plugins/slo/common/summary_indices.test.ts b/x-pack/solutions/observability/plugins/slo/common/summary_indices.test.ts index 64f9ad0d44540..a2b921f94435d 100644 --- a/x-pack/solutions/observability/plugins/slo/common/summary_indices.test.ts +++ b/x-pack/solutions/observability/plugins/slo/common/summary_indices.test.ts @@ -6,10 +6,7 @@ */ import { getListOfSloSummaryIndices } from './summary_indices'; -import { - DEFAULT_STALE_SLO_THRESHOLD_HOURS, - SLO_SUMMARY_DESTINATION_INDEX_PATTERN, -} from './constants'; +import { DEFAULT_STALE_SLO_THRESHOLD_HOURS, SUMMARY_DESTINATION_INDEX_PATTERN } from './constants'; describe('getListOfSloSummaryIndices', () => { it('should return default index if disabled', function () { @@ -19,7 +16,7 @@ describe('getListOfSloSummaryIndices', () => { staleThresholdInHours: DEFAULT_STALE_SLO_THRESHOLD_HOURS, }; const result = getListOfSloSummaryIndices(settings, []); - expect(result).toBe(SLO_SUMMARY_DESTINATION_INDEX_PATTERN); + expect(result).toBe(SUMMARY_DESTINATION_INDEX_PATTERN); }); it('should return all remote clusters when enabled', function () { @@ -34,7 +31,7 @@ describe('getListOfSloSummaryIndices', () => { ]; const result = getListOfSloSummaryIndices(settings, clustersByName); expect(result).toBe( - `${SLO_SUMMARY_DESTINATION_INDEX_PATTERN},cluster1:${SLO_SUMMARY_DESTINATION_INDEX_PATTERN},cluster2:${SLO_SUMMARY_DESTINATION_INDEX_PATTERN}` + `${SUMMARY_DESTINATION_INDEX_PATTERN},cluster1:${SUMMARY_DESTINATION_INDEX_PATTERN},cluster2:${SUMMARY_DESTINATION_INDEX_PATTERN}` ); }); @@ -50,7 +47,7 @@ describe('getListOfSloSummaryIndices', () => { ]; const result = getListOfSloSummaryIndices(settings, clustersByName); expect(result).toBe( - `${SLO_SUMMARY_DESTINATION_INDEX_PATTERN},cluster1:${SLO_SUMMARY_DESTINATION_INDEX_PATTERN}` + `${SUMMARY_DESTINATION_INDEX_PATTERN},cluster1:${SUMMARY_DESTINATION_INDEX_PATTERN}` ); }); }); diff --git a/x-pack/solutions/observability/plugins/slo/common/summary_indices.ts b/x-pack/solutions/observability/plugins/slo/common/summary_indices.ts index c9a9d47bfdf1a..216f351496cd8 100644 --- a/x-pack/solutions/observability/plugins/slo/common/summary_indices.ts +++ b/x-pack/solutions/observability/plugins/slo/common/summary_indices.ts @@ -6,7 +6,7 @@ */ import { GetSLOSettingsResponse } from '@kbn/slo-schema'; -import { SLO_SUMMARY_DESTINATION_INDEX_PATTERN } from './constants'; +import { SUMMARY_DESTINATION_INDEX_PATTERN } from './constants'; export const getListOfSloSummaryIndices = ( settings: GetSLOSettingsResponse, @@ -14,13 +14,13 @@ export const getListOfSloSummaryIndices = ( ) => { const { useAllRemoteClusters, selectedRemoteClusters } = settings; if (!useAllRemoteClusters && selectedRemoteClusters.length === 0) { - return SLO_SUMMARY_DESTINATION_INDEX_PATTERN; + return SUMMARY_DESTINATION_INDEX_PATTERN; } - const indices: string[] = [SLO_SUMMARY_DESTINATION_INDEX_PATTERN]; + const indices: string[] = [SUMMARY_DESTINATION_INDEX_PATTERN]; clustersByName.forEach(({ name, isConnected }) => { if (isConnected && (useAllRemoteClusters || selectedRemoteClusters.includes(name))) { - indices.push(`${name}:${SLO_SUMMARY_DESTINATION_INDEX_PATTERN}`); + indices.push(`${name}:${SUMMARY_DESTINATION_INDEX_PATTERN}`); } }); diff --git a/x-pack/solutions/observability/plugins/slo/public/components/slo/error_rate_chart/use_lens_definition.ts b/x-pack/solutions/observability/plugins/slo/public/components/slo/error_rate_chart/use_lens_definition.ts index db7eb43f71188..5e555c10c2e4b 100644 --- a/x-pack/solutions/observability/plugins/slo/public/components/slo/error_rate_chart/use_lens_definition.ts +++ b/x-pack/solutions/observability/plugins/slo/public/components/slo/error_rate_chart/use_lens_definition.ts @@ -12,7 +12,7 @@ import { TypedLensByValueInput } from '@kbn/lens-plugin/public'; import { ALL_VALUE, SLOWithSummaryResponse } from '@kbn/slo-schema'; import moment from 'moment'; import { v4 as uuidv4 } from 'uuid'; -import { SLO_DESTINATION_INDEX_PATTERN } from '../../../../common/constants'; +import { SLI_DESTINATION_INDEX_PATTERN } from '../../../../common/constants'; import { getLensDefinitionInterval } from './utils'; export interface TimeRange { @@ -487,8 +487,8 @@ export function useLensDefinition({ '32ca1ad4-81c0-4daf-b9d1-07118044bdc5': { id: '32ca1ad4-81c0-4daf-b9d1-07118044bdc5', title: !!slo.remote - ? `${slo.remote.remoteName}:${SLO_DESTINATION_INDEX_PATTERN}` - : SLO_DESTINATION_INDEX_PATTERN, + ? `${slo.remote.remoteName}:${SLI_DESTINATION_INDEX_PATTERN}` + : SLI_DESTINATION_INDEX_PATTERN, timeFieldName: '@timestamp', sourceFilters: [], fieldFormats: {}, diff --git a/x-pack/solutions/observability/plugins/slo/public/embeddable/slo/overview/group_view/slo_group_filters.tsx b/x-pack/solutions/observability/plugins/slo/public/embeddable/slo/overview/group_view/slo_group_filters.tsx index d9995adfc412c..0adf7200d1629 100644 --- a/x-pack/solutions/observability/plugins/slo/public/embeddable/slo/overview/group_view/slo_group_filters.tsx +++ b/x-pack/solutions/observability/plugins/slo/public/embeddable/slo/overview/group_view/slo_group_filters.tsx @@ -11,7 +11,7 @@ import { FormattedMessage } from '@kbn/i18n-react'; import { debounce } from 'lodash'; import React, { useEffect, useMemo, useState } from 'react'; import { sloAppId } from '../../../../../common'; -import { SLO_SUMMARY_DESTINATION_INDEX_NAME } from '../../../../../common/constants'; +import { SUMMARY_DESTINATION_INDEX_NAME } from '../../../../../common/constants'; import { useCreateDataView } from '../../../../hooks/use_create_data_view'; import { useFetchSloGroups } from '../../../../hooks/use_fetch_slo_groups'; import { SLI_OPTIONS } from '../../../../pages/slo_edit/constants'; @@ -86,7 +86,7 @@ export function SloGroupFilters({ selectedFilters, onSelected }: Props) { : []), ]; const { dataView } = useCreateDataView({ - indexPatternString: SLO_SUMMARY_DESTINATION_INDEX_NAME, + indexPatternString: SUMMARY_DESTINATION_INDEX_NAME, }); const [selectedGroupBy, setSelectedGroupBy] = useState(selectedFilters.groupBy) ?? 'status'; diff --git a/x-pack/solutions/observability/plugins/slo/public/hooks/use_fetch_slo_groups.ts b/x-pack/solutions/observability/plugins/slo/public/hooks/use_fetch_slo_groups.ts index da9b93e0eb209..f6a8cb598466b 100644 --- a/x-pack/solutions/observability/plugins/slo/public/hooks/use_fetch_slo_groups.ts +++ b/x-pack/solutions/observability/plugins/slo/public/hooks/use_fetch_slo_groups.ts @@ -16,7 +16,7 @@ import { import { useMemo } from 'react'; import { DEFAULT_SLO_GROUPS_PAGE_SIZE, - SLO_SUMMARY_DESTINATION_INDEX_PATTERN, + SUMMARY_DESTINATION_INDEX_PATTERN, } from '../../common/constants'; import type { GroupByField } from '../pages/slos/types'; import { SearchState } from '../pages/slos/hooks/use_url_search_state'; @@ -65,7 +65,7 @@ export function useFetchSloGroups({ } = useKibana().services; const { dataView } = useCreateDataView({ - indexPatternString: SLO_SUMMARY_DESTINATION_INDEX_PATTERN, + indexPatternString: SUMMARY_DESTINATION_INDEX_PATTERN, }); const filters = useMemo(() => { diff --git a/x-pack/solutions/observability/plugins/slo/public/hooks/use_fetch_slo_list.ts b/x-pack/solutions/observability/plugins/slo/public/hooks/use_fetch_slo_list.ts index 2ed986fd1ffc8..9651588d1e418 100644 --- a/x-pack/solutions/observability/plugins/slo/public/hooks/use_fetch_slo_list.ts +++ b/x-pack/solutions/observability/plugins/slo/public/hooks/use_fetch_slo_list.ts @@ -10,10 +10,7 @@ import { i18n } from '@kbn/i18n'; import { FindSLOResponse } from '@kbn/slo-schema'; import { useQuery, useQueryClient } from '@tanstack/react-query'; import { useMemo } from 'react'; -import { - DEFAULT_SLO_PAGE_SIZE, - SLO_SUMMARY_DESTINATION_INDEX_PATTERN, -} from '../../common/constants'; +import { DEFAULT_SLO_PAGE_SIZE, SUMMARY_DESTINATION_INDEX_PATTERN } from '../../common/constants'; import { SearchState } from '../pages/slos/hooks/use_url_search_state'; import { useKibana } from './use_kibana'; import { sloKeys } from './query_key_factory'; @@ -63,7 +60,7 @@ export function useFetchSloList({ const queryClient = useQueryClient(); const { dataView } = useCreateDataView({ - indexPatternString: SLO_SUMMARY_DESTINATION_INDEX_PATTERN, + indexPatternString: SUMMARY_DESTINATION_INDEX_PATTERN, }); const filters = useMemo(() => { diff --git a/x-pack/solutions/observability/plugins/slo/public/pages/slos/components/grouped_slos/hooks/use_group_name.test.ts b/x-pack/solutions/observability/plugins/slo/public/pages/slos/components/grouped_slos/hooks/use_group_name.test.ts index fa2b5192665ea..46e1bfc6d2993 100644 --- a/x-pack/solutions/observability/plugins/slo/public/pages/slos/components/grouped_slos/hooks/use_group_name.test.ts +++ b/x-pack/solutions/observability/plugins/slo/public/pages/slos/components/grouped_slos/hooks/use_group_name.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { SLO_SUMMARY_DESTINATION_INDEX_PATTERN } from '../../../../../../common/constants'; +import { SUMMARY_DESTINATION_INDEX_PATTERN } from '../../../../../../common/constants'; import { GroupSummary } from '@kbn/slo-schema'; import { useGroupName } from './use_group_name'; @@ -57,18 +57,14 @@ describe('useGroupName', () => { }); it('returns the group name for local index', () => { - const groupName = useGroupName( - '_index', - SLO_SUMMARY_DESTINATION_INDEX_PATTERN, - {} as GroupSummary - ); + const groupName = useGroupName('_index', SUMMARY_DESTINATION_INDEX_PATTERN, {} as GroupSummary); expect(groupName).toBe('Local Kibana'); }); it('returns the group name for remote index', () => { const groupName = useGroupName( '_index', - `my-remote-cluster:${SLO_SUMMARY_DESTINATION_INDEX_PATTERN}`, + `my-remote-cluster:${SUMMARY_DESTINATION_INDEX_PATTERN}`, {} as GroupSummary ); expect(groupName).toBe('Remote Cluster: my-remote-cluster'); diff --git a/x-pack/solutions/observability/plugins/slo/public/pages/slos/hooks/use_fetch_slos_overview.ts b/x-pack/solutions/observability/plugins/slo/public/pages/slos/hooks/use_fetch_slos_overview.ts index 1e9246d97f795..4308b30571621 100644 --- a/x-pack/solutions/observability/plugins/slo/public/pages/slos/hooks/use_fetch_slos_overview.ts +++ b/x-pack/solutions/observability/plugins/slo/public/pages/slos/hooks/use_fetch_slos_overview.ts @@ -9,7 +9,7 @@ import { i18n } from '@kbn/i18n'; import { GetOverviewResponse } from '@kbn/slo-schema/src/rest_specs/routes/get_overview'; import { useQuery } from '@tanstack/react-query'; import { useMemo } from 'react'; -import { SLO_SUMMARY_DESTINATION_INDEX_PATTERN } from '../../../../common/constants'; +import { SUMMARY_DESTINATION_INDEX_PATTERN } from '../../../../common/constants'; import { sloKeys } from '../../../hooks/query_key_factory'; import { useCreateDataView } from '../../../hooks/use_create_data_view'; import { usePluginContext } from '../../../hooks/use_plugin_context'; @@ -45,7 +45,7 @@ export function useFetchSLOsOverview({ } = useKibana().services; const { dataView } = useCreateDataView({ - indexPatternString: SLO_SUMMARY_DESTINATION_INDEX_PATTERN, + indexPatternString: SUMMARY_DESTINATION_INDEX_PATTERN, }); const filters = useMemo(() => { diff --git a/x-pack/solutions/observability/plugins/slo/server/assets/component_templates/slo_mappings_template.ts b/x-pack/solutions/observability/plugins/slo/server/assets/component_templates/slI_mappings_template.ts similarity index 91% rename from x-pack/solutions/observability/plugins/slo/server/assets/component_templates/slo_mappings_template.ts rename to x-pack/solutions/observability/plugins/slo/server/assets/component_templates/slI_mappings_template.ts index 38227916a486d..4b0cfbb366ca4 100644 --- a/x-pack/solutions/observability/plugins/slo/server/assets/component_templates/slo_mappings_template.ts +++ b/x-pack/solutions/observability/plugins/slo/server/assets/component_templates/slI_mappings_template.ts @@ -5,10 +5,13 @@ * 2.0. */ import type { ClusterPutComponentTemplateRequest } from '@elastic/elasticsearch/lib/api/types'; -import { SLO_RESOURCES_VERSION } from '../../../common/constants'; +import { + SLI_COMPONENT_TEMPLATE_MAPPINGS_NAME, + SLO_RESOURCES_VERSION, +} from '../../../common/constants'; -export const getSLOMappingsTemplate = (name: string): ClusterPutComponentTemplateRequest => ({ - name, +export const SLI_MAPPINGS_TEMPLATE: ClusterPutComponentTemplateRequest = { + name: SLI_COMPONENT_TEMPLATE_MAPPINGS_NAME, template: { mappings: { properties: { @@ -109,4 +112,4 @@ export const getSLOMappingsTemplate = (name: string): ClusterPutComponentTemplat managed: true, managed_by: 'observability', }, -}); +}; diff --git a/x-pack/solutions/observability/plugins/slo/server/assets/component_templates/slo_settings_template.ts b/x-pack/solutions/observability/plugins/slo/server/assets/component_templates/slI_settings_template.ts similarity index 71% rename from x-pack/solutions/observability/plugins/slo/server/assets/component_templates/slo_settings_template.ts rename to x-pack/solutions/observability/plugins/slo/server/assets/component_templates/slI_settings_template.ts index 5e8845a050688..3b06438eb010d 100644 --- a/x-pack/solutions/observability/plugins/slo/server/assets/component_templates/slo_settings_template.ts +++ b/x-pack/solutions/observability/plugins/slo/server/assets/component_templates/slI_settings_template.ts @@ -5,10 +5,13 @@ * 2.0. */ -import { SLO_RESOURCES_VERSION } from '../../../common/constants'; +import { + SLI_COMPONENT_TEMPLATE_SETTINGS_NAME, + SLO_RESOURCES_VERSION, +} from '../../../common/constants'; -export const getSLOSettingsTemplate = (name: string) => ({ - name, +export const SLI_SETTINGS_TEMPLATE = { + name: SLI_COMPONENT_TEMPLATE_SETTINGS_NAME, template: { settings: { auto_expand_replicas: '0-1', @@ -21,4 +24,4 @@ export const getSLOSettingsTemplate = (name: string) => ({ managed: true, managed_by: 'observability', }, -}); +}; diff --git a/x-pack/solutions/observability/plugins/slo/server/assets/component_templates/slo_summary_mappings_template.ts b/x-pack/solutions/observability/plugins/slo/server/assets/component_templates/summary_mappings_template.ts similarity index 95% rename from x-pack/solutions/observability/plugins/slo/server/assets/component_templates/slo_summary_mappings_template.ts rename to x-pack/solutions/observability/plugins/slo/server/assets/component_templates/summary_mappings_template.ts index a130e45ade735..da4e3f4910f9f 100644 --- a/x-pack/solutions/observability/plugins/slo/server/assets/component_templates/slo_summary_mappings_template.ts +++ b/x-pack/solutions/observability/plugins/slo/server/assets/component_templates/summary_mappings_template.ts @@ -5,12 +5,13 @@ * 2.0. */ import type { ClusterPutComponentTemplateRequest } from '@elastic/elasticsearch/lib/api/types'; -import { SLO_RESOURCES_VERSION } from '../../../common/constants'; +import { + SLO_RESOURCES_VERSION, + SUMMARY_COMPONENT_TEMPLATE_MAPPINGS_NAME, +} from '../../../common/constants'; -export const getSLOSummaryMappingsTemplate = ( - name: string -): ClusterPutComponentTemplateRequest => ({ - name, +export const SUMMARY_MAPPINGS_TEMPLATE: ClusterPutComponentTemplateRequest = { + name: SUMMARY_COMPONENT_TEMPLATE_MAPPINGS_NAME, template: { mappings: { properties: { @@ -240,4 +241,4 @@ export const getSLOSummaryMappingsTemplate = ( managed: true, managed_by: 'observability', }, -}); +}; diff --git a/x-pack/solutions/observability/plugins/slo/server/assets/component_templates/slo_summary_settings_template.ts b/x-pack/solutions/observability/plugins/slo/server/assets/component_templates/summary_settings_template.ts similarity index 70% rename from x-pack/solutions/observability/plugins/slo/server/assets/component_templates/slo_summary_settings_template.ts rename to x-pack/solutions/observability/plugins/slo/server/assets/component_templates/summary_settings_template.ts index f9b18c7f62555..6424bb342a31e 100644 --- a/x-pack/solutions/observability/plugins/slo/server/assets/component_templates/slo_summary_settings_template.ts +++ b/x-pack/solutions/observability/plugins/slo/server/assets/component_templates/summary_settings_template.ts @@ -5,10 +5,13 @@ * 2.0. */ -import { SLO_RESOURCES_VERSION } from '../../../common/constants'; +import { + SLO_RESOURCES_VERSION, + SUMMARY_COMPONENT_TEMPLATE_SETTINGS_NAME, +} from '../../../common/constants'; -export const getSLOSummarySettingsTemplate = (name: string) => ({ - name, +export const SUMMARY_SETTINGS_TEMPLATE = { + name: SUMMARY_COMPONENT_TEMPLATE_SETTINGS_NAME, template: { settings: { auto_expand_replicas: '0-1', @@ -21,4 +24,4 @@ export const getSLOSummarySettingsTemplate = (name: string) => ({ managed: true, managed_by: 'observability', }, -}); +}; diff --git a/x-pack/solutions/observability/plugins/slo/server/assets/index_templates/slo_index_templates.ts b/x-pack/solutions/observability/plugins/slo/server/assets/index_templates/sli_index_template.ts similarity index 50% rename from x-pack/solutions/observability/plugins/slo/server/assets/index_templates/slo_index_templates.ts rename to x-pack/solutions/observability/plugins/slo/server/assets/index_templates/sli_index_template.ts index 6524d6e7d49cf..6b3447a72c8d4 100644 --- a/x-pack/solutions/observability/plugins/slo/server/assets/index_templates/slo_index_templates.ts +++ b/x-pack/solutions/observability/plugins/slo/server/assets/index_templates/sli_index_template.ts @@ -5,12 +5,18 @@ * 2.0. */ -import { SLO_RESOURCES_VERSION } from '../../../common/constants'; +import { + SLI_COMPONENT_TEMPLATE_MAPPINGS_NAME, + SLI_COMPONENT_TEMPLATE_SETTINGS_NAME, + SLI_INDEX_TEMPLATE_NAME, + SLI_INDEX_TEMPLATE_PATTERN, + SLO_RESOURCES_VERSION, +} from '../../../common/constants'; -export const getSLOIndexTemplate = (name: string, indexPattern: string, composedOf: string[]) => ({ - name, - index_patterns: [indexPattern], - composed_of: composedOf, +export const SLI_INDEX_TEMPLATE = { + name: SLI_INDEX_TEMPLATE_NAME, + index_patterns: [SLI_INDEX_TEMPLATE_PATTERN], + composed_of: [SLI_COMPONENT_TEMPLATE_MAPPINGS_NAME, SLI_COMPONENT_TEMPLATE_SETTINGS_NAME], priority: 500, _meta: { description: 'Template for SLO rollup data', @@ -18,4 +24,4 @@ export const getSLOIndexTemplate = (name: string, indexPattern: string, composed managed: true, managed_by: 'observability', }, -}); +}; diff --git a/x-pack/solutions/observability/plugins/slo/server/assets/index_templates/slo_summary_index_templates.ts b/x-pack/solutions/observability/plugins/slo/server/assets/index_templates/slo_summary_index_templates.ts deleted file mode 100644 index 3986273ca99ce..0000000000000 --- a/x-pack/solutions/observability/plugins/slo/server/assets/index_templates/slo_summary_index_templates.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 { SLO_RESOURCES_VERSION } from '../../../common/constants'; - -export const getSLOSummaryIndexTemplate = ( - name: string, - indexPattern: string, - composedOf: string[] -) => ({ - name, - index_patterns: [indexPattern], - composed_of: composedOf, - priority: 500, - _meta: { - description: 'SLO summary index template', - version: SLO_RESOURCES_VERSION, - managed: true, - managed_by: 'observability', - }, -}); diff --git a/x-pack/solutions/observability/plugins/slo/server/assets/index_templates/summary_index_template.ts b/x-pack/solutions/observability/plugins/slo/server/assets/index_templates/summary_index_template.ts new file mode 100644 index 0000000000000..fd70d9909d799 --- /dev/null +++ b/x-pack/solutions/observability/plugins/slo/server/assets/index_templates/summary_index_template.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 { + SLO_RESOURCES_VERSION, + SUMMARY_COMPONENT_TEMPLATE_MAPPINGS_NAME, + SUMMARY_COMPONENT_TEMPLATE_SETTINGS_NAME, + SUMMARY_INDEX_TEMPLATE_NAME, + SUMMARY_INDEX_TEMPLATE_PATTERN, +} from '../../../common/constants'; + +export const SUMMARY_INDEX_TEMPLATE = { + name: SUMMARY_INDEX_TEMPLATE_NAME, + index_patterns: [SUMMARY_INDEX_TEMPLATE_PATTERN], + composed_of: [SUMMARY_COMPONENT_TEMPLATE_MAPPINGS_NAME, SUMMARY_COMPONENT_TEMPLATE_SETTINGS_NAME], + priority: 500, + _meta: { + description: 'SLO summary index template', + version: SLO_RESOURCES_VERSION, + managed: true, + managed_by: 'observability', + }, +}; diff --git a/x-pack/solutions/observability/plugins/slo/server/assets/ingest_templates/slo_pipeline_template.ts b/x-pack/solutions/observability/plugins/slo/server/assets/ingest_templates/sli_pipeline_template.ts similarity index 92% rename from x-pack/solutions/observability/plugins/slo/server/assets/ingest_templates/slo_pipeline_template.ts rename to x-pack/solutions/observability/plugins/slo/server/assets/ingest_templates/sli_pipeline_template.ts index dc078f351eb3e..605e733d444e6 100644 --- a/x-pack/solutions/observability/plugins/slo/server/assets/ingest_templates/slo_pipeline_template.ts +++ b/x-pack/solutions/observability/plugins/slo/server/assets/ingest_templates/sli_pipeline_template.ts @@ -8,12 +8,12 @@ import { ALL_VALUE } from '@kbn/slo-schema'; import { getSLOPipelineId, - SLO_INGEST_PIPELINE_INDEX_NAME_PREFIX, + SLI_INGEST_PIPELINE_INDEX_NAME_PREFIX, SLO_RESOURCES_VERSION, } from '../../../common/constants'; import { SLODefinition } from '../../domain/models'; -export const getSLOPipelineTemplate = (slo: SLODefinition) => ({ +export const getSLIPipelineTemplate = (slo: SLODefinition) => ({ id: getSLOPipelineId(slo.id, slo.revision), description: `Ingest pipeline for SLO rollup data [id: ${slo.id}, revision: ${slo.revision}]`, processors: [ @@ -44,7 +44,7 @@ export const getSLOPipelineTemplate = (slo: SLODefinition) => ({ { date_index_name: { field: '@timestamp', - index_name_prefix: SLO_INGEST_PIPELINE_INDEX_NAME_PREFIX, + index_name_prefix: SLI_INGEST_PIPELINE_INDEX_NAME_PREFIX, date_rounding: 'M', date_formats: ['UNIX_MS', 'ISO8601', "yyyy-MM-dd'T'HH:mm:ss.SSSXX"], }, diff --git a/x-pack/solutions/observability/plugins/slo/server/assets/ingest_templates/slo_summary_pipeline_template.ts b/x-pack/solutions/observability/plugins/slo/server/assets/ingest_templates/summary_pipeline_template.ts similarity index 99% rename from x-pack/solutions/observability/plugins/slo/server/assets/ingest_templates/slo_summary_pipeline_template.ts rename to x-pack/solutions/observability/plugins/slo/server/assets/ingest_templates/summary_pipeline_template.ts index d269bdf1d6de9..d662ab9ca2e0c 100644 --- a/x-pack/solutions/observability/plugins/slo/server/assets/ingest_templates/slo_summary_pipeline_template.ts +++ b/x-pack/solutions/observability/plugins/slo/server/assets/ingest_templates/summary_pipeline_template.ts @@ -11,7 +11,7 @@ import { IBasePath } from '@kbn/core-http-server'; import { getSLOSummaryPipelineId, SLO_RESOURCES_VERSION } from '../../../common/constants'; import { SLODefinition } from '../../domain/models'; -export const getSLOSummaryPipelineTemplate = ( +export const getSummaryPipelineTemplate = ( slo: SLODefinition, spaceId: string, basePath: IBasePath diff --git a/x-pack/solutions/observability/plugins/slo/server/lib/collectors/fetcher.ts b/x-pack/solutions/observability/plugins/slo/server/lib/collectors/fetcher.ts index dfd47986ba38b..9eeaf385a3486 100644 --- a/x-pack/solutions/observability/plugins/slo/server/lib/collectors/fetcher.ts +++ b/x-pack/solutions/observability/plugins/slo/server/lib/collectors/fetcher.ts @@ -10,7 +10,7 @@ import { CollectorFetchContext } from '@kbn/usage-collection-plugin/server'; import { StoredSLODefinition } from '../../domain/models'; import { SO_SLO_TYPE } from '../../saved_objects'; import { Usage } from './type'; -import { SLO_SUMMARY_DESTINATION_INDEX_PATTERN } from '../../../common/constants'; +import { SUMMARY_DESTINATION_INDEX_PATTERN } from '../../../common/constants'; export const fetcher = async (context: CollectorFetchContext) => { const finder = context.soClient.createPointInTimeFinder({ @@ -19,7 +19,7 @@ export const fetcher = async (context: CollectorFetchContext) => { }); const totalInstances = await context.esClient.count({ - index: SLO_SUMMARY_DESTINATION_INDEX_PATTERN, + index: SUMMARY_DESTINATION_INDEX_PATTERN, query: { bool: { filter: [ diff --git a/x-pack/solutions/observability/plugins/slo/server/lib/rules/slo_burn_rate/lib/evaluate.ts b/x-pack/solutions/observability/plugins/slo/server/lib/rules/slo_burn_rate/lib/evaluate.ts index aa0979d34ba3b..957157cecda29 100644 --- a/x-pack/solutions/observability/plugins/slo/server/lib/rules/slo_burn_rate/lib/evaluate.ts +++ b/x-pack/solutions/observability/plugins/slo/server/lib/rules/slo_burn_rate/lib/evaluate.ts @@ -9,7 +9,7 @@ import { ElasticsearchClient } from '@kbn/core/server'; import { get } from 'lodash'; import { Duration, SLODefinition, toDurationUnit } from '../../../../domain/models'; import { BurnRateRuleParams } from '../types'; -import { SLO_DESTINATION_INDEX_PATTERN } from '../../../../../common/constants'; +import { SLI_DESTINATION_INDEX_PATTERN } from '../../../../../common/constants'; import { buildQuery, EvaluationAfterKey, @@ -72,7 +72,7 @@ async function queryAllResults( ): Promise { const queryAndAggs = buildQuery(startedAt, slo, params, lastAfterKey); const results = await esClient.search({ - index: SLO_DESTINATION_INDEX_PATTERN, + index: SLI_DESTINATION_INDEX_PATTERN, ...queryAndAggs, }); diff --git a/x-pack/solutions/observability/plugins/slo/server/lib/rules/slo_burn_rate/lib/summary_repository.ts b/x-pack/solutions/observability/plugins/slo/server/lib/rules/slo_burn_rate/lib/summary_repository.ts index 361b3c1376c6e..67c4deedbe332 100644 --- a/x-pack/solutions/observability/plugins/slo/server/lib/rules/slo_burn_rate/lib/summary_repository.ts +++ b/x-pack/solutions/observability/plugins/slo/server/lib/rules/slo_burn_rate/lib/summary_repository.ts @@ -7,7 +7,7 @@ import { ElasticsearchClient } from '@kbn/core/server'; import { SLODefinition } from '../../../../domain/models'; -import { SLO_SUMMARY_DESTINATION_INDEX_PATTERN } from '../../../../../common/constants'; +import { SUMMARY_DESTINATION_INDEX_PATTERN } from '../../../../../common/constants'; import { EsSummaryDocument } from '../../../../services/summary_transform_generator/helpers/create_temp_summary'; export async function getSloSummary( @@ -17,7 +17,7 @@ export async function getSloSummary( ) { try { const res = await esClient.search({ - index: SLO_SUMMARY_DESTINATION_INDEX_PATTERN, + index: SUMMARY_DESTINATION_INDEX_PATTERN, body: { query: { bool: { diff --git a/x-pack/solutions/observability/plugins/slo/server/plugin.ts b/x-pack/solutions/observability/plugins/slo/server/plugin.ts index c7a5a1dda3280..e9df927f33b19 100644 --- a/x-pack/solutions/observability/plugins/slo/server/plugin.ts +++ b/x-pack/solutions/observability/plugins/slo/server/plugin.ts @@ -28,7 +28,7 @@ import { registerServerRoutes } from './routes/register_routes'; import { SLORoutesDependencies } from './routes/types'; import { SO_SLO_TYPE, slo } from './saved_objects'; import { SO_SLO_SETTINGS_TYPE, sloSettings } from './saved_objects/slo_settings'; -import { DefaultResourceInstaller, DefaultSLOInstaller } from './services'; +import { DefaultResourceInstaller } from './services'; import { SloOrphanSummaryCleanupTask } from './services/tasks/orphan_summary_cleanup_task'; import type { SLOConfig, @@ -157,8 +157,7 @@ export class SLOPlugin .then(async ([coreStart, pluginStart]) => { const esInternalClient = coreStart.elasticsearch.client.asInternalUser; const sloResourceInstaller = new DefaultResourceInstaller(esInternalClient, this.logger); - const sloInstaller = new DefaultSLOInstaller(sloResourceInstaller, this.logger); - await sloInstaller.install(); + await sloResourceInstaller.ensureCommonResourcesInstalled(); }) .catch(() => { // noop - error already logged from the installer diff --git a/x-pack/solutions/observability/plugins/slo/server/routes/slo/create_slo.ts b/x-pack/solutions/observability/plugins/slo/server/routes/slo/create_slo.ts new file mode 100644 index 0000000000000..7b4db6e077e6e --- /dev/null +++ b/x-pack/solutions/observability/plugins/slo/server/routes/slo/create_slo.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 { createSLOParamsSchema } from '@kbn/slo-schema'; +import { createSloServerRoute } from '../create_slo_server_route'; +import { assertPlatinumLicense } from './utils/assert_platinum_license'; +import { getSpaceId } from './utils/get_space_id'; +import { createTransformGenerators } from '../../services/transform_generators'; +import { DefaultSummaryTransformGenerator } from '../../services/summary_transform_generator/summary_transform_generator'; +import { executeWithErrorHandler } from '../../errors'; +import { + CreateSLO, + DefaultSummaryTransformManager, + DefaultTransformManager, + KibanaSavedObjectsSLORepository, +} from '../../services'; + +export const createSLORoute = createSloServerRoute({ + endpoint: 'POST /api/observability/slos 2023-10-31', + options: { access: 'public' }, + security: { + authz: { + requiredPrivileges: ['slo_write'], + }, + }, + params: createSLOParamsSchema, + handler: async ({ context, params, logger, request, plugins, corePlugins }) => { + await assertPlatinumLicense(plugins); + + const sloContext = await context.slo; + const dataViews = await plugins.dataViews.start(); + const core = await context.core; + const userId = core.security.authc.getCurrentUser()?.username!; + const scopedClusterClient = core.elasticsearch.client; + const esClient = core.elasticsearch.client.asCurrentUser; + const soClient = core.savedObjects.client; + const basePath = corePlugins.http.basePath; + const repository = new KibanaSavedObjectsSLORepository(soClient, logger); + + const [spaceId, dataViewsService] = await Promise.all([ + getSpaceId(plugins, request), + dataViews.dataViewsServiceFactory(soClient, esClient), + ]); + + const transformGenerators = createTransformGenerators( + spaceId, + dataViewsService, + sloContext.isServerless + ); + + const transformManager = new DefaultTransformManager( + transformGenerators, + scopedClusterClient, + logger + ); + const summaryTransformManager = new DefaultSummaryTransformManager( + new DefaultSummaryTransformGenerator(), + scopedClusterClient, + logger + ); + const createSLO = new CreateSLO( + esClient, + scopedClusterClient, + repository, + transformManager, + summaryTransformManager, + logger, + spaceId, + basePath, + userId + ); + + return await executeWithErrorHandler(() => createSLO.execute(params.body)); + }, +}); diff --git a/x-pack/solutions/observability/plugins/slo/server/routes/slo/delete_instances.ts b/x-pack/solutions/observability/plugins/slo/server/routes/slo/delete_instances.ts new file mode 100644 index 0000000000000..be92f87332b88 --- /dev/null +++ b/x-pack/solutions/observability/plugins/slo/server/routes/slo/delete_instances.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 { deleteSLOInstancesParamsSchema } from '@kbn/slo-schema'; +import { executeWithErrorHandler } from '../../errors'; +import { DeleteSLOInstances } from '../../services'; +import { createSloServerRoute } from '../create_slo_server_route'; +import { assertPlatinumLicense } from './utils/assert_platinum_license'; + +export const deleteSloInstancesRoute = createSloServerRoute({ + endpoint: 'POST /api/observability/slos/_delete_instances 2023-10-31', + options: { access: 'public' }, + security: { + authz: { + requiredPrivileges: ['slo_write'], + }, + }, + params: deleteSLOInstancesParamsSchema, + handler: async ({ response, context, params, plugins }) => { + await assertPlatinumLicense(plugins); + + const esClient = (await context.core).elasticsearch.client.asCurrentUser; + const deleteSloInstances = new DeleteSLOInstances(esClient); + + await executeWithErrorHandler(() => deleteSloInstances.execute(params.body)); + return response.noContent(); + }, +}); diff --git a/x-pack/solutions/observability/plugins/slo/server/routes/slo/delete_slo.ts b/x-pack/solutions/observability/plugins/slo/server/routes/slo/delete_slo.ts new file mode 100644 index 0000000000000..98c5f803c4d12 --- /dev/null +++ b/x-pack/solutions/observability/plugins/slo/server/routes/slo/delete_slo.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 { deleteSLOParamsSchema } from '@kbn/slo-schema'; +import { executeWithErrorHandler } from '../../errors'; +import { + DefaultSummaryTransformManager, + DefaultTransformManager, + DeleteSLO, + KibanaSavedObjectsSLORepository, +} from '../../services'; +import { DefaultSummaryTransformGenerator } from '../../services/summary_transform_generator/summary_transform_generator'; +import { createTransformGenerators } from '../../services/transform_generators'; +import { createSloServerRoute } from '../create_slo_server_route'; +import { assertPlatinumLicense } from './utils/assert_platinum_license'; +import { getSpaceId } from './utils/get_space_id'; + +export const deleteSLORoute = createSloServerRoute({ + endpoint: 'DELETE /api/observability/slos/{id} 2023-10-31', + options: { access: 'public' }, + security: { + authz: { + requiredPrivileges: ['slo_write'], + }, + }, + params: deleteSLOParamsSchema, + handler: async ({ request, response, context, params, logger, plugins }) => { + await assertPlatinumLicense(plugins); + + const spaceId = await getSpaceId(plugins, request); + const dataViews = await plugins.dataViews.start(); + + const sloContext = await context.slo; + const core = await context.core; + const scopedClusterClient = core.elasticsearch.client; + const esClient = core.elasticsearch.client.asCurrentUser; + const soClient = core.savedObjects.client; + + const alerting = await plugins.alerting.start(); + const rulesClient = await alerting.getRulesClientWithRequest(request); + + const dataViewsService = await dataViews.dataViewsServiceFactory(soClient, esClient); + + const transformGenerators = createTransformGenerators( + spaceId, + dataViewsService, + sloContext.isServerless + ); + const repository = new KibanaSavedObjectsSLORepository(soClient, logger); + const transformManager = new DefaultTransformManager( + transformGenerators, + scopedClusterClient, + logger + ); + + const summaryTransformManager = new DefaultSummaryTransformManager( + new DefaultSummaryTransformGenerator(), + scopedClusterClient, + logger + ); + + const deleteSLO = new DeleteSLO( + repository, + transformManager, + summaryTransformManager, + esClient, + scopedClusterClient, + rulesClient + ); + + await executeWithErrorHandler(() => deleteSLO.execute(params.path.id)); + return response.noContent(); + }, +}); diff --git a/x-pack/solutions/observability/plugins/slo/server/routes/slo/disable_slo.ts b/x-pack/solutions/observability/plugins/slo/server/routes/slo/disable_slo.ts new file mode 100644 index 0000000000000..ac527c39be1a7 --- /dev/null +++ b/x-pack/solutions/observability/plugins/slo/server/routes/slo/disable_slo.ts @@ -0,0 +1,66 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { manageSLOParamsSchema } from '@kbn/slo-schema'; +import { executeWithErrorHandler } from '../../errors'; +import { + DefaultSummaryTransformManager, + DefaultTransformManager, + KibanaSavedObjectsSLORepository, +} from '../../services'; +import { ManageSLO } from '../../services/manage_slo'; +import { DefaultSummaryTransformGenerator } from '../../services/summary_transform_generator/summary_transform_generator'; +import { createTransformGenerators } from '../../services/transform_generators'; +import { createSloServerRoute } from '../create_slo_server_route'; +import { assertPlatinumLicense } from './utils/assert_platinum_license'; +import { getSpaceId } from './utils/get_space_id'; + +export const disableSLORoute = createSloServerRoute({ + endpoint: 'POST /api/observability/slos/{id}/disable 2023-10-31', + options: { access: 'public' }, + security: { + authz: { + requiredPrivileges: ['slo_write'], + }, + }, + params: manageSLOParamsSchema, + handler: async ({ response, request, context, params, logger, plugins }) => { + await assertPlatinumLicense(plugins); + + const spaceId = await getSpaceId(plugins, request); + const dataViews = await plugins.dataViews.start(); + + const sloContext = await context.slo; + const core = await context.core; + const scopedClusterClient = core.elasticsearch.client; + const soClient = core.savedObjects.client; + const esClient = core.elasticsearch.client.asCurrentUser; + const dataViewsService = await dataViews.dataViewsServiceFactory(soClient, esClient); + const repository = new KibanaSavedObjectsSLORepository(soClient, logger); + + const transformGenerators = createTransformGenerators( + spaceId, + dataViewsService, + sloContext.isServerless + ); + const transformManager = new DefaultTransformManager( + transformGenerators, + scopedClusterClient, + logger + ); + const summaryTransformManager = new DefaultSummaryTransformManager( + new DefaultSummaryTransformGenerator(), + scopedClusterClient, + logger + ); + + const manageSLO = new ManageSLO(repository, transformManager, summaryTransformManager); + + await executeWithErrorHandler(() => manageSLO.disable(params.path.id)); + return response.noContent(); + }, +}); diff --git a/x-pack/solutions/observability/plugins/slo/server/routes/slo/enable_slo.ts b/x-pack/solutions/observability/plugins/slo/server/routes/slo/enable_slo.ts new file mode 100644 index 0000000000000..5227817cd3e48 --- /dev/null +++ b/x-pack/solutions/observability/plugins/slo/server/routes/slo/enable_slo.ts @@ -0,0 +1,67 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { manageSLOParamsSchema } from '@kbn/slo-schema'; +import { executeWithErrorHandler } from '../../errors'; +import { + DefaultSummaryTransformManager, + DefaultTransformManager, + KibanaSavedObjectsSLORepository, +} from '../../services'; +import { ManageSLO } from '../../services/manage_slo'; +import { DefaultSummaryTransformGenerator } from '../../services/summary_transform_generator/summary_transform_generator'; +import { createTransformGenerators } from '../../services/transform_generators'; +import { createSloServerRoute } from '../create_slo_server_route'; +import { assertPlatinumLicense } from './utils/assert_platinum_license'; +import { getSpaceId } from './utils/get_space_id'; + +export const enableSLORoute = createSloServerRoute({ + endpoint: 'POST /api/observability/slos/{id}/enable 2023-10-31', + options: { access: 'public' }, + security: { + authz: { + requiredPrivileges: ['slo_write'], + }, + }, + params: manageSLOParamsSchema, + handler: async ({ request, response, context, params, logger, plugins }) => { + await assertPlatinumLicense(plugins); + + const spaceId = await getSpaceId(plugins, request); + const dataViews = await plugins.dataViews.start(); + const sloContext = await context.slo; + const core = await context.core; + const scopedClusterClient = core.elasticsearch.client; + const soClient = core.savedObjects.client; + const esClient = core.elasticsearch.client.asCurrentUser; + const dataViewsService = await dataViews.dataViewsServiceFactory(soClient, esClient); + const repository = new KibanaSavedObjectsSLORepository(soClient, logger); + + const transformGenerators = createTransformGenerators( + spaceId, + dataViewsService, + sloContext.isServerless + ); + + const transformManager = new DefaultTransformManager( + transformGenerators, + scopedClusterClient, + logger + ); + const summaryTransformManager = new DefaultSummaryTransformManager( + new DefaultSummaryTransformGenerator(), + scopedClusterClient, + logger + ); + + const manageSLO = new ManageSLO(repository, transformManager, summaryTransformManager); + + await executeWithErrorHandler(() => manageSLO.enable(params.path.id)); + + return response.noContent(); + }, +}); diff --git a/x-pack/solutions/observability/plugins/slo/server/routes/slo/fetch_health.ts b/x-pack/solutions/observability/plugins/slo/server/routes/slo/fetch_health.ts new file mode 100644 index 0000000000000..2e093006e7cbe --- /dev/null +++ b/x-pack/solutions/observability/plugins/slo/server/routes/slo/fetch_health.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 { fetchSLOHealthParamsSchema } from '@kbn/slo-schema'; +import { executeWithErrorHandler } from '../../errors'; +import { GetSLOHealth, KibanaSavedObjectsSLORepository } from '../../services'; +import { createSloServerRoute } from '../create_slo_server_route'; +import { assertPlatinumLicense } from './utils/assert_platinum_license'; + +export const fetchSloHealthRoute = createSloServerRoute({ + endpoint: 'POST /internal/observability/slos/_health', + options: { access: 'internal' }, + security: { + authz: { + requiredPrivileges: ['slo_read'], + }, + }, + params: fetchSLOHealthParamsSchema, + handler: async ({ context, params, logger, plugins }) => { + await assertPlatinumLicense(plugins); + + const core = await context.core; + const scopedClusterClient = core.elasticsearch.client; + const soClient = core.savedObjects.client; + const esClient = core.elasticsearch.client.asCurrentUser; + const repository = new KibanaSavedObjectsSLORepository(soClient, logger); + + const getSLOHealth = new GetSLOHealth(esClient, scopedClusterClient, repository); + + return await executeWithErrorHandler(() => getSLOHealth.execute(params.body)); + }, +}); diff --git a/x-pack/solutions/observability/plugins/slo/server/routes/slo/fetch_historical_summary.ts b/x-pack/solutions/observability/plugins/slo/server/routes/slo/fetch_historical_summary.ts new file mode 100644 index 0000000000000..ac41836445df4 --- /dev/null +++ b/x-pack/solutions/observability/plugins/slo/server/routes/slo/fetch_historical_summary.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 { fetchHistoricalSummaryParamsSchema } from '@kbn/slo-schema'; +import { executeWithErrorHandler } from '../../errors'; +import { DefaultHistoricalSummaryClient } from '../../services/historical_summary_client'; +import { createSloServerRoute } from '../create_slo_server_route'; +import { assertPlatinumLicense } from './utils/assert_platinum_license'; + +export const fetchHistoricalSummary = createSloServerRoute({ + endpoint: 'POST /internal/observability/slos/_historical_summary', + options: { access: 'internal' }, + security: { + authz: { + requiredPrivileges: ['slo_read'], + }, + }, + params: fetchHistoricalSummaryParamsSchema, + handler: async ({ context, params, plugins }) => { + await assertPlatinumLicense(plugins); + + const esClient = (await context.core).elasticsearch.client.asCurrentUser; + const historicalSummaryClient = new DefaultHistoricalSummaryClient(esClient); + + return await executeWithErrorHandler(() => historicalSummaryClient.fetch(params.body)); + }, +}); diff --git a/x-pack/solutions/observability/plugins/slo/server/routes/slo/find_definitions.ts b/x-pack/solutions/observability/plugins/slo/server/routes/slo/find_definitions.ts new file mode 100644 index 0000000000000..b7e05e51b5d68 --- /dev/null +++ b/x-pack/solutions/observability/plugins/slo/server/routes/slo/find_definitions.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 { findSloDefinitionsParamsSchema } from '@kbn/slo-schema'; +import { executeWithErrorHandler } from '../../errors'; +import { KibanaSavedObjectsSLORepository } from '../../services'; +import { FindSLODefinitions } from '../../services/find_slo_definitions'; +import { createSloServerRoute } from '../create_slo_server_route'; +import { assertPlatinumLicense } from './utils/assert_platinum_license'; + +export const findSloDefinitionsRoute = createSloServerRoute({ + endpoint: 'GET /api/observability/slos/_definitions 2023-10-31', + options: { access: 'public' }, + security: { + authz: { + requiredPrivileges: ['slo_read'], + }, + }, + params: findSloDefinitionsParamsSchema, + handler: async ({ context, params, logger, plugins }) => { + await assertPlatinumLicense(plugins); + + const soClient = (await context.core).savedObjects.client; + const repository = new KibanaSavedObjectsSLORepository(soClient, logger); + const findSloDefinitions = new FindSLODefinitions(repository); + + return await executeWithErrorHandler(() => findSloDefinitions.execute(params?.query ?? {})); + }, +}); diff --git a/x-pack/solutions/observability/plugins/slo/server/routes/slo/find_groups.ts b/x-pack/solutions/observability/plugins/slo/server/routes/slo/find_groups.ts new file mode 100644 index 0000000000000..20fd53c1460ca --- /dev/null +++ b/x-pack/solutions/observability/plugins/slo/server/routes/slo/find_groups.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 { findSLOGroupsParamsSchema } from '@kbn/slo-schema'; +import { executeWithErrorHandler } from '../../errors'; +import { FindSLOGroups } from '../../services'; +import { createSloServerRoute } from '../create_slo_server_route'; +import { assertPlatinumLicense } from './utils/assert_platinum_license'; +import { getSpaceId } from './utils/get_space_id'; + +export const findSLOGroupsRoute = createSloServerRoute({ + endpoint: 'GET /internal/observability/slos/_groups', + options: { access: 'internal' }, + security: { + authz: { + requiredPrivileges: ['slo_read'], + }, + }, + params: findSLOGroupsParamsSchema, + handler: async ({ context, request, params, logger, plugins }) => { + await assertPlatinumLicense(plugins); + + const spaceId = await getSpaceId(plugins, request); + const soClient = (await context.core).savedObjects.client; + const coreContext = context.core; + const esClient = (await coreContext).elasticsearch.client.asCurrentUser; + const findSLOGroups = new FindSLOGroups(esClient, soClient, logger, spaceId); + return await executeWithErrorHandler(() => findSLOGroups.execute(params?.query ?? {})); + }, +}); diff --git a/x-pack/solutions/observability/plugins/slo/server/routes/slo/find_slo.ts b/x-pack/solutions/observability/plugins/slo/server/routes/slo/find_slo.ts new file mode 100644 index 0000000000000..bfc17b55ca64f --- /dev/null +++ b/x-pack/solutions/observability/plugins/slo/server/routes/slo/find_slo.ts @@ -0,0 +1,38 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { findSLOParamsSchema } from '@kbn/slo-schema'; +import { executeWithErrorHandler } from '../../errors'; +import { FindSLO, KibanaSavedObjectsSLORepository } from '../../services'; +import { DefaultSummarySearchClient } from '../../services/summary_search_client/summary_search_client'; +import { createSloServerRoute } from '../create_slo_server_route'; +import { assertPlatinumLicense } from './utils/assert_platinum_license'; +import { getSpaceId } from './utils/get_space_id'; + +export const findSLORoute = createSloServerRoute({ + endpoint: 'GET /api/observability/slos 2023-10-31', + options: { access: 'public' }, + security: { + authz: { + requiredPrivileges: ['slo_read'], + }, + }, + params: findSLOParamsSchema, + handler: async ({ context, request, params, logger, plugins }) => { + await assertPlatinumLicense(plugins); + + const spaceId = await getSpaceId(plugins, request); + const soClient = (await context.core).savedObjects.client; + const esClient = (await context.core).elasticsearch.client.asCurrentUser; + const repository = new KibanaSavedObjectsSLORepository(soClient, logger); + const summarySearchClient = new DefaultSummarySearchClient(esClient, soClient, logger, spaceId); + + const findSLO = new FindSLO(repository, summarySearchClient); + + return await executeWithErrorHandler(() => findSLO.execute(params?.query ?? {})); + }, +}); diff --git a/x-pack/solutions/observability/plugins/slo/server/routes/slo/get_diagnosis.ts b/x-pack/solutions/observability/plugins/slo/server/routes/slo/get_diagnosis.ts new file mode 100644 index 0000000000000..1fc392d08bb0e --- /dev/null +++ b/x-pack/solutions/observability/plugins/slo/server/routes/slo/get_diagnosis.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 { errors } from '@elastic/elasticsearch'; +import { failedDependency, forbidden } from '@hapi/boom'; +import { getGlobalDiagnosis } from '../../services/get_diagnosis'; +import { createSloServerRoute } from '../create_slo_server_route'; + +export const getDiagnosisRoute = createSloServerRoute({ + endpoint: 'GET /internal/observability/slos/_diagnosis', + options: { access: 'internal' }, + security: { + authz: { + enabled: false, + reason: 'The endpoint is used to diagnose SLOs and does not require any specific privileges.', + }, + }, + params: undefined, + handler: async ({ context, plugins }) => { + const esClient = (await context.core).elasticsearch.client.asCurrentUser; + const licensing = await plugins.licensing.start(); + + try { + const response = await getGlobalDiagnosis(esClient, licensing); + return response; + } catch (error) { + if (error instanceof errors.ResponseError && error.statusCode === 403) { + throw forbidden('Insufficient Elasticsearch cluster permissions to access feature.'); + } + throw failedDependency(error); + } + }, +}); diff --git a/x-pack/solutions/observability/plugins/slo/server/routes/slo/get_groupings.ts b/x-pack/solutions/observability/plugins/slo/server/routes/slo/get_groupings.ts new file mode 100644 index 0000000000000..f59b89da77d29 --- /dev/null +++ b/x-pack/solutions/observability/plugins/slo/server/routes/slo/get_groupings.ts @@ -0,0 +1,45 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { getSLOGroupingsParamsSchema } from '@kbn/slo-schema'; +import { executeWithErrorHandler } from '../../errors'; +import { KibanaSavedObjectsSLORepository } from '../../services'; +import { GetSLOGroupings } from '../../services/get_slo_groupings'; +import { SloDefinitionClient } from '../../services/slo_definition_client'; +import { getSloSettings } from '../../services/slo_settings'; +import { createSloServerRoute } from '../create_slo_server_route'; +import { assertPlatinumLicense } from './utils/assert_platinum_license'; +import { getSpaceId } from './utils/get_space_id'; + +export const getSLOGroupingsRoute = createSloServerRoute({ + endpoint: 'GET /internal/observability/slos/{id}/_groupings', + options: { access: 'internal' }, + security: { + authz: { + requiredPrivileges: ['slo_read'], + }, + }, + params: getSLOGroupingsParamsSchema, + handler: async ({ context, params, request, logger, plugins }) => { + await assertPlatinumLicense(plugins); + const soClient = (await context.core).savedObjects.client; + const esClient = (await context.core).elasticsearch.client.asCurrentUser; + const [spaceId, settings] = await Promise.all([ + getSpaceId(plugins, request), + getSloSettings(soClient), + ]); + + const repository = new KibanaSavedObjectsSLORepository(soClient, logger); + const definitionClient = new SloDefinitionClient(repository, esClient, logger); + + const getSLOGroupings = new GetSLOGroupings(definitionClient, esClient, settings, spaceId); + + return await executeWithErrorHandler(() => + getSLOGroupings.execute(params.path.id, params.query) + ); + }, +}); diff --git a/x-pack/solutions/observability/plugins/slo/server/routes/slo/get_preview_data.ts b/x-pack/solutions/observability/plugins/slo/server/routes/slo/get_preview_data.ts new file mode 100644 index 0000000000000..72e71f1c00dae --- /dev/null +++ b/x-pack/solutions/observability/plugins/slo/server/routes/slo/get_preview_data.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 { getPreviewDataParamsSchema } from '@kbn/slo-schema'; +import { GetPreviewData } from '../../services/get_preview_data'; +import { createSloServerRoute } from '../create_slo_server_route'; +import { assertPlatinumLicense } from './utils/assert_platinum_license'; +import { getSpaceId } from './utils/get_space_id'; + +export const getPreviewData = createSloServerRoute({ + endpoint: 'POST /internal/observability/slos/_preview', + options: { access: 'internal' }, + security: { + authz: { + requiredPrivileges: ['slo_read'], + }, + }, + params: getPreviewDataParamsSchema, + handler: async ({ request, context, params, plugins }) => { + await assertPlatinumLicense(plugins); + + const spaceId = await getSpaceId(plugins, request); + const dataViews = await plugins.dataViews.start(); + + const esClient = (await context.core).elasticsearch.client.asCurrentUser; + const soClient = (await context.core).savedObjects.client; + const dataViewsService = await dataViews.dataViewsServiceFactory(soClient, esClient); + const service = new GetPreviewData(esClient, spaceId, dataViewsService); + return await service.execute(params.body); + }, +}); diff --git a/x-pack/solutions/observability/plugins/slo/server/routes/slo/get_slo.ts b/x-pack/solutions/observability/plugins/slo/server/routes/slo/get_slo.ts new file mode 100644 index 0000000000000..812f93c2683a4 --- /dev/null +++ b/x-pack/solutions/observability/plugins/slo/server/routes/slo/get_slo.ts @@ -0,0 +1,47 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { getSLOParamsSchema } from '@kbn/slo-schema'; +import { executeWithErrorHandler } from '../../errors'; +import { + DefaultBurnRatesClient, + DefaultSummaryClient, + GetSLO, + KibanaSavedObjectsSLORepository, +} from '../../services'; +import { SloDefinitionClient } from '../../services/slo_definition_client'; +import { createSloServerRoute } from '../create_slo_server_route'; +import { assertPlatinumLicense } from './utils/assert_platinum_license'; +import { getSpaceId } from './utils/get_space_id'; + +export const getSLORoute = createSloServerRoute({ + endpoint: 'GET /api/observability/slos/{id} 2023-10-31', + options: { access: 'public' }, + security: { + authz: { + requiredPrivileges: ['slo_read'], + }, + }, + params: getSLOParamsSchema, + handler: async ({ request, context, params, logger, plugins }) => { + await assertPlatinumLicense(plugins); + + const spaceId = await getSpaceId(plugins, request); + + const soClient = (await context.core).savedObjects.client; + const esClient = (await context.core).elasticsearch.client.asCurrentUser; + const repository = new KibanaSavedObjectsSLORepository(soClient, logger); + const burnRatesClient = new DefaultBurnRatesClient(esClient); + const summaryClient = new DefaultSummaryClient(esClient, burnRatesClient); + const definitionClient = new SloDefinitionClient(repository, esClient, logger); + const getSLO = new GetSLO(definitionClient, summaryClient); + + return await executeWithErrorHandler(() => + getSLO.execute(params.path.id, spaceId, params.query) + ); + }, +}); diff --git a/x-pack/solutions/observability/plugins/slo/server/routes/slo/get_slo_burn_rates.ts b/x-pack/solutions/observability/plugins/slo/server/routes/slo/get_slo_burn_rates.ts new file mode 100644 index 0000000000000..111b10c713ae3 --- /dev/null +++ b/x-pack/solutions/observability/plugins/slo/server/routes/slo/get_slo_burn_rates.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 { getSLOBurnRatesParamsSchema } from '@kbn/slo-schema'; +import { executeWithErrorHandler } from '../../errors'; +import { getBurnRates } from '../../services/get_burn_rates'; +import { createSloServerRoute } from '../create_slo_server_route'; +import { assertPlatinumLicense } from './utils/assert_platinum_license'; +import { getSpaceId } from './utils/get_space_id'; + +export const getSloBurnRates = createSloServerRoute({ + endpoint: 'POST /internal/observability/slos/{id}/_burn_rates', + options: { access: 'internal' }, + security: { + authz: { + requiredPrivileges: ['slo_read'], + }, + }, + params: getSLOBurnRatesParamsSchema, + handler: async ({ request, context, params, logger, plugins }) => { + await assertPlatinumLicense(plugins); + + const spaceId = await getSpaceId(plugins, request); + + const esClient = (await context.core).elasticsearch.client.asCurrentUser; + const soClient = (await context.core).savedObjects.client; + const { instanceId, windows, remoteName } = params.body; + + return await executeWithErrorHandler(() => + getBurnRates({ + instanceId, + spaceId, + windows, + remoteName, + sloId: params.path.id, + services: { + soClient, + esClient, + logger, + }, + }) + ); + }, +}); diff --git a/x-pack/solutions/observability/plugins/slo/server/routes/slo/get_slo_settings.ts b/x-pack/solutions/observability/plugins/slo/server/routes/slo/get_slo_settings.ts new file mode 100644 index 0000000000000..5049191c89dbb --- /dev/null +++ b/x-pack/solutions/observability/plugins/slo/server/routes/slo/get_slo_settings.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 { executeWithErrorHandler } from '../../errors'; +import { getSloSettings } from '../../services/slo_settings'; +import { createSloServerRoute } from '../create_slo_server_route'; +import { assertPlatinumLicense } from './utils/assert_platinum_license'; + +export const getSloSettingsRoute = createSloServerRoute({ + endpoint: 'GET /internal/slo/settings', + options: { access: 'internal' }, + security: { + authz: { + requiredPrivileges: ['slo_read'], + }, + }, + handler: async ({ context, plugins }) => { + await assertPlatinumLicense(plugins); + + const soClient = (await context.core).savedObjects.client; + + return await executeWithErrorHandler(() => getSloSettings(soClient)); + }, +}); diff --git a/x-pack/solutions/observability/plugins/slo/server/routes/slo/get_slos_overview.ts b/x-pack/solutions/observability/plugins/slo/server/routes/slo/get_slos_overview.ts new file mode 100644 index 0000000000000..4c6981236ff58 --- /dev/null +++ b/x-pack/solutions/observability/plugins/slo/server/routes/slo/get_slos_overview.ts @@ -0,0 +1,49 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { getOverviewParamsSchema } from '@kbn/slo-schema/src/rest_specs/routes/get_overview'; +import { executeWithErrorHandler } from '../../errors'; +import { GetSLOsOverview } from '../../services/get_slos_overview'; +import { createSloServerRoute } from '../create_slo_server_route'; +import { assertPlatinumLicense } from './utils/assert_platinum_license'; +import { getSpaceId } from './utils/get_space_id'; + +export const getSLOsOverview = createSloServerRoute({ + endpoint: 'GET /internal/observability/slos/overview', + options: { access: 'internal' }, + security: { + authz: { + requiredPrivileges: ['slo_read'], + }, + }, + params: getOverviewParamsSchema, + handler: async ({ context, params, request, logger, plugins }) => { + await assertPlatinumLicense(plugins); + + const soClient = (await context.core).savedObjects.client; + const esClient = (await context.core).elasticsearch.client.asCurrentUser; + + const ruleRegistry = await plugins.ruleRegistry.start(); + const racClient = await ruleRegistry.getRacClientWithRequest(request); + + const spaceId = await getSpaceId(plugins, request); + + const alerting = await plugins.alerting.start(); + const rulesClient = await alerting.getRulesClientWithRequest(request); + + const slosOverview = new GetSLOsOverview( + soClient, + esClient, + spaceId, + logger, + rulesClient, + racClient + ); + + return await executeWithErrorHandler(() => slosOverview.execute(params?.query ?? {})); + }, +}); diff --git a/x-pack/solutions/observability/plugins/slo/server/routes/slo/get_suggestions.ts b/x-pack/solutions/observability/plugins/slo/server/routes/slo/get_suggestions.ts new file mode 100644 index 0000000000000..57a0d4bd7c15d --- /dev/null +++ b/x-pack/solutions/observability/plugins/slo/server/routes/slo/get_suggestions.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 { executeWithErrorHandler } from '../../errors'; +import { GetSLOSuggestions } from '../../services/get_slo_suggestions'; +import { createSloServerRoute } from '../create_slo_server_route'; +import { assertPlatinumLicense } from './utils/assert_platinum_license'; + +export const getSLOSuggestionsRoute = createSloServerRoute({ + endpoint: 'GET /internal/observability/slos/suggestions', + options: { access: 'internal' }, + security: { + authz: { + requiredPrivileges: ['slo_read'], + }, + }, + handler: async ({ context, plugins }) => { + await assertPlatinumLicense(plugins); + + const soClient = (await context.core).savedObjects.client; + const getSLOSuggestions = new GetSLOSuggestions(soClient); + return await executeWithErrorHandler(() => getSLOSuggestions.execute()); + }, +}); diff --git a/x-pack/solutions/observability/plugins/slo/server/routes/slo/inspect_slo.ts b/x-pack/solutions/observability/plugins/slo/server/routes/slo/inspect_slo.ts new file mode 100644 index 0000000000000..550466c42a69b --- /dev/null +++ b/x-pack/solutions/observability/plugins/slo/server/routes/slo/inspect_slo.ts @@ -0,0 +1,76 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { createSLOParamsSchema } from '@kbn/slo-schema'; +import { executeWithErrorHandler } from '../../errors'; +import { + CreateSLO, + DefaultSummaryTransformManager, + DefaultTransformManager, + KibanaSavedObjectsSLORepository, +} from '../../services'; +import { DefaultSummaryTransformGenerator } from '../../services/summary_transform_generator/summary_transform_generator'; +import { createTransformGenerators } from '../../services/transform_generators'; +import { createSloServerRoute } from '../create_slo_server_route'; +import { assertPlatinumLicense } from './utils/assert_platinum_license'; +import { getSpaceId } from './utils/get_space_id'; + +export const inspectSLORoute = createSloServerRoute({ + endpoint: 'POST /internal/observability/slos/_inspect', + options: { access: 'internal' }, + security: { + authz: { + requiredPrivileges: ['slo_write'], + }, + }, + params: createSLOParamsSchema, + handler: async ({ context, params, logger, request, plugins, corePlugins }) => { + await assertPlatinumLicense(plugins); + + const sloContext = await context.slo; + const dataViews = await plugins.dataViews.start(); + const spaceId = await getSpaceId(plugins, request); + const basePath = corePlugins.http.basePath; + const core = await context.core; + const scopedClusterClient = core.elasticsearch.client; + const esClient = core.elasticsearch.client.asCurrentUser; + const username = core.security.authc.getCurrentUser()?.username!; + const soClient = core.savedObjects.client; + const repository = new KibanaSavedObjectsSLORepository(soClient, logger); + const dataViewsService = await dataViews.dataViewsServiceFactory(soClient, esClient); + + const transformGenerators = createTransformGenerators( + spaceId, + dataViewsService, + sloContext.isServerless + ); + const transformManager = new DefaultTransformManager( + transformGenerators, + scopedClusterClient, + logger + ); + const summaryTransformManager = new DefaultSummaryTransformManager( + new DefaultSummaryTransformGenerator(), + scopedClusterClient, + logger + ); + + const createSLO = new CreateSLO( + esClient, + scopedClusterClient, + repository, + transformManager, + summaryTransformManager, + logger, + spaceId, + basePath, + username + ); + + return await executeWithErrorHandler(() => createSLO.inspect(params.body)); + }, +}); diff --git a/x-pack/solutions/observability/plugins/slo/server/routes/slo/put_slo_settings.ts b/x-pack/solutions/observability/plugins/slo/server/routes/slo/put_slo_settings.ts new file mode 100644 index 0000000000000..0b5fa03b2d5ad --- /dev/null +++ b/x-pack/solutions/observability/plugins/slo/server/routes/slo/put_slo_settings.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 { + PutSLOSettingsParams, + putSLOServerlessSettingsParamsSchema, + putSLOSettingsParamsSchema, +} from '@kbn/slo-schema'; +import { executeWithErrorHandler } from '../../errors'; +import { storeSloSettings } from '../../services/slo_settings'; +import { createSloServerRoute } from '../create_slo_server_route'; +import { assertPlatinumLicense } from './utils/assert_platinum_license'; + +export const putSloSettings = (isServerless?: boolean) => + createSloServerRoute({ + endpoint: 'PUT /internal/slo/settings', + options: { access: 'internal' }, + security: { + authz: { + requiredPrivileges: ['slo_write'], + }, + }, + params: isServerless ? putSLOServerlessSettingsParamsSchema : putSLOSettingsParamsSchema, + handler: async ({ context, params, plugins }) => { + await assertPlatinumLicense(plugins); + + const soClient = (await context.core).savedObjects.client; + return await executeWithErrorHandler(() => + storeSloSettings(soClient, params.body as PutSLOSettingsParams) + ); + }, + }); diff --git a/x-pack/solutions/observability/plugins/slo/server/routes/slo/reset_slo.ts b/x-pack/solutions/observability/plugins/slo/server/routes/slo/reset_slo.ts new file mode 100644 index 0000000000000..494eda55b22ed --- /dev/null +++ b/x-pack/solutions/observability/plugins/slo/server/routes/slo/reset_slo.ts @@ -0,0 +1,75 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { resetSLOParamsSchema } from '@kbn/slo-schema'; +import { executeWithErrorHandler } from '../../errors'; +import { + DefaultSummaryTransformManager, + DefaultTransformManager, + KibanaSavedObjectsSLORepository, +} from '../../services'; +import { ResetSLO } from '../../services/reset_slo'; +import { DefaultSummaryTransformGenerator } from '../../services/summary_transform_generator/summary_transform_generator'; +import { createTransformGenerators } from '../../services/transform_generators'; +import { createSloServerRoute } from '../create_slo_server_route'; +import { assertPlatinumLicense } from './utils/assert_platinum_license'; +import { getSpaceId } from './utils/get_space_id'; + +export const resetSLORoute = createSloServerRoute({ + endpoint: 'POST /api/observability/slos/{id}/_reset 2023-10-31', + options: { access: 'public' }, + security: { + authz: { + requiredPrivileges: ['slo_write'], + }, + }, + params: resetSLOParamsSchema, + handler: async ({ context, request, params, logger, plugins, corePlugins }) => { + await assertPlatinumLicense(plugins); + + const sloContext = await context.slo; + const dataViews = await plugins.dataViews.start(); + const spaceId = await getSpaceId(plugins, request); + const core = await context.core; + const scopedClusterClient = core.elasticsearch.client; + const soClient = core.savedObjects.client; + const esClient = core.elasticsearch.client.asCurrentUser; + const basePath = corePlugins.http.basePath; + + const dataViewsService = await dataViews.dataViewsServiceFactory(soClient, esClient); + const repository = new KibanaSavedObjectsSLORepository(soClient, logger); + + const transformGenerators = createTransformGenerators( + spaceId, + dataViewsService, + sloContext.isServerless + ); + const transformManager = new DefaultTransformManager( + transformGenerators, + scopedClusterClient, + logger + ); + const summaryTransformManager = new DefaultSummaryTransformManager( + new DefaultSummaryTransformGenerator(), + scopedClusterClient, + logger + ); + + const resetSLO = new ResetSLO( + esClient, + scopedClusterClient, + repository, + transformManager, + summaryTransformManager, + logger, + spaceId, + basePath + ); + + return await executeWithErrorHandler(() => resetSLO.execute(params.path.id)); + }, +}); diff --git a/x-pack/solutions/observability/plugins/slo/server/routes/slo/route.ts b/x-pack/solutions/observability/plugins/slo/server/routes/slo/route.ts index cac23f8d1f1ef..99164e386fc0b 100644 --- a/x-pack/solutions/observability/plugins/slo/server/routes/slo/route.ts +++ b/x-pack/solutions/observability/plugins/slo/server/routes/slo/route.ts @@ -5,815 +5,28 @@ * 2.0. */ -import { errors } from '@elastic/elasticsearch'; -import { failedDependency, forbidden } from '@hapi/boom'; -import { KibanaRequest } from '@kbn/core-http-server'; -import { - PutSLOSettingsParams, - createSLOParamsSchema, - deleteSLOInstancesParamsSchema, - deleteSLOParamsSchema, - fetchHistoricalSummaryParamsSchema, - fetchSLOHealthParamsSchema, - findSLOGroupsParamsSchema, - findSLOParamsSchema, - findSloDefinitionsParamsSchema, - getPreviewDataParamsSchema, - getSLOBurnRatesParamsSchema, - getSLOGroupingsParamsSchema, - getSLOParamsSchema, - manageSLOParamsSchema, - putSLOServerlessSettingsParamsSchema, - putSLOSettingsParamsSchema, - resetSLOParamsSchema, - updateSLOParamsSchema, -} from '@kbn/slo-schema'; -import { getOverviewParamsSchema } from '@kbn/slo-schema/src/rest_specs/routes/get_overview'; -import { executeWithErrorHandler } from '../../errors'; -import { - CreateSLO, - DefaultBurnRatesClient, - DefaultSummaryClient, - DefaultSummaryTransformManager, - DefaultTransformManager, - DeleteSLO, - DeleteSLOInstances, - FindSLO, - FindSLOGroups, - GetSLO, - GetSLOHealth, - KibanaSavedObjectsSLORepository, - UpdateSLO, -} from '../../services'; -import { FindSLODefinitions } from '../../services/find_slo_definitions'; -import { getBurnRates } from '../../services/get_burn_rates'; -import { getGlobalDiagnosis } from '../../services/get_diagnosis'; -import { GetPreviewData } from '../../services/get_preview_data'; -import { GetSLOGroupings } from '../../services/get_slo_groupings'; -import { GetSLOSuggestions } from '../../services/get_slo_suggestions'; -import { GetSLOsOverview } from '../../services/get_slos_overview'; -import { DefaultHistoricalSummaryClient } from '../../services/historical_summary_client'; -import { ManageSLO } from '../../services/manage_slo'; -import { ResetSLO } from '../../services/reset_slo'; -import { SloDefinitionClient } from '../../services/slo_definition_client'; -import { getSloSettings, storeSloSettings } from '../../services/slo_settings'; -import { DefaultSummarySearchClient } from '../../services/summary_search_client/summary_search_client'; -import { DefaultSummaryTransformGenerator } from '../../services/summary_transform_generator/summary_transform_generator'; -import { createTransformGenerators } from '../../services/transform_generators'; -import { createSloServerRoute } from '../create_slo_server_route'; -import { SLORoutesDependencies } from '../types'; - -const assertPlatinumLicense = async (plugins: SLORoutesDependencies['plugins']) => { - const licensing = await plugins.licensing.start(); - const hasCorrectLicense = (await licensing.getLicense()).hasAtLeast('platinum'); - - if (!hasCorrectLicense) { - throw forbidden('Platinum license or higher is needed to make use of this feature.'); - } -}; - -const getSpaceId = async (plugins: SLORoutesDependencies['plugins'], request: KibanaRequest) => { - const spaces = await plugins.spaces.start(); - return (await spaces?.spacesService?.getActiveSpace(request))?.id ?? 'default'; -}; - -const createSLORoute = createSloServerRoute({ - endpoint: 'POST /api/observability/slos 2023-10-31', - options: { access: 'public' }, - security: { - authz: { - requiredPrivileges: ['slo_write'], - }, - }, - params: createSLOParamsSchema, - handler: async ({ context, params, logger, request, plugins, corePlugins }) => { - await assertPlatinumLicense(plugins); - - const sloContext = await context.slo; - const dataViews = await plugins.dataViews.start(); - const core = await context.core; - const userId = core.security.authc.getCurrentUser()?.username!; - const scopedClusterClient = core.elasticsearch.client; - const esClient = core.elasticsearch.client.asCurrentUser; - const soClient = core.savedObjects.client; - const basePath = corePlugins.http.basePath; - const repository = new KibanaSavedObjectsSLORepository(soClient, logger); - - const [spaceId, dataViewsService] = await Promise.all([ - getSpaceId(plugins, request), - dataViews.dataViewsServiceFactory(soClient, esClient), - ]); - - const transformGenerators = createTransformGenerators( - spaceId, - dataViewsService, - sloContext.isServerless - ); - - const transformManager = new DefaultTransformManager( - transformGenerators, - scopedClusterClient, - logger - ); - const summaryTransformManager = new DefaultSummaryTransformManager( - new DefaultSummaryTransformGenerator(), - scopedClusterClient, - logger - ); - const createSLO = new CreateSLO( - esClient, - scopedClusterClient, - repository, - transformManager, - summaryTransformManager, - logger, - spaceId, - basePath, - userId - ); - - return await executeWithErrorHandler(() => createSLO.execute(params.body)); - }, -}); - -const inspectSLORoute = createSloServerRoute({ - endpoint: 'POST /internal/observability/slos/_inspect', - options: { access: 'internal' }, - security: { - authz: { - requiredPrivileges: ['slo_write'], - }, - }, - params: createSLOParamsSchema, - handler: async ({ context, params, logger, request, plugins, corePlugins }) => { - await assertPlatinumLicense(plugins); - - const sloContext = await context.slo; - const dataViews = await plugins.dataViews.start(); - const spaceId = await getSpaceId(plugins, request); - const basePath = corePlugins.http.basePath; - const core = await context.core; - const scopedClusterClient = core.elasticsearch.client; - const esClient = core.elasticsearch.client.asCurrentUser; - const username = core.security.authc.getCurrentUser()?.username!; - const soClient = core.savedObjects.client; - const repository = new KibanaSavedObjectsSLORepository(soClient, logger); - const dataViewsService = await dataViews.dataViewsServiceFactory(soClient, esClient); - - const transformGenerators = createTransformGenerators( - spaceId, - dataViewsService, - sloContext.isServerless - ); - const transformManager = new DefaultTransformManager( - transformGenerators, - scopedClusterClient, - logger - ); - const summaryTransformManager = new DefaultSummaryTransformManager( - new DefaultSummaryTransformGenerator(), - scopedClusterClient, - logger - ); - - const createSLO = new CreateSLO( - esClient, - scopedClusterClient, - repository, - transformManager, - summaryTransformManager, - logger, - spaceId, - basePath, - username - ); - - return await executeWithErrorHandler(() => createSLO.inspect(params.body)); - }, -}); - -const updateSLORoute = createSloServerRoute({ - endpoint: 'PUT /api/observability/slos/{id} 2023-10-31', - options: { access: 'public' }, - security: { - authz: { - requiredPrivileges: ['slo_write'], - }, - }, - params: updateSLOParamsSchema, - handler: async ({ context, request, params, logger, plugins, corePlugins }) => { - await assertPlatinumLicense(plugins); - - const spaceId = await getSpaceId(plugins, request); - const dataViews = await plugins.dataViews.start(); - - const sloContext = await context.slo; - const basePath = corePlugins.http.basePath; - const core = await context.core; - const scopedClusterClient = core.elasticsearch.client; - const esClient = core.elasticsearch.client.asCurrentUser; - const userId = core.security.authc.getCurrentUser()?.username!; - - const soClient = core.savedObjects.client; - const dataViewsService = await dataViews.dataViewsServiceFactory(soClient, esClient); - const repository = new KibanaSavedObjectsSLORepository(soClient, logger); - - const transformGenerators = createTransformGenerators( - spaceId, - dataViewsService, - sloContext.isServerless - ); - const transformManager = new DefaultTransformManager( - transformGenerators, - scopedClusterClient, - logger - ); - const summaryTransformManager = new DefaultSummaryTransformManager( - new DefaultSummaryTransformGenerator(), - scopedClusterClient, - logger - ); - - const updateSLO = new UpdateSLO( - repository, - transformManager, - summaryTransformManager, - esClient, - scopedClusterClient, - logger, - spaceId, - basePath, - userId - ); - - return await executeWithErrorHandler(() => updateSLO.execute(params.path.id, params.body)); - }, -}); - -const deleteSLORoute = createSloServerRoute({ - endpoint: 'DELETE /api/observability/slos/{id} 2023-10-31', - options: { access: 'public' }, - security: { - authz: { - requiredPrivileges: ['slo_write'], - }, - }, - params: deleteSLOParamsSchema, - handler: async ({ request, response, context, params, logger, plugins }) => { - await assertPlatinumLicense(plugins); - - const spaceId = await getSpaceId(plugins, request); - const dataViews = await plugins.dataViews.start(); - - const sloContext = await context.slo; - const core = await context.core; - const scopedClusterClient = core.elasticsearch.client; - const esClient = core.elasticsearch.client.asCurrentUser; - const soClient = core.savedObjects.client; - - const alerting = await plugins.alerting.start(); - const rulesClient = await alerting.getRulesClientWithRequest(request); - - const dataViewsService = await dataViews.dataViewsServiceFactory(soClient, esClient); - - const transformGenerators = createTransformGenerators( - spaceId, - dataViewsService, - sloContext.isServerless - ); - const repository = new KibanaSavedObjectsSLORepository(soClient, logger); - const transformManager = new DefaultTransformManager( - transformGenerators, - scopedClusterClient, - logger - ); - - const summaryTransformManager = new DefaultSummaryTransformManager( - new DefaultSummaryTransformGenerator(), - scopedClusterClient, - logger - ); - - const deleteSLO = new DeleteSLO( - repository, - transformManager, - summaryTransformManager, - esClient, - scopedClusterClient, - rulesClient - ); - - await executeWithErrorHandler(() => deleteSLO.execute(params.path.id)); - return response.noContent(); - }, -}); - -const getSLORoute = createSloServerRoute({ - endpoint: 'GET /api/observability/slos/{id} 2023-10-31', - options: { access: 'public' }, - security: { - authz: { - requiredPrivileges: ['slo_read'], - }, - }, - params: getSLOParamsSchema, - handler: async ({ request, context, params, logger, plugins }) => { - await assertPlatinumLicense(plugins); - - const spaceId = await getSpaceId(plugins, request); - - const soClient = (await context.core).savedObjects.client; - const esClient = (await context.core).elasticsearch.client.asCurrentUser; - const repository = new KibanaSavedObjectsSLORepository(soClient, logger); - const burnRatesClient = new DefaultBurnRatesClient(esClient); - const summaryClient = new DefaultSummaryClient(esClient, burnRatesClient); - const definitionClient = new SloDefinitionClient(repository, esClient, logger); - const getSLO = new GetSLO(definitionClient, summaryClient); - - return await executeWithErrorHandler(() => - getSLO.execute(params.path.id, spaceId, params.query) - ); - }, -}); - -const enableSLORoute = createSloServerRoute({ - endpoint: 'POST /api/observability/slos/{id}/enable 2023-10-31', - options: { access: 'public' }, - security: { - authz: { - requiredPrivileges: ['slo_write'], - }, - }, - params: manageSLOParamsSchema, - handler: async ({ request, response, context, params, logger, plugins }) => { - await assertPlatinumLicense(plugins); - - const spaceId = await getSpaceId(plugins, request); - const dataViews = await plugins.dataViews.start(); - const sloContext = await context.slo; - const core = await context.core; - const scopedClusterClient = core.elasticsearch.client; - const soClient = core.savedObjects.client; - const esClient = core.elasticsearch.client.asCurrentUser; - const dataViewsService = await dataViews.dataViewsServiceFactory(soClient, esClient); - const repository = new KibanaSavedObjectsSLORepository(soClient, logger); - - const transformGenerators = createTransformGenerators( - spaceId, - dataViewsService, - sloContext.isServerless - ); - - const transformManager = new DefaultTransformManager( - transformGenerators, - scopedClusterClient, - logger - ); - const summaryTransformManager = new DefaultSummaryTransformManager( - new DefaultSummaryTransformGenerator(), - scopedClusterClient, - logger - ); - - const manageSLO = new ManageSLO(repository, transformManager, summaryTransformManager); - - await executeWithErrorHandler(() => manageSLO.enable(params.path.id)); - - return response.noContent(); - }, -}); - -const disableSLORoute = createSloServerRoute({ - endpoint: 'POST /api/observability/slos/{id}/disable 2023-10-31', - options: { access: 'public' }, - security: { - authz: { - requiredPrivileges: ['slo_write'], - }, - }, - params: manageSLOParamsSchema, - handler: async ({ response, request, context, params, logger, plugins }) => { - await assertPlatinumLicense(plugins); - - const spaceId = await getSpaceId(plugins, request); - const dataViews = await plugins.dataViews.start(); - - const sloContext = await context.slo; - const core = await context.core; - const scopedClusterClient = core.elasticsearch.client; - const soClient = core.savedObjects.client; - const esClient = core.elasticsearch.client.asCurrentUser; - const dataViewsService = await dataViews.dataViewsServiceFactory(soClient, esClient); - const repository = new KibanaSavedObjectsSLORepository(soClient, logger); - - const transformGenerators = createTransformGenerators( - spaceId, - dataViewsService, - sloContext.isServerless - ); - const transformManager = new DefaultTransformManager( - transformGenerators, - scopedClusterClient, - logger - ); - const summaryTransformManager = new DefaultSummaryTransformManager( - new DefaultSummaryTransformGenerator(), - scopedClusterClient, - logger - ); - - const manageSLO = new ManageSLO(repository, transformManager, summaryTransformManager); - - await executeWithErrorHandler(() => manageSLO.disable(params.path.id)); - return response.noContent(); - }, -}); - -const resetSLORoute = createSloServerRoute({ - endpoint: 'POST /api/observability/slos/{id}/_reset 2023-10-31', - options: { access: 'public' }, - security: { - authz: { - requiredPrivileges: ['slo_write'], - }, - }, - params: resetSLOParamsSchema, - handler: async ({ context, request, params, logger, plugins, corePlugins }) => { - await assertPlatinumLicense(plugins); - - const sloContext = await context.slo; - const dataViews = await plugins.dataViews.start(); - const spaceId = await getSpaceId(plugins, request); - const core = await context.core; - const scopedClusterClient = core.elasticsearch.client; - const soClient = core.savedObjects.client; - const esClient = core.elasticsearch.client.asCurrentUser; - const basePath = corePlugins.http.basePath; - - const dataViewsService = await dataViews.dataViewsServiceFactory(soClient, esClient); - const repository = new KibanaSavedObjectsSLORepository(soClient, logger); - - const transformGenerators = createTransformGenerators( - spaceId, - dataViewsService, - sloContext.isServerless - ); - const transformManager = new DefaultTransformManager( - transformGenerators, - scopedClusterClient, - logger - ); - const summaryTransformManager = new DefaultSummaryTransformManager( - new DefaultSummaryTransformGenerator(), - scopedClusterClient, - logger - ); - - const resetSLO = new ResetSLO( - esClient, - scopedClusterClient, - repository, - transformManager, - summaryTransformManager, - logger, - spaceId, - basePath - ); - - return await executeWithErrorHandler(() => resetSLO.execute(params.path.id)); - }, -}); - -const findSLORoute = createSloServerRoute({ - endpoint: 'GET /api/observability/slos 2023-10-31', - options: { access: 'public' }, - security: { - authz: { - requiredPrivileges: ['slo_read'], - }, - }, - params: findSLOParamsSchema, - handler: async ({ context, request, params, logger, plugins }) => { - await assertPlatinumLicense(plugins); - - const spaceId = await getSpaceId(plugins, request); - const soClient = (await context.core).savedObjects.client; - const esClient = (await context.core).elasticsearch.client.asCurrentUser; - const repository = new KibanaSavedObjectsSLORepository(soClient, logger); - const summarySearchClient = new DefaultSummarySearchClient(esClient, soClient, logger, spaceId); - - const findSLO = new FindSLO(repository, summarySearchClient); - - return await executeWithErrorHandler(() => findSLO.execute(params?.query ?? {})); - }, -}); - -const findSLOGroupsRoute = createSloServerRoute({ - endpoint: 'GET /internal/observability/slos/_groups', - options: { access: 'internal' }, - security: { - authz: { - requiredPrivileges: ['slo_read'], - }, - }, - params: findSLOGroupsParamsSchema, - handler: async ({ context, request, params, logger, plugins }) => { - await assertPlatinumLicense(plugins); - - const spaceId = await getSpaceId(plugins, request); - const soClient = (await context.core).savedObjects.client; - const coreContext = context.core; - const esClient = (await coreContext).elasticsearch.client.asCurrentUser; - const findSLOGroups = new FindSLOGroups(esClient, soClient, logger, spaceId); - return await executeWithErrorHandler(() => findSLOGroups.execute(params?.query ?? {})); - }, -}); - -const getSLOSuggestionsRoute = createSloServerRoute({ - endpoint: 'GET /internal/observability/slos/suggestions', - options: { access: 'internal' }, - security: { - authz: { - requiredPrivileges: ['slo_read'], - }, - }, - handler: async ({ context, plugins }) => { - await assertPlatinumLicense(plugins); - - const soClient = (await context.core).savedObjects.client; - const getSLOSuggestions = new GetSLOSuggestions(soClient); - return await executeWithErrorHandler(() => getSLOSuggestions.execute()); - }, -}); - -const deleteSloInstancesRoute = createSloServerRoute({ - endpoint: 'POST /api/observability/slos/_delete_instances 2023-10-31', - options: { access: 'public' }, - security: { - authz: { - requiredPrivileges: ['slo_write'], - }, - }, - params: deleteSLOInstancesParamsSchema, - handler: async ({ response, context, params, plugins }) => { - await assertPlatinumLicense(plugins); - - const esClient = (await context.core).elasticsearch.client.asCurrentUser; - const deleteSloInstances = new DeleteSLOInstances(esClient); - - await executeWithErrorHandler(() => deleteSloInstances.execute(params.body)); - return response.noContent(); - }, -}); - -const findSloDefinitionsRoute = createSloServerRoute({ - endpoint: 'GET /api/observability/slos/_definitions 2023-10-31', - options: { access: 'public' }, - security: { - authz: { - requiredPrivileges: ['slo_read'], - }, - }, - params: findSloDefinitionsParamsSchema, - handler: async ({ context, params, logger, plugins }) => { - await assertPlatinumLicense(plugins); - - const soClient = (await context.core).savedObjects.client; - const repository = new KibanaSavedObjectsSLORepository(soClient, logger); - const findSloDefinitions = new FindSLODefinitions(repository); - - return await executeWithErrorHandler(() => findSloDefinitions.execute(params?.query ?? {})); - }, -}); - -const fetchHistoricalSummary = createSloServerRoute({ - endpoint: 'POST /internal/observability/slos/_historical_summary', - options: { access: 'internal' }, - security: { - authz: { - requiredPrivileges: ['slo_read'], - }, - }, - params: fetchHistoricalSummaryParamsSchema, - handler: async ({ context, params, plugins }) => { - await assertPlatinumLicense(plugins); - - const esClient = (await context.core).elasticsearch.client.asCurrentUser; - const historicalSummaryClient = new DefaultHistoricalSummaryClient(esClient); - - return await executeWithErrorHandler(() => historicalSummaryClient.fetch(params.body)); - }, -}); - -const getSLOGroupingsRoute = createSloServerRoute({ - endpoint: 'GET /internal/observability/slos/{id}/_groupings', - options: { access: 'internal' }, - security: { - authz: { - requiredPrivileges: ['slo_read'], - }, - }, - params: getSLOGroupingsParamsSchema, - handler: async ({ context, params, request, logger, plugins }) => { - await assertPlatinumLicense(plugins); - const soClient = (await context.core).savedObjects.client; - const esClient = (await context.core).elasticsearch.client.asCurrentUser; - const [spaceId, settings] = await Promise.all([ - getSpaceId(plugins, request), - getSloSettings(soClient), - ]); - - const repository = new KibanaSavedObjectsSLORepository(soClient, logger); - const definitionClient = new SloDefinitionClient(repository, esClient, logger); - - const getSLOGroupings = new GetSLOGroupings(definitionClient, esClient, settings, spaceId); - - return await executeWithErrorHandler(() => - getSLOGroupings.execute(params.path.id, params.query) - ); - }, -}); - -const getDiagnosisRoute = createSloServerRoute({ - endpoint: 'GET /internal/observability/slos/_diagnosis', - options: { access: 'internal' }, - security: { - authz: { - enabled: false, - reason: 'The endpoint is used to diagnose SLOs and does not require any specific privileges.', - }, - }, - params: undefined, - handler: async ({ context, plugins }) => { - const esClient = (await context.core).elasticsearch.client.asCurrentUser; - const licensing = await plugins.licensing.start(); - - try { - const response = await getGlobalDiagnosis(esClient, licensing); - return response; - } catch (error) { - if (error instanceof errors.ResponseError && error.statusCode === 403) { - throw forbidden('Insufficient Elasticsearch cluster permissions to access feature.'); - } - throw failedDependency(error); - } - }, -}); - -const fetchSloHealthRoute = createSloServerRoute({ - endpoint: 'POST /internal/observability/slos/_health', - options: { access: 'internal' }, - security: { - authz: { - requiredPrivileges: ['slo_read'], - }, - }, - params: fetchSLOHealthParamsSchema, - handler: async ({ context, params, logger, plugins }) => { - await assertPlatinumLicense(plugins); - - const core = await context.core; - const scopedClusterClient = core.elasticsearch.client; - const soClient = core.savedObjects.client; - const esClient = core.elasticsearch.client.asCurrentUser; - const repository = new KibanaSavedObjectsSLORepository(soClient, logger); - - const getSLOHealth = new GetSLOHealth(esClient, scopedClusterClient, repository); - - return await executeWithErrorHandler(() => getSLOHealth.execute(params.body)); - }, -}); - -const getSloBurnRates = createSloServerRoute({ - endpoint: 'POST /internal/observability/slos/{id}/_burn_rates', - options: { access: 'internal' }, - security: { - authz: { - requiredPrivileges: ['slo_read'], - }, - }, - params: getSLOBurnRatesParamsSchema, - handler: async ({ request, context, params, logger, plugins }) => { - await assertPlatinumLicense(plugins); - - const spaceId = await getSpaceId(plugins, request); - - const esClient = (await context.core).elasticsearch.client.asCurrentUser; - const soClient = (await context.core).savedObjects.client; - const { instanceId, windows, remoteName } = params.body; - - return await executeWithErrorHandler(() => - getBurnRates({ - instanceId, - spaceId, - windows, - remoteName, - sloId: params.path.id, - services: { - soClient, - esClient, - logger, - }, - }) - ); - }, -}); - -const getPreviewData = createSloServerRoute({ - endpoint: 'POST /internal/observability/slos/_preview', - options: { access: 'internal' }, - security: { - authz: { - requiredPrivileges: ['slo_read'], - }, - }, - params: getPreviewDataParamsSchema, - handler: async ({ request, context, params, plugins }) => { - await assertPlatinumLicense(plugins); - - const spaceId = await getSpaceId(plugins, request); - const dataViews = await plugins.dataViews.start(); - - const esClient = (await context.core).elasticsearch.client.asCurrentUser; - const soClient = (await context.core).savedObjects.client; - const dataViewsService = await dataViews.dataViewsServiceFactory(soClient, esClient); - const service = new GetPreviewData(esClient, spaceId, dataViewsService); - return await service.execute(params.body); - }, -}); - -const getSloSettingsRoute = createSloServerRoute({ - endpoint: 'GET /internal/slo/settings', - options: { access: 'internal' }, - security: { - authz: { - requiredPrivileges: ['slo_read'], - }, - }, - handler: async ({ context, plugins }) => { - await assertPlatinumLicense(plugins); - - const soClient = (await context.core).savedObjects.client; - - return await executeWithErrorHandler(() => getSloSettings(soClient)); - }, -}); - -const putSloSettings = (isServerless?: boolean) => - createSloServerRoute({ - endpoint: 'PUT /internal/slo/settings', - options: { access: 'internal' }, - security: { - authz: { - requiredPrivileges: ['slo_write'], - }, - }, - params: isServerless ? putSLOServerlessSettingsParamsSchema : putSLOSettingsParamsSchema, - handler: async ({ context, params, plugins }) => { - await assertPlatinumLicense(plugins); - - const soClient = (await context.core).savedObjects.client; - return await executeWithErrorHandler(() => - storeSloSettings(soClient, params.body as PutSLOSettingsParams) - ); - }, - }); - -const getSLOsOverview = createSloServerRoute({ - endpoint: 'GET /internal/observability/slos/overview', - options: { access: 'internal' }, - security: { - authz: { - requiredPrivileges: ['slo_read'], - }, - }, - params: getOverviewParamsSchema, - handler: async ({ context, params, request, logger, plugins }) => { - await assertPlatinumLicense(plugins); - - const soClient = (await context.core).savedObjects.client; - const esClient = (await context.core).elasticsearch.client.asCurrentUser; - - const ruleRegistry = await plugins.ruleRegistry.start(); - const racClient = await ruleRegistry.getRacClientWithRequest(request); - - const spaceId = await getSpaceId(plugins, request); - - const alerting = await plugins.alerting.start(); - const rulesClient = await alerting.getRulesClientWithRequest(request); - - const slosOverview = new GetSLOsOverview( - soClient, - esClient, - spaceId, - logger, - rulesClient, - racClient - ); - - return await executeWithErrorHandler(() => slosOverview.execute(params?.query ?? {})); - }, -}); +import { fetchSloHealthRoute } from './fetch_health'; +import { getSloSettingsRoute } from './get_slo_settings'; +import { createSLORoute } from './create_slo'; +import { inspectSLORoute } from './inspect_slo'; +import { updateSLORoute } from './update_slo'; +import { deleteSLORoute } from './delete_slo'; +import { enableSLORoute } from './enable_slo'; +import { getSLORoute } from './get_slo'; +import { deleteSloInstancesRoute } from './delete_instances'; +import { disableSLORoute } from './disable_slo'; +import { fetchHistoricalSummary } from './fetch_historical_summary'; +import { findSLORoute } from './find_slo'; +import { findSloDefinitionsRoute } from './find_definitions'; +import { findSLOGroupsRoute } from './find_groups'; +import { getDiagnosisRoute } from './get_diagnosis'; +import { getSLOGroupingsRoute } from './get_groupings'; +import { getPreviewData } from './get_preview_data'; +import { getSloBurnRates } from './get_slo_burn_rates'; +import { getSLOSuggestionsRoute } from './get_suggestions'; +import { putSloSettings } from './put_slo_settings'; +import { resetSLORoute } from './reset_slo'; +import { getSLOsOverview } from './get_slos_overview'; export const getSloRouteRepository = (isServerless?: boolean) => { return { diff --git a/x-pack/solutions/observability/plugins/slo/server/routes/slo/update_slo.ts b/x-pack/solutions/observability/plugins/slo/server/routes/slo/update_slo.ts new file mode 100644 index 0000000000000..5af7f9c54aacd --- /dev/null +++ b/x-pack/solutions/observability/plugins/slo/server/routes/slo/update_slo.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 { updateSLOParamsSchema } from '@kbn/slo-schema'; +import { executeWithErrorHandler } from '../../errors'; +import { + DefaultSummaryTransformManager, + DefaultTransformManager, + KibanaSavedObjectsSLORepository, + UpdateSLO, +} from '../../services'; +import { DefaultSummaryTransformGenerator } from '../../services/summary_transform_generator/summary_transform_generator'; +import { createTransformGenerators } from '../../services/transform_generators'; +import { createSloServerRoute } from '../create_slo_server_route'; +import { assertPlatinumLicense } from './utils/assert_platinum_license'; +import { getSpaceId } from './utils/get_space_id'; + +export const updateSLORoute = createSloServerRoute({ + endpoint: 'PUT /api/observability/slos/{id} 2023-10-31', + options: { access: 'public' }, + security: { + authz: { + requiredPrivileges: ['slo_write'], + }, + }, + params: updateSLOParamsSchema, + handler: async ({ context, request, params, logger, plugins, corePlugins }) => { + await assertPlatinumLicense(plugins); + + const spaceId = await getSpaceId(plugins, request); + const dataViews = await plugins.dataViews.start(); + + const sloContext = await context.slo; + const basePath = corePlugins.http.basePath; + const core = await context.core; + const scopedClusterClient = core.elasticsearch.client; + const esClient = core.elasticsearch.client.asCurrentUser; + const userId = core.security.authc.getCurrentUser()?.username!; + + const soClient = core.savedObjects.client; + const dataViewsService = await dataViews.dataViewsServiceFactory(soClient, esClient); + const repository = new KibanaSavedObjectsSLORepository(soClient, logger); + + const transformGenerators = createTransformGenerators( + spaceId, + dataViewsService, + sloContext.isServerless + ); + const transformManager = new DefaultTransformManager( + transformGenerators, + scopedClusterClient, + logger + ); + const summaryTransformManager = new DefaultSummaryTransformManager( + new DefaultSummaryTransformGenerator(), + scopedClusterClient, + logger + ); + + const updateSLO = new UpdateSLO( + repository, + transformManager, + summaryTransformManager, + esClient, + scopedClusterClient, + logger, + spaceId, + basePath, + userId + ); + + return await executeWithErrorHandler(() => updateSLO.execute(params.path.id, params.body)); + }, +}); diff --git a/x-pack/solutions/observability/plugins/slo/server/routes/slo/utils/assert_platinum_license.ts b/x-pack/solutions/observability/plugins/slo/server/routes/slo/utils/assert_platinum_license.ts new file mode 100644 index 0000000000000..616a3ca4b92b6 --- /dev/null +++ b/x-pack/solutions/observability/plugins/slo/server/routes/slo/utils/assert_platinum_license.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 { forbidden } from '@hapi/boom'; +import { SLORoutesDependencies } from '../../types'; + +export const assertPlatinumLicense = async (plugins: SLORoutesDependencies['plugins']) => { + const licensing = await plugins.licensing.start(); + const hasCorrectLicense = (await licensing.getLicense()).hasAtLeast('platinum'); + + if (!hasCorrectLicense) { + throw forbidden('Platinum license or higher is needed to make use of this feature.'); + } +}; diff --git a/x-pack/solutions/observability/plugins/slo/server/routes/slo/utils/get_space_id.ts b/x-pack/solutions/observability/plugins/slo/server/routes/slo/utils/get_space_id.ts new file mode 100644 index 0000000000000..901c82a7c3678 --- /dev/null +++ b/x-pack/solutions/observability/plugins/slo/server/routes/slo/utils/get_space_id.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 { KibanaRequest } from '@kbn/core/server'; +import { SLORoutesDependencies } from '../../types'; + +export const getSpaceId = async ( + plugins: SLORoutesDependencies['plugins'], + request: KibanaRequest +) => { + const spaces = await plugins.spaces.start(); + return (await spaces?.spacesService?.getActiveSpace(request))?.id ?? 'default'; +}; diff --git a/x-pack/solutions/observability/plugins/slo/server/services/burn_rates_client.ts b/x-pack/solutions/observability/plugins/slo/server/services/burn_rates_client.ts index eb7e130e448f3..0897afbe9bcc1 100644 --- a/x-pack/solutions/observability/plugins/slo/server/services/burn_rates_client.ts +++ b/x-pack/solutions/observability/plugins/slo/server/services/burn_rates_client.ts @@ -19,7 +19,7 @@ import { occurrencesBudgetingMethodSchema, timeslicesBudgetingMethodSchema, } from '@kbn/slo-schema'; -import { SLO_DESTINATION_INDEX_PATTERN } from '../../common/constants'; +import { SLI_DESTINATION_INDEX_PATTERN } from '../../common/constants'; import { DateRange, Duration, SLODefinition } from '../domain/models'; import { computeBurnRate, computeSLI } from '../domain/services'; import { getDelayInSecondsFromSLO } from '../domain/services/get_delay_in_seconds_from_slo'; @@ -65,8 +65,8 @@ export class DefaultBurnRatesClient implements BurnRatesClient { ); const index = remoteName - ? `${remoteName}:${SLO_DESTINATION_INDEX_PATTERN}` - : SLO_DESTINATION_INDEX_PATTERN; + ? `${remoteName}:${SLI_DESTINATION_INDEX_PATTERN}` + : SLI_DESTINATION_INDEX_PATTERN; const result = await this.esClient.search({ ...commonQuery(slo, instanceId, longestDateRange), diff --git a/x-pack/solutions/observability/plugins/slo/server/services/create_slo.ts b/x-pack/solutions/observability/plugins/slo/server/services/create_slo.ts index 8d596d2d27c44..0bc5500b2782c 100644 --- a/x-pack/solutions/observability/plugins/slo/server/services/create_slo.ts +++ b/x-pack/solutions/observability/plugins/slo/server/services/create_slo.ts @@ -13,14 +13,14 @@ import { merge } from 'lodash'; import { v4 as uuidv4 } from 'uuid'; import { SLO_MODEL_VERSION, - SLO_SUMMARY_TEMP_INDEX_NAME, + SUMMARY_TEMP_INDEX_NAME, getSLOPipelineId, getSLOSummaryPipelineId, getSLOSummaryTransformId, getSLOTransformId, } from '../../common/constants'; -import { getSLOPipelineTemplate } from '../assets/ingest_templates/slo_pipeline_template'; -import { getSLOSummaryPipelineTemplate } from '../assets/ingest_templates/slo_summary_pipeline_template'; +import { getSLIPipelineTemplate } from '../assets/ingest_templates/sli_pipeline_template'; +import { getSummaryPipelineTemplate } from '../assets/ingest_templates/summary_pipeline_template'; import { Duration, DurationUnit, SLODefinition } from '../domain/models'; import { validateSLO } from '../domain/services'; import { SLOIdConflict, SecurityException } from '../errors'; @@ -60,14 +60,14 @@ export class CreateSLO { const rollupTransformId = getSLOTransformId(slo.id, slo.revision); const summaryTransformId = getSLOSummaryTransformId(slo.id, slo.revision); try { - const sloPipelinePromise = this.createPipeline(getSLOPipelineTemplate(slo)); + const sloPipelinePromise = this.createPipeline(getSLIPipelineTemplate(slo)); rollbackOperations.push(() => this.deletePipeline(getSLOPipelineId(slo.id, slo.revision))); const rollupTransformPromise = this.transformManager.install(slo); rollbackOperations.push(() => this.transformManager.uninstall(rollupTransformId)); const summaryPipelinePromise = this.createPipeline( - getSLOSummaryPipelineTemplate(slo, this.spaceId, this.basePath) + getSummaryPipelineTemplate(slo, this.spaceId, this.basePath) ); rollbackOperations.push(() => @@ -132,7 +132,7 @@ export class CreateSLO { return await retryTransientEsErrors( () => this.esClient.index({ - index: SLO_SUMMARY_TEMP_INDEX_NAME, + index: SUMMARY_TEMP_INDEX_NAME, id: `slo-${slo.id}`, document: createTempSummaryDocument(slo, this.spaceId, this.basePath), refresh: true, @@ -145,7 +145,7 @@ export class CreateSLO { return await retryTransientEsErrors( () => this.esClient.delete({ - index: SLO_SUMMARY_TEMP_INDEX_NAME, + index: SUMMARY_TEMP_INDEX_NAME, id: `slo-${slo.id}`, refresh: true, }), @@ -181,8 +181,8 @@ export class CreateSLO { validateSLO(slo); const rollUpTransform = await this.transformManager.inspect(slo); - const rollUpPipeline = getSLOPipelineTemplate(slo); - const summaryPipeline = getSLOSummaryPipelineTemplate(slo, this.spaceId, this.basePath); + const rollUpPipeline = getSLIPipelineTemplate(slo); + const summaryPipeline = getSummaryPipelineTemplate(slo, this.spaceId, this.basePath); const summaryTransform = await this.summaryTransformManager.inspect(slo); const temporaryDoc = createTempSummaryDocument(slo, this.spaceId, this.basePath); diff --git a/x-pack/solutions/observability/plugins/slo/server/services/delete_slo.ts b/x-pack/solutions/observability/plugins/slo/server/services/delete_slo.ts index e86fab0a1620d..d98c85f618a17 100644 --- a/x-pack/solutions/observability/plugins/slo/server/services/delete_slo.ts +++ b/x-pack/solutions/observability/plugins/slo/server/services/delete_slo.ts @@ -12,8 +12,8 @@ import { getSLOSummaryPipelineId, getSLOSummaryTransformId, getSLOTransformId, - SLO_DESTINATION_INDEX_PATTERN, - SLO_SUMMARY_DESTINATION_INDEX_PATTERN, + SLI_DESTINATION_INDEX_PATTERN, + SUMMARY_DESTINATION_INDEX_PATTERN, } from '../../common/constants'; import { retryTransientEsErrors } from '../utils/retry'; import { SLORepository } from './slo_repository'; @@ -62,7 +62,7 @@ export class DeleteSLO { private async deleteRollupData(sloId: string): Promise { await this.esClient.deleteByQuery({ - index: SLO_DESTINATION_INDEX_PATTERN, + index: SLI_DESTINATION_INDEX_PATTERN, wait_for_completion: false, query: { match: { @@ -74,7 +74,7 @@ export class DeleteSLO { private async deleteSummaryData(sloId: string): Promise { await this.esClient.deleteByQuery({ - index: SLO_SUMMARY_DESTINATION_INDEX_PATTERN, + index: SUMMARY_DESTINATION_INDEX_PATTERN, refresh: true, query: { match: { diff --git a/x-pack/solutions/observability/plugins/slo/server/services/delete_slo_instances.ts b/x-pack/solutions/observability/plugins/slo/server/services/delete_slo_instances.ts index fb423dc37f930..fb2fc60fa29b5 100644 --- a/x-pack/solutions/observability/plugins/slo/server/services/delete_slo_instances.ts +++ b/x-pack/solutions/observability/plugins/slo/server/services/delete_slo_instances.ts @@ -8,8 +8,8 @@ import { ElasticsearchClient } from '@kbn/core/server'; import { ALL_VALUE, DeleteSLOInstancesParams } from '@kbn/slo-schema'; import { - SLO_DESTINATION_INDEX_PATTERN, - SLO_SUMMARY_DESTINATION_INDEX_PATTERN, + SLI_DESTINATION_INDEX_PATTERN, + SUMMARY_DESTINATION_INDEX_PATTERN, } from '../../common/constants'; import { IllegalArgumentError } from '../errors'; @@ -31,7 +31,7 @@ export class DeleteSLOInstances { // Delete rollup data when excluding rollup data is not explicitly requested private async deleteRollupData(list: List): Promise { await this.esClient.deleteByQuery({ - index: SLO_DESTINATION_INDEX_PATTERN, + index: SLI_DESTINATION_INDEX_PATTERN, wait_for_completion: false, query: { bool: { @@ -52,7 +52,7 @@ export class DeleteSLOInstances { private async deleteSummaryData(list: List): Promise { await this.esClient.deleteByQuery({ - index: SLO_SUMMARY_DESTINATION_INDEX_PATTERN, + index: SUMMARY_DESTINATION_INDEX_PATTERN, refresh: true, query: { bool: { diff --git a/x-pack/solutions/observability/plugins/slo/server/services/get_slo_groupings.ts b/x-pack/solutions/observability/plugins/slo/server/services/get_slo_groupings.ts index 81ed1c0c7518f..2191b690df2d7 100644 --- a/x-pack/solutions/observability/plugins/slo/server/services/get_slo_groupings.ts +++ b/x-pack/solutions/observability/plugins/slo/server/services/get_slo_groupings.ts @@ -8,7 +8,7 @@ import { AggregationsCompositeAggregation } from '@elastic/elasticsearch/lib/api/types'; import { ElasticsearchClient } from '@kbn/core-elasticsearch-server'; import { ALL_VALUE, GetSLOGroupingsParams, GetSLOGroupingsResponse } from '@kbn/slo-schema'; -import { SLO_SUMMARY_DESTINATION_INDEX_NAME } from '../../common/constants'; +import { SUMMARY_DESTINATION_INDEX_NAME } from '../../common/constants'; import { SLODefinition, SLOSettings } from '../domain/models'; import { SloDefinitionClient } from './slo_definition_client'; @@ -52,8 +52,8 @@ export class GetSLOGroupings { } >({ index: params.remoteName - ? `${params.remoteName}:${SLO_SUMMARY_DESTINATION_INDEX_NAME}` - : SLO_SUMMARY_DESTINATION_INDEX_NAME, + ? `${params.remoteName}:${SUMMARY_DESTINATION_INDEX_NAME}` + : SUMMARY_DESTINATION_INDEX_NAME, ...generateQuery(slo, params, this.sloSettings), }); diff --git a/x-pack/solutions/observability/plugins/slo/server/services/get_slo_health.ts b/x-pack/solutions/observability/plugins/slo/server/services/get_slo_health.ts index 585bf7ef5d4e2..4d75025a7429e 100644 --- a/x-pack/solutions/observability/plugins/slo/server/services/get_slo_health.ts +++ b/x-pack/solutions/observability/plugins/slo/server/services/get_slo_health.ts @@ -17,7 +17,7 @@ import moment from 'moment'; import { getSLOSummaryTransformId, getSLOTransformId, - SLO_SUMMARY_DESTINATION_INDEX_PATTERN, + SUMMARY_DESTINATION_INDEX_PATTERN, } from '../../common/constants'; import { SLODefinition } from '../domain/models'; import { HealthStatus, State } from '../domain/models/health'; @@ -70,7 +70,7 @@ export class GetSLOHealth { filteredList: Array<{ sloId: string; sloInstanceId: string; sloRevision: number }> ) { const summaryDocs = await this.esClient.search({ - index: SLO_SUMMARY_DESTINATION_INDEX_PATTERN, + index: SUMMARY_DESTINATION_INDEX_PATTERN, query: { bool: { should: filteredList.map((item) => ({ diff --git a/x-pack/solutions/observability/plugins/slo/server/services/historical_summary_client.ts b/x-pack/solutions/observability/plugins/slo/server/services/historical_summary_client.ts index d4e3cdcbf6004..16d94ddb55574 100644 --- a/x-pack/solutions/observability/plugins/slo/server/services/historical_summary_client.ts +++ b/x-pack/solutions/observability/plugins/slo/server/services/historical_summary_client.ts @@ -22,7 +22,7 @@ import { import { assertNever } from '@kbn/std'; import * as t from 'io-ts'; import moment from 'moment'; -import { SLO_DESTINATION_INDEX_PATTERN } from '../../common/constants'; +import { SLI_DESTINATION_INDEX_PATTERN } from '../../common/constants'; import { DateRange, GroupBy, @@ -74,8 +74,8 @@ export class DefaultHistoricalSummaryClient implements HistoricalSummaryClient { ({ sloId, revision, budgetingMethod, instanceId, groupBy, timeWindow, remoteName }) => [ { index: remoteName - ? `${remoteName}:${SLO_DESTINATION_INDEX_PATTERN}` - : SLO_DESTINATION_INDEX_PATTERN, + ? `${remoteName}:${SLI_DESTINATION_INDEX_PATTERN}` + : SLI_DESTINATION_INDEX_PATTERN, }, generateSearchQuery({ groupBy, diff --git a/x-pack/solutions/observability/plugins/slo/server/services/index.ts b/x-pack/solutions/observability/plugins/slo/server/services/index.ts index c229226a290d2..b56a74baf7c38 100644 --- a/x-pack/solutions/observability/plugins/slo/server/services/index.ts +++ b/x-pack/solutions/observability/plugins/slo/server/services/index.ts @@ -12,7 +12,6 @@ export * from './find_slo'; export * from './get_slo'; export * from './historical_summary_client'; export * from './resource_installer'; -export * from './slo_installer'; export * from './burn_rates_client'; export * from './slo_repository'; export * from './transform_manager'; diff --git a/x-pack/solutions/observability/plugins/slo/server/services/reset_slo.ts b/x-pack/solutions/observability/plugins/slo/server/services/reset_slo.ts index e91e720b4fd8d..24aa6a705741c 100644 --- a/x-pack/solutions/observability/plugins/slo/server/services/reset_slo.ts +++ b/x-pack/solutions/observability/plugins/slo/server/services/reset_slo.ts @@ -8,17 +8,17 @@ import { ElasticsearchClient, IBasePath, IScopedClusterClient, Logger } from '@kbn/core/server'; import { resetSLOResponseSchema } from '@kbn/slo-schema'; import { - SLO_DESTINATION_INDEX_PATTERN, + SLI_DESTINATION_INDEX_PATTERN, SLO_MODEL_VERSION, - SLO_SUMMARY_DESTINATION_INDEX_PATTERN, - SLO_SUMMARY_TEMP_INDEX_NAME, + SUMMARY_DESTINATION_INDEX_PATTERN, + SUMMARY_TEMP_INDEX_NAME, getSLOPipelineId, getSLOSummaryPipelineId, getSLOSummaryTransformId, getSLOTransformId, } from '../../common/constants'; -import { getSLOPipelineTemplate } from '../assets/ingest_templates/slo_pipeline_template'; -import { getSLOSummaryPipelineTemplate } from '../assets/ingest_templates/slo_summary_pipeline_template'; +import { getSLIPipelineTemplate } from '../assets/ingest_templates/sli_pipeline_template'; +import { getSummaryPipelineTemplate } from '../assets/ingest_templates/summary_pipeline_template'; import { retryTransientEsErrors } from '../utils/retry'; import { SLORepository } from './slo_repository'; import { createTempSummaryDocument } from './summary_transform_generator/helpers/create_temp_summary'; @@ -56,7 +56,7 @@ export class ResetSLO { await retryTransientEsErrors( () => this.scopedClusterClient.asSecondaryAuthUser.ingest.putPipeline( - getSLOPipelineTemplate(slo) + getSLIPipelineTemplate(slo) ), { logger: this.logger } ); @@ -67,7 +67,7 @@ export class ResetSLO { await retryTransientEsErrors( () => this.scopedClusterClient.asSecondaryAuthUser.ingest.putPipeline( - getSLOSummaryPipelineTemplate(slo, this.spaceId, this.basePath) + getSummaryPipelineTemplate(slo, this.spaceId, this.basePath) ), { logger: this.logger } ); @@ -78,7 +78,7 @@ export class ResetSLO { await retryTransientEsErrors( () => this.esClient.index({ - index: SLO_SUMMARY_TEMP_INDEX_NAME, + index: SUMMARY_TEMP_INDEX_NAME, id: `slo-${slo.id}`, document: createTempSummaryDocument(slo, this.spaceId, this.basePath), refresh: true, @@ -124,7 +124,7 @@ export class ResetSLO { */ private async deleteRollupData(sloId: string): Promise { await this.esClient.deleteByQuery({ - index: SLO_DESTINATION_INDEX_PATTERN, + index: SLI_DESTINATION_INDEX_PATTERN, refresh: true, query: { bool: { @@ -142,7 +142,7 @@ export class ResetSLO { */ private async deleteSummaryData(sloId: string): Promise { await this.esClient.deleteByQuery({ - index: SLO_SUMMARY_DESTINATION_INDEX_PATTERN, + index: SUMMARY_DESTINATION_INDEX_PATTERN, refresh: true, query: { bool: { diff --git a/x-pack/solutions/observability/plugins/slo/server/services/resource_installer.test.ts b/x-pack/solutions/observability/plugins/slo/server/services/resource_installer.test.ts index 3f72ace983d20..7e2f40663f409 100644 --- a/x-pack/solutions/observability/plugins/slo/server/services/resource_installer.test.ts +++ b/x-pack/solutions/observability/plugins/slo/server/services/resource_installer.test.ts @@ -8,13 +8,13 @@ import { elasticsearchServiceMock } from '@kbn/core/server/mocks'; import { loggerMock } from '@kbn/logging-mocks'; import { - SLO_COMPONENT_TEMPLATE_MAPPINGS_NAME, - SLO_COMPONENT_TEMPLATE_SETTINGS_NAME, - SLO_INDEX_TEMPLATE_NAME, + SLI_COMPONENT_TEMPLATE_MAPPINGS_NAME, + SLI_COMPONENT_TEMPLATE_SETTINGS_NAME, + SLI_INDEX_TEMPLATE_NAME, SLO_RESOURCES_VERSION, - SLO_SUMMARY_COMPONENT_TEMPLATE_MAPPINGS_NAME, - SLO_SUMMARY_COMPONENT_TEMPLATE_SETTINGS_NAME, - SLO_SUMMARY_INDEX_TEMPLATE_NAME, + SUMMARY_COMPONENT_TEMPLATE_MAPPINGS_NAME, + SUMMARY_COMPONENT_TEMPLATE_SETTINGS_NAME, + SUMMARY_INDEX_TEMPLATE_NAME, } from '../../common/constants'; import { DefaultResourceInstaller } from './resource_installer'; @@ -24,7 +24,7 @@ describe('resourceInstaller', () => { mockClusterClient.cluster.getComponentTemplate.mockResponse({ component_templates: [ { - name: SLO_INDEX_TEMPLATE_NAME, + name: SLI_INDEX_TEMPLATE_NAME, component_template: { _meta: { version: 2, @@ -39,10 +39,10 @@ describe('resourceInstaller', () => { mockClusterClient.indices.getIndexTemplate.mockResponse({ index_templates: [ { - name: SLO_INDEX_TEMPLATE_NAME, + name: SLI_INDEX_TEMPLATE_NAME, index_template: { - index_patterns: SLO_INDEX_TEMPLATE_NAME, - composed_of: [SLO_SUMMARY_COMPONENT_TEMPLATE_MAPPINGS_NAME], + index_patterns: SLI_INDEX_TEMPLATE_NAME, + composed_of: [SUMMARY_COMPONENT_TEMPLATE_MAPPINGS_NAME], _meta: { version: 2, }, @@ -58,28 +58,28 @@ describe('resourceInstaller', () => { expect(mockClusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(4); expect(mockClusterClient.cluster.putComponentTemplate).toHaveBeenNthCalledWith( 1, - expect.objectContaining({ name: SLO_COMPONENT_TEMPLATE_MAPPINGS_NAME }) + expect.objectContaining({ name: SLI_COMPONENT_TEMPLATE_MAPPINGS_NAME }) ); expect(mockClusterClient.cluster.putComponentTemplate).toHaveBeenNthCalledWith( 2, - expect.objectContaining({ name: SLO_COMPONENT_TEMPLATE_SETTINGS_NAME }) + expect.objectContaining({ name: SLI_COMPONENT_TEMPLATE_SETTINGS_NAME }) ); expect(mockClusterClient.cluster.putComponentTemplate).toHaveBeenNthCalledWith( 3, - expect.objectContaining({ name: SLO_SUMMARY_COMPONENT_TEMPLATE_MAPPINGS_NAME }) + expect.objectContaining({ name: SUMMARY_COMPONENT_TEMPLATE_MAPPINGS_NAME }) ); expect(mockClusterClient.cluster.putComponentTemplate).toHaveBeenNthCalledWith( 4, - expect.objectContaining({ name: SLO_SUMMARY_COMPONENT_TEMPLATE_SETTINGS_NAME }) + expect.objectContaining({ name: SUMMARY_COMPONENT_TEMPLATE_SETTINGS_NAME }) ); expect(mockClusterClient.indices.putIndexTemplate).toHaveBeenCalledTimes(2); expect(mockClusterClient.indices.putIndexTemplate).toHaveBeenNthCalledWith( 1, - expect.objectContaining({ name: SLO_INDEX_TEMPLATE_NAME }) + expect.objectContaining({ name: SLI_INDEX_TEMPLATE_NAME }) ); expect(mockClusterClient.indices.putIndexTemplate).toHaveBeenNthCalledWith( 2, - expect.objectContaining({ name: SLO_SUMMARY_INDEX_TEMPLATE_NAME }) + expect.objectContaining({ name: SUMMARY_INDEX_TEMPLATE_NAME }) ); }); @@ -88,7 +88,7 @@ describe('resourceInstaller', () => { mockClusterClient.cluster.getComponentTemplate.mockResponse({ component_templates: [ { - name: SLO_INDEX_TEMPLATE_NAME, + name: SLI_INDEX_TEMPLATE_NAME, component_template: { _meta: { version: SLO_RESOURCES_VERSION, @@ -103,10 +103,10 @@ describe('resourceInstaller', () => { mockClusterClient.indices.getIndexTemplate.mockResponse({ index_templates: [ { - name: SLO_INDEX_TEMPLATE_NAME, + name: SLI_INDEX_TEMPLATE_NAME, index_template: { - index_patterns: SLO_INDEX_TEMPLATE_NAME, - composed_of: [SLO_SUMMARY_COMPONENT_TEMPLATE_MAPPINGS_NAME], + index_patterns: SLI_INDEX_TEMPLATE_NAME, + composed_of: [SUMMARY_COMPONENT_TEMPLATE_MAPPINGS_NAME], _meta: { version: SLO_RESOURCES_VERSION, }, @@ -122,4 +122,42 @@ describe('resourceInstaller', () => { expect(mockClusterClient.cluster.putComponentTemplate).not.toHaveBeenCalled(); expect(mockClusterClient.indices.putIndexTemplate).not.toHaveBeenCalled(); }); + + it('runs the installation only once at a time', async () => { + const mockClusterClient = elasticsearchServiceMock.createElasticsearchClient(); + mockClusterClient.cluster.getComponentTemplate.mockImplementation( + () => + new Promise((resolve) => + setTimeout( + () => + resolve({ + component_templates: [ + { + name: SLI_INDEX_TEMPLATE_NAME, + component_template: { + _meta: { + version: SLO_RESOURCES_VERSION - 1, + }, + template: { + settings: {}, + }, + }, + }, + ], + }), + 1000 + ) + ) + ); + + const installer = new DefaultResourceInstaller(mockClusterClient, loggerMock.create()); + + await Promise.all([ + installer.ensureCommonResourcesInstalled(), + installer.ensureCommonResourcesInstalled(), + ]); + + // Ensure that the installation was only run once, e.g. 4 calls to the put component template API, and not 2x 4 calls + expect(mockClusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(4); + }); }); diff --git a/x-pack/solutions/observability/plugins/slo/server/services/resource_installer.ts b/x-pack/solutions/observability/plugins/slo/server/services/resource_installer.ts index d6544d352f90f..e69d37262b69f 100644 --- a/x-pack/solutions/observability/plugins/slo/server/services/resource_installer.ts +++ b/x-pack/solutions/observability/plugins/slo/server/services/resource_installer.ts @@ -10,26 +10,17 @@ import type { IndicesPutIndexTemplateRequest, } from '@elastic/elasticsearch/lib/api/types'; import type { ElasticsearchClient, Logger } from '@kbn/core/server'; -import { getSLOMappingsTemplate } from '../assets/component_templates/slo_mappings_template'; -import { getSLOSettingsTemplate } from '../assets/component_templates/slo_settings_template'; -import { getSLOSummaryMappingsTemplate } from '../assets/component_templates/slo_summary_mappings_template'; -import { getSLOSummarySettingsTemplate } from '../assets/component_templates/slo_summary_settings_template'; import { - SLO_COMPONENT_TEMPLATE_MAPPINGS_NAME, - SLO_COMPONENT_TEMPLATE_SETTINGS_NAME, - SLO_DESTINATION_INDEX_NAME, - SLO_INDEX_TEMPLATE_NAME, - SLO_INDEX_TEMPLATE_PATTERN, - SLO_SUMMARY_COMPONENT_TEMPLATE_MAPPINGS_NAME, - SLO_SUMMARY_COMPONENT_TEMPLATE_SETTINGS_NAME, - SLO_SUMMARY_DESTINATION_INDEX_NAME, - SLO_SUMMARY_INDEX_TEMPLATE_NAME, - SLO_SUMMARY_INDEX_TEMPLATE_PATTERN, - SLO_SUMMARY_TEMP_INDEX_NAME, + SLI_DESTINATION_INDEX_NAME, + SUMMARY_DESTINATION_INDEX_NAME, + SUMMARY_TEMP_INDEX_NAME, } from '../../common/constants'; -import { getSLOIndexTemplate } from '../assets/index_templates/slo_index_templates'; -import { getSLOSummaryIndexTemplate } from '../assets/index_templates/slo_summary_index_templates'; - +import { SLI_MAPPINGS_TEMPLATE } from '../assets/component_templates/slI_mappings_template'; +import { SLI_SETTINGS_TEMPLATE } from '../assets/component_templates/slI_settings_template'; +import { SUMMARY_MAPPINGS_TEMPLATE } from '../assets/component_templates/summary_mappings_template'; +import { SUMMARY_SETTINGS_TEMPLATE } from '../assets/component_templates/summary_settings_template'; +import { SLI_INDEX_TEMPLATE } from '../assets/index_templates/sli_index_template'; +import { SUMMARY_INDEX_TEMPLATE } from '../assets/index_templates/summary_index_template'; import { retryTransientEsErrors } from '../utils/retry'; export interface ResourceInstaller { @@ -37,50 +28,39 @@ export interface ResourceInstaller { } export class DefaultResourceInstaller implements ResourceInstaller { + private isInstalling: boolean = false; + constructor(private esClient: ElasticsearchClient, private logger: Logger) {} - public async ensureCommonResourcesInstalled(): Promise { + public async ensureCommonResourcesInstalled() { + if (this.isInstalling) { + return; + } + this.isInstalling = true; + + let installTimeout; try { + installTimeout = setTimeout(() => (this.isInstalling = false), 60000); + this.logger.info('Installing SLO shared resources'); await Promise.all([ - this.createOrUpdateComponentTemplate( - getSLOMappingsTemplate(SLO_COMPONENT_TEMPLATE_MAPPINGS_NAME) - ), - this.createOrUpdateComponentTemplate( - getSLOSettingsTemplate(SLO_COMPONENT_TEMPLATE_SETTINGS_NAME) - ), - this.createOrUpdateComponentTemplate( - getSLOSummaryMappingsTemplate(SLO_SUMMARY_COMPONENT_TEMPLATE_MAPPINGS_NAME) - ), - this.createOrUpdateComponentTemplate( - getSLOSummarySettingsTemplate(SLO_SUMMARY_COMPONENT_TEMPLATE_SETTINGS_NAME) - ), + this.createOrUpdateComponentTemplate(SLI_MAPPINGS_TEMPLATE), + this.createOrUpdateComponentTemplate(SLI_SETTINGS_TEMPLATE), + this.createOrUpdateComponentTemplate(SUMMARY_MAPPINGS_TEMPLATE), + this.createOrUpdateComponentTemplate(SUMMARY_SETTINGS_TEMPLATE), ]); - await this.createOrUpdateIndexTemplate( - getSLOIndexTemplate(SLO_INDEX_TEMPLATE_NAME, SLO_INDEX_TEMPLATE_PATTERN, [ - SLO_COMPONENT_TEMPLATE_MAPPINGS_NAME, - SLO_COMPONENT_TEMPLATE_SETTINGS_NAME, - ]) - ); - - await this.createOrUpdateIndexTemplate( - getSLOSummaryIndexTemplate( - SLO_SUMMARY_INDEX_TEMPLATE_NAME, - SLO_SUMMARY_INDEX_TEMPLATE_PATTERN, - [ - SLO_SUMMARY_COMPONENT_TEMPLATE_MAPPINGS_NAME, - SLO_SUMMARY_COMPONENT_TEMPLATE_SETTINGS_NAME, - ] - ) - ); - - await this.createIndex(SLO_DESTINATION_INDEX_NAME); - await this.createIndex(SLO_SUMMARY_DESTINATION_INDEX_NAME); - await this.createIndex(SLO_SUMMARY_TEMP_INDEX_NAME); + await this.createOrUpdateIndexTemplate(SLI_INDEX_TEMPLATE); + await this.createOrUpdateIndexTemplate(SUMMARY_INDEX_TEMPLATE); + + await this.createIndex(SLI_DESTINATION_INDEX_NAME); + await this.createIndex(SUMMARY_DESTINATION_INDEX_NAME); + await this.createIndex(SUMMARY_TEMP_INDEX_NAME); } catch (err) { this.logger.error(`Error while installing SLO shared resources: ${err}`); - throw err; + } finally { + this.isInstalling = false; + clearTimeout(installTimeout); } } diff --git a/x-pack/solutions/observability/plugins/slo/server/services/slo_definition_client.ts b/x-pack/solutions/observability/plugins/slo/server/services/slo_definition_client.ts index 39e3d3f446e39..26daeb833c3b0 100644 --- a/x-pack/solutions/observability/plugins/slo/server/services/slo_definition_client.ts +++ b/x-pack/solutions/observability/plugins/slo/server/services/slo_definition_client.ts @@ -6,7 +6,7 @@ */ import { ElasticsearchClient, Logger } from '@kbn/core/server'; -import { SLO_SUMMARY_DESTINATION_INDEX_PATTERN } from '../../common/constants'; +import { SUMMARY_DESTINATION_INDEX_PATTERN } from '../../common/constants'; import { SLODefinition } from '../domain/models'; import { SLORepository } from './slo_repository'; import { EsSummaryDocument } from './summary_transform_generator/helpers/create_temp_summary'; @@ -34,7 +34,7 @@ export class SloDefinitionClient { ): Promise { if (remoteName) { const summarySearch = await this.esClient.search({ - index: `${remoteName}:${SLO_SUMMARY_DESTINATION_INDEX_PATTERN}`, + index: `${remoteName}:${SUMMARY_DESTINATION_INDEX_PATTERN}`, query: { bool: { filter: [{ term: { spaceId } }, { term: { 'slo.id': sloId } }], diff --git a/x-pack/solutions/observability/plugins/slo/server/services/slo_installer.test.ts b/x-pack/solutions/observability/plugins/slo/server/services/slo_installer.test.ts deleted file mode 100644 index 92d0865ec5c9f..0000000000000 --- a/x-pack/solutions/observability/plugins/slo/server/services/slo_installer.test.ts +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { loggingSystemMock } from '@kbn/core/server/mocks'; -import { MockedLogger } from '@kbn/logging-mocks'; -import { createResourceInstallerMock } from './mocks'; -import { DefaultSLOInstaller } from './slo_installer'; - -describe('SLO Installer', () => { - let loggerMock: jest.Mocked; - - beforeEach(() => { - loggerMock = loggingSystemMock.createLogger(); - }); - - it.skip('handles concurrent installation', async () => { - const resourceInstaller = createResourceInstallerMock(); - const service = new DefaultSLOInstaller(resourceInstaller, loggerMock); - - await Promise.all([service.install(), service.install()]); - - expect(resourceInstaller.ensureCommonResourcesInstalled).toHaveBeenCalledTimes(1); - }); -}); diff --git a/x-pack/solutions/observability/plugins/slo/server/services/slo_installer.ts b/x-pack/solutions/observability/plugins/slo/server/services/slo_installer.ts deleted file mode 100644 index eab4c266aae8e..0000000000000 --- a/x-pack/solutions/observability/plugins/slo/server/services/slo_installer.ts +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { Logger } from '@kbn/core/server'; -import { ResourceInstaller } from '.'; - -export interface SLOInstaller { - install(): Promise; -} - -export class DefaultSLOInstaller implements SLOInstaller { - private isInstalling: boolean = false; - - constructor(private sloResourceInstaller: ResourceInstaller, private logger: Logger) {} - - public async install() { - if (this.isInstalling) { - return; - } - this.isInstalling = true; - - let installTimeout; - try { - installTimeout = setTimeout(() => (this.isInstalling = false), 60000); - - await this.sloResourceInstaller.ensureCommonResourcesInstalled(); - } catch (error) { - this.logger.error(`Failed to install SLO common resources: ${error}`); - } finally { - this.isInstalling = false; - clearTimeout(installTimeout); - } - } -} diff --git a/x-pack/solutions/observability/plugins/slo/server/services/slo_repository.test.ts b/x-pack/solutions/observability/plugins/slo/server/services/slo_repository.test.ts deleted file mode 100644 index 633ee359ca53f..0000000000000 --- a/x-pack/solutions/observability/plugins/slo/server/services/slo_repository.test.ts +++ /dev/null @@ -1,274 +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 { SavedObjectsClientContract, SavedObjectsFindResponse } from '@kbn/core/server'; -import { loggingSystemMock, savedObjectsClientMock } from '@kbn/core/server/mocks'; -import { MockedLogger } from '@kbn/logging-mocks'; -import { sloDefinitionSchema } from '@kbn/slo-schema'; -import { SLO_MODEL_VERSION } from '../../common/constants'; -import { SLODefinition, StoredSLODefinition } from '../domain/models'; -import { SLONotFound } from '../errors'; -import { SO_SLO_TYPE } from '../saved_objects'; -import { aStoredSLO, createAPMTransactionDurationIndicator, createSLO } from './fixtures/slo'; -import { KibanaSavedObjectsSLORepository } from './slo_repository'; - -const SOME_SLO = createSLO({ indicator: createAPMTransactionDurationIndicator() }); -const ANOTHER_SLO = createSLO(); -const INVALID_SLO_ID = 'invalid-slo-id'; - -function soFindResponse( - sloList: SLODefinition[], - includeInvalidStoredSLO: boolean = false -): SavedObjectsFindResponse { - return { - page: 1, - per_page: 25, - total: includeInvalidStoredSLO ? sloList.length + 1 : sloList.length, - // @ts-ignore invalid SLO is not following shape of StoredSLO - saved_objects: [ - ...sloList.map((slo) => ({ - id: slo.id, - attributes: sloDefinitionSchema.encode(slo), - type: SO_SLO_TYPE, - references: [], - score: 1, - })), - ...(includeInvalidStoredSLO - ? [ - { - id: 'invalid-so-id', - type: SO_SLO_TYPE, - references: [], - score: 1, - attributes: { id: INVALID_SLO_ID, name: 'invalid' }, - }, - ] - : []), - ], - }; -} - -describe('KibanaSavedObjectsSLORepository', () => { - let loggerMock: jest.Mocked; - let soClientMock: jest.Mocked; - - beforeEach(() => { - loggerMock = loggingSystemMock.createLogger(); - soClientMock = savedObjectsClientMock.create(); - }); - - describe('validation', () => { - it('findById throws when an SLO is not found', async () => { - soClientMock.find.mockResolvedValueOnce(soFindResponse([])); - const repository = new KibanaSavedObjectsSLORepository(soClientMock, loggerMock); - - await expect(repository.findById('inexistant-slo-id')).rejects.toThrowError( - new SLONotFound('SLO [inexistant-slo-id] not found') - ); - }); - - it('deleteById throws when an SLO is not found', async () => { - soClientMock.find.mockResolvedValueOnce(soFindResponse([])); - const repository = new KibanaSavedObjectsSLORepository(soClientMock, loggerMock); - - await expect(repository.deleteById('inexistant-slo-id')).rejects.toThrowError( - new SLONotFound('SLO [inexistant-slo-id] not found') - ); - }); - }); - - describe('saving an SLO', () => { - it('checking existing id for slo', async () => { - const slo = createSLO({ id: 'my-id' }); - soClientMock.find.mockResolvedValueOnce(soFindResponse([])); - soClientMock.create.mockResolvedValueOnce(aStoredSLO(slo)); - const repository = new KibanaSavedObjectsSLORepository(soClientMock, loggerMock); - - await repository.exists(slo.id); - - expect(soClientMock.find).toHaveBeenCalledWith({ - type: SO_SLO_TYPE, - perPage: 0, - filter: `slo.attributes.id:(${slo.id})`, - }); - }); - - it('saves the new SLO', async () => { - const slo = createSLO({ id: 'my-id' }); - soClientMock.find.mockResolvedValueOnce(soFindResponse([])); - soClientMock.create.mockResolvedValueOnce(aStoredSLO(slo)); - const repository = new KibanaSavedObjectsSLORepository(soClientMock, loggerMock); - - const savedSLO = await repository.create(slo); - - expect(savedSLO).toEqual(slo); - expect(soClientMock.create).toHaveBeenCalledWith( - SO_SLO_TYPE, - sloDefinitionSchema.encode(slo) - ); - }); - - it('checks when the SLO id already exists', async () => { - const slo = createSLO({ id: 'my-id' }); - soClientMock.find.mockResolvedValueOnce(soFindResponse([slo])); - const repository = new KibanaSavedObjectsSLORepository(soClientMock, loggerMock); - - await expect(await repository.exists(slo.id)).toEqual(true); - expect(soClientMock.find).toHaveBeenCalledWith({ - type: SO_SLO_TYPE, - perPage: 0, - filter: `slo.attributes.id:(${slo.id})`, - }); - }); - - it('updates the existing SLO', async () => { - const slo = createSLO({ id: 'my-id' }); - soClientMock.find.mockResolvedValueOnce(soFindResponse([slo])); - soClientMock.create.mockResolvedValueOnce(aStoredSLO(slo)); - const repository = new KibanaSavedObjectsSLORepository(soClientMock, loggerMock); - - const savedSLO = await repository.update(slo); - - expect(savedSLO).toEqual(slo); - - expect(soClientMock.create).toHaveBeenCalledWith( - SO_SLO_TYPE, - sloDefinitionSchema.encode(slo), - { - id: 'my-id', - overwrite: true, - } - ); - }); - }); - - describe('Find SLO', () => { - it('finds an existing SLO', async () => { - const repository = new KibanaSavedObjectsSLORepository(soClientMock, loggerMock); - soClientMock.find.mockResolvedValueOnce(soFindResponse([SOME_SLO])); - - const foundSLO = await repository.findById(SOME_SLO.id); - - expect(foundSLO).toEqual(SOME_SLO); - expect(soClientMock.find).toHaveBeenCalledWith({ - type: SO_SLO_TYPE, - page: 1, - perPage: 1, - filter: `slo.attributes.id:(${SOME_SLO.id})`, - }); - }); - - it('throws and logs error on invalid stored SLO', async () => { - const INCLUDE_INVALID_STORED_SLO = true; - const repository = new KibanaSavedObjectsSLORepository(soClientMock, loggerMock); - soClientMock.find.mockResolvedValueOnce(soFindResponse([], INCLUDE_INVALID_STORED_SLO)); - - await expect(repository.findById(INVALID_SLO_ID)).rejects.toThrowError( - new Error('Invalid stored SLO') - ); - - expect(loggerMock.error).toHaveBeenCalled(); - }); - }); - - describe('Find all SLO by ids', () => { - it('returns the SLOs', async () => { - const repository = new KibanaSavedObjectsSLORepository(soClientMock, loggerMock); - soClientMock.find.mockResolvedValueOnce(soFindResponse([SOME_SLO, ANOTHER_SLO])); - - const results = await repository.findAllByIds([SOME_SLO.id, ANOTHER_SLO.id]); - - expect(results).toEqual([SOME_SLO, ANOTHER_SLO]); - expect(soClientMock.find).toHaveBeenCalledWith({ - type: SO_SLO_TYPE, - page: 1, - perPage: 2, - filter: `slo.attributes.id:(${SOME_SLO.id} or ${ANOTHER_SLO.id})`, - }); - }); - - it('handles invalid stored SLO by logging error', async () => { - const INCLUDE_INVALID_STORED_SLO = true; - const repository = new KibanaSavedObjectsSLORepository(soClientMock, loggerMock); - soClientMock.find.mockResolvedValueOnce( - soFindResponse([SOME_SLO, ANOTHER_SLO], INCLUDE_INVALID_STORED_SLO) - ); - - const results = await repository.findAllByIds([SOME_SLO.id, INVALID_SLO_ID, ANOTHER_SLO.id]); - - expect(loggerMock.error).toHaveBeenCalled(); - expect(results).toEqual([SOME_SLO, ANOTHER_SLO]); - }); - }); - - it('deletes an SLO', async () => { - const repository = new KibanaSavedObjectsSLORepository(soClientMock, loggerMock); - soClientMock.find.mockResolvedValueOnce(soFindResponse([SOME_SLO])); - - await repository.deleteById(SOME_SLO.id); - - expect(soClientMock.find).toHaveBeenCalledWith({ - type: SO_SLO_TYPE, - page: 1, - perPage: 1, - filter: `slo.attributes.id:(${SOME_SLO.id})`, - }); - expect(soClientMock.delete).toHaveBeenCalledWith(SO_SLO_TYPE, SOME_SLO.id); - }); - - describe('search', () => { - it('searches by name', async () => { - const repository = new KibanaSavedObjectsSLORepository(soClientMock, loggerMock); - soClientMock.find.mockResolvedValueOnce(soFindResponse([SOME_SLO, ANOTHER_SLO])); - - const results = await repository.search(SOME_SLO.name, { page: 1, perPage: 100 }); - - expect(results.results).toEqual([SOME_SLO, ANOTHER_SLO]); - expect(soClientMock.find).toHaveBeenCalledWith({ - type: SO_SLO_TYPE, - page: 1, - perPage: 100, - search: SOME_SLO.name, - searchFields: ['name'], - }); - }); - - it('searches only the outdated ones', async () => { - const repository = new KibanaSavedObjectsSLORepository(soClientMock, loggerMock); - soClientMock.find.mockResolvedValueOnce(soFindResponse([SOME_SLO, ANOTHER_SLO])); - - const results = await repository.search( - SOME_SLO.name, - { page: 1, perPage: 100 }, - { includeOutdatedOnly: true } - ); - - expect(results.results).toEqual([SOME_SLO, ANOTHER_SLO]); - expect(soClientMock.find).toHaveBeenCalledWith({ - type: SO_SLO_TYPE, - page: 1, - perPage: 100, - search: SOME_SLO.name, - searchFields: ['name'], - filter: `slo.attributes.version < ${SLO_MODEL_VERSION}`, - }); - }); - - it('handles invalid stored SLO by logging error', async () => { - const INCLUDE_INVALID_STORED_SLO = true; - const repository = new KibanaSavedObjectsSLORepository(soClientMock, loggerMock); - soClientMock.find.mockResolvedValueOnce( - soFindResponse([SOME_SLO, ANOTHER_SLO], INCLUDE_INVALID_STORED_SLO) - ); - - const results = await repository.search('*', { page: 1, perPage: 100 }); - - expect(loggerMock.error).toHaveBeenCalled(); - expect(results.results).toEqual([SOME_SLO, ANOTHER_SLO]); - }); - }); -}); diff --git a/x-pack/solutions/observability/plugins/slo/server/services/slo_settings.ts b/x-pack/solutions/observability/plugins/slo/server/services/slo_settings.ts index 3874ab808dc34..d6ef76e4f2458 100644 --- a/x-pack/solutions/observability/plugins/slo/server/services/slo_settings.ts +++ b/x-pack/solutions/observability/plugins/slo/server/services/slo_settings.ts @@ -11,7 +11,7 @@ import { SavedObjectsErrorHelpers } from '@kbn/core-saved-objects-server'; import { PutSLOSettingsParams, sloSettingsSchema } from '@kbn/slo-schema'; import { DEFAULT_STALE_SLO_THRESHOLD_HOURS, - SLO_SUMMARY_DESTINATION_INDEX_PATTERN, + SUMMARY_DESTINATION_INDEX_PATTERN, } from '../../common/constants'; import { getListOfSloSummaryIndices } from '../../common/summary_indices'; import { SLOSettings, StoredSLOSettings } from '../domain/models'; @@ -62,7 +62,7 @@ export const getListOfSummaryIndices = async ( ) => { const { useAllRemoteClusters, selectedRemoteClusters } = settings; if (!useAllRemoteClusters && selectedRemoteClusters.length === 0) { - return { indices: [SLO_SUMMARY_DESTINATION_INDEX_PATTERN], settings }; + return { indices: [SUMMARY_DESTINATION_INDEX_PATTERN], settings }; } const clustersByName = await esClient.cluster.remoteInfo(); diff --git a/x-pack/solutions/observability/plugins/slo/server/services/summary_client.test.ts b/x-pack/solutions/observability/plugins/slo/server/services/summary_client.test.ts index 120285f374f4d..92433476c6515 100644 --- a/x-pack/solutions/observability/plugins/slo/server/services/summary_client.test.ts +++ b/x-pack/solutions/observability/plugins/slo/server/services/summary_client.test.ts @@ -7,7 +7,7 @@ import { ElasticsearchClientMock, elasticsearchServiceMock } from '@kbn/core/server/mocks'; import moment from 'moment'; -import { SLO_DESTINATION_INDEX_PATTERN } from '../../common/constants'; +import { SLI_DESTINATION_INDEX_PATTERN } from '../../common/constants'; import { Duration, DurationUnit } from '../domain/models'; import { BurnRatesClient } from './burn_rates_client'; import { createSLO } from './fixtures/slo'; @@ -59,7 +59,7 @@ describe('SummaryClient', () => { expect(result).toMatchSnapshot(); expect(esClientMock.search.mock.calls[0][0]).toEqual({ - index: SLO_DESTINATION_INDEX_PATTERN, + index: SLI_DESTINATION_INDEX_PATTERN, size: 0, query: { bool: { @@ -93,7 +93,7 @@ describe('SummaryClient', () => { await summaryClient.computeSummary({ slo }); expect(esClientMock.search.mock.calls[0][0]).toEqual({ - index: SLO_DESTINATION_INDEX_PATTERN, + index: SLI_DESTINATION_INDEX_PATTERN, size: 0, query: { bool: { @@ -137,7 +137,7 @@ describe('SummaryClient', () => { expect(result).toMatchSnapshot(); expect(esClientMock.search.mock.calls[0][0]).toEqual({ - index: SLO_DESTINATION_INDEX_PATTERN, + index: SLI_DESTINATION_INDEX_PATTERN, size: 0, query: { bool: { @@ -179,7 +179,7 @@ describe('SummaryClient', () => { expect(result).toMatchSnapshot(); expect(esClientMock.search.mock.calls[0][0]).toEqual({ - index: SLO_DESTINATION_INDEX_PATTERN, + index: SLI_DESTINATION_INDEX_PATTERN, size: 0, query: { bool: { diff --git a/x-pack/solutions/observability/plugins/slo/server/services/summary_client.ts b/x-pack/solutions/observability/plugins/slo/server/services/summary_client.ts index 23110db94cdde..bb98c4443f0f2 100644 --- a/x-pack/solutions/observability/plugins/slo/server/services/summary_client.ts +++ b/x-pack/solutions/observability/plugins/slo/server/services/summary_client.ts @@ -19,7 +19,7 @@ import { occurrencesBudgetingMethodSchema, timeslicesBudgetingMethodSchema, } from '@kbn/slo-schema'; -import { SLO_DESTINATION_INDEX_PATTERN } from '../../common/constants'; +import { SLI_DESTINATION_INDEX_PATTERN } from '../../common/constants'; import { DateRange, Groupings, Meta, SLODefinition, Summary } from '../domain/models'; import { computeSLI, computeSummaryStatus, toErrorBudget } from '../domain/services'; import { toDateRange } from '../domain/services/date_range'; @@ -69,8 +69,8 @@ export class DefaultSummaryClient implements SummaryClient { } >({ index: remoteName - ? `${remoteName}:${SLO_DESTINATION_INDEX_PATTERN}` - : SLO_DESTINATION_INDEX_PATTERN, + ? `${remoteName}:${SLI_DESTINATION_INDEX_PATTERN}` + : SLI_DESTINATION_INDEX_PATTERN, size: 0, query: { bool: { diff --git a/x-pack/solutions/observability/plugins/slo/server/services/summary_search_client/summary_search_client.ts b/x-pack/solutions/observability/plugins/slo/server/services/summary_search_client/summary_search_client.ts index 5c1c0e9e780cb..9ef20d333cc75 100644 --- a/x-pack/solutions/observability/plugins/slo/server/services/summary_search_client/summary_search_client.ts +++ b/x-pack/solutions/observability/plugins/slo/server/services/summary_search_client/summary_search_client.ts @@ -11,7 +11,7 @@ import { isCCSRemoteIndexName } from '@kbn/es-query'; import { ALL_VALUE } from '@kbn/slo-schema'; import { assertNever } from '@kbn/std'; import { partition } from 'lodash'; -import { SLO_SUMMARY_DESTINATION_INDEX_PATTERN } from '../../../common/constants'; +import { SUMMARY_DESTINATION_INDEX_PATTERN } from '../../../common/constants'; import { StoredSLOSettings } from '../../domain/models'; import { toHighPrecision } from '../../utils/number'; import { createEsParams, typedSearch } from '../../utils/queries'; @@ -170,7 +170,7 @@ export class DefaultSummarySearchClient implements SummarySearchClient { // The temp summary documents are _eventually_ removed as we get through the real summary documents await this.esClient.deleteByQuery({ - index: SLO_SUMMARY_DESTINATION_INDEX_PATTERN, + index: SUMMARY_DESTINATION_INDEX_PATTERN, wait_for_completion: false, query: { bool: { diff --git a/x-pack/solutions/observability/plugins/slo/server/services/summary_transform_generator/generators/occurrences.ts b/x-pack/solutions/observability/plugins/slo/server/services/summary_transform_generator/generators/occurrences.ts index ab5377e38b12e..4615222dd7525 100644 --- a/x-pack/solutions/observability/plugins/slo/server/services/summary_transform_generator/generators/occurrences.ts +++ b/x-pack/solutions/observability/plugins/slo/server/services/summary_transform_generator/generators/occurrences.ts @@ -10,9 +10,9 @@ import { calendarAlignedTimeWindowSchema, DurationUnit } from '@kbn/slo-schema'; import { getSLOSummaryPipelineId, getSLOSummaryTransformId, - SLO_DESTINATION_INDEX_NAME, + SLI_DESTINATION_INDEX_NAME, SLO_RESOURCES_VERSION, - SLO_SUMMARY_DESTINATION_INDEX_NAME, + SUMMARY_DESTINATION_INDEX_NAME, } from '../../../../common/constants'; import { SLODefinition } from '../../../domain/models'; import { getGroupBy } from './common'; @@ -37,10 +37,10 @@ export function generateSummaryTransformForOccurrences( transform_id: getSLOSummaryTransformId(slo.id, slo.revision), dest: { pipeline: getSLOSummaryPipelineId(slo.id, slo.revision), - index: SLO_SUMMARY_DESTINATION_INDEX_NAME, + index: SUMMARY_DESTINATION_INDEX_NAME, }, source: { - index: `${SLO_DESTINATION_INDEX_NAME}*`, + index: `${SLI_DESTINATION_INDEX_NAME}*`, query: { bool: { filter: [ diff --git a/x-pack/solutions/observability/plugins/slo/server/services/summary_transform_generator/generators/timeslices_calendar_aligned.ts b/x-pack/solutions/observability/plugins/slo/server/services/summary_transform_generator/generators/timeslices_calendar_aligned.ts index f5db77467c94d..52949158ca951 100644 --- a/x-pack/solutions/observability/plugins/slo/server/services/summary_transform_generator/generators/timeslices_calendar_aligned.ts +++ b/x-pack/solutions/observability/plugins/slo/server/services/summary_transform_generator/generators/timeslices_calendar_aligned.ts @@ -9,9 +9,9 @@ import { TransformPutTransformRequest } from '@elastic/elasticsearch/lib/api/typ import { getSLOSummaryPipelineId, getSLOSummaryTransformId, - SLO_DESTINATION_INDEX_NAME, + SLI_DESTINATION_INDEX_NAME, SLO_RESOURCES_VERSION, - SLO_SUMMARY_DESTINATION_INDEX_NAME, + SUMMARY_DESTINATION_INDEX_NAME, } from '../../../../common/constants'; import { DurationUnit, SLODefinition } from '../../../domain/models'; import { getGroupBy } from './common'; @@ -27,10 +27,10 @@ export function generateSummaryTransformForTimeslicesAndCalendarAligned( transform_id: getSLOSummaryTransformId(slo.id, slo.revision), dest: { pipeline: getSLOSummaryPipelineId(slo.id, slo.revision), - index: SLO_SUMMARY_DESTINATION_INDEX_NAME, + index: SUMMARY_DESTINATION_INDEX_NAME, }, source: { - index: `${SLO_DESTINATION_INDEX_NAME}*`, + index: `${SLI_DESTINATION_INDEX_NAME}*`, query: { bool: { filter: [ diff --git a/x-pack/solutions/observability/plugins/slo/server/services/summary_transform_generator/generators/timeslices_rolling.ts b/x-pack/solutions/observability/plugins/slo/server/services/summary_transform_generator/generators/timeslices_rolling.ts index 05724cb9e43d6..c5f06b465d896 100644 --- a/x-pack/solutions/observability/plugins/slo/server/services/summary_transform_generator/generators/timeslices_rolling.ts +++ b/x-pack/solutions/observability/plugins/slo/server/services/summary_transform_generator/generators/timeslices_rolling.ts @@ -9,9 +9,9 @@ import { TransformPutTransformRequest } from '@elastic/elasticsearch/lib/api/typ import { getSLOSummaryPipelineId, getSLOSummaryTransformId, - SLO_DESTINATION_INDEX_NAME, + SLI_DESTINATION_INDEX_NAME, SLO_RESOURCES_VERSION, - SLO_SUMMARY_DESTINATION_INDEX_NAME, + SUMMARY_DESTINATION_INDEX_NAME, } from '../../../../common/constants'; import { SLODefinition } from '../../../domain/models'; import { getGroupBy } from './common'; @@ -28,10 +28,10 @@ export function generateSummaryTransformForTimeslicesAndRolling( transform_id: getSLOSummaryTransformId(slo.id, slo.revision), dest: { pipeline: getSLOSummaryPipelineId(slo.id, slo.revision), - index: SLO_SUMMARY_DESTINATION_INDEX_NAME, + index: SUMMARY_DESTINATION_INDEX_NAME, }, source: { - index: `${SLO_DESTINATION_INDEX_NAME}*`, + index: `${SLI_DESTINATION_INDEX_NAME}*`, query: { bool: { filter: [ diff --git a/x-pack/solutions/observability/plugins/slo/server/services/tasks/orphan_summary_cleanup_task.test.ts b/x-pack/solutions/observability/plugins/slo/server/services/tasks/orphan_summary_cleanup_task.test.ts index 31b74b3cf9ed4..dc714d8ee8dd4 100644 --- a/x-pack/solutions/observability/plugins/slo/server/services/tasks/orphan_summary_cleanup_task.test.ts +++ b/x-pack/solutions/observability/plugins/slo/server/services/tasks/orphan_summary_cleanup_task.test.ts @@ -10,7 +10,7 @@ import { savedObjectsClientMock } from '@kbn/core-saved-objects-api-server-mocks import { loggerMock } from '@kbn/logging-mocks'; import { taskManagerMock } from '@kbn/task-manager-plugin/server/mocks'; import { times } from 'lodash'; -import { SLO_SUMMARY_DESTINATION_INDEX_PATTERN } from '../../../common/constants'; +import { SUMMARY_DESTINATION_INDEX_PATTERN } from '../../../common/constants'; import { getDeleteQueryFilter, SloOrphanSummaryCleanupTask } from './orphan_summary_cleanup_task'; const taskManagerSetup = taskManagerMock.createSetup(); @@ -59,7 +59,7 @@ describe('SloSummaryCleanupTask', () => { expect(task.fetchSloSummariesIds).toHaveBeenCalled(); expect(esClient.deleteByQuery).toHaveBeenCalledWith({ - index: SLO_SUMMARY_DESTINATION_INDEX_PATTERN, + index: SUMMARY_DESTINATION_INDEX_PATTERN, query: { bool: { should: [ @@ -100,7 +100,7 @@ describe('SloSummaryCleanupTask', () => { expect(esClient.deleteByQuery).toHaveBeenCalledTimes(1); expect(esClient.deleteByQuery).toHaveBeenNthCalledWith(1, { wait_for_completion: false, - index: SLO_SUMMARY_DESTINATION_INDEX_PATTERN, + index: SUMMARY_DESTINATION_INDEX_PATTERN, query: { bool: { should: getDeleteQueryFilter([ @@ -158,7 +158,7 @@ describe('SloSummaryCleanupTask', () => { expect(esClient.deleteByQuery).toHaveBeenCalledTimes(2); expect(esClient.deleteByQuery).toHaveBeenNthCalledWith(1, { - index: SLO_SUMMARY_DESTINATION_INDEX_PATTERN, + index: SUMMARY_DESTINATION_INDEX_PATTERN, query: { bool: { should: getDeleteQueryFilter([ @@ -174,7 +174,7 @@ describe('SloSummaryCleanupTask', () => { expect(esClient.deleteByQuery).toHaveBeenLastCalledWith({ wait_for_completion: false, - index: SLO_SUMMARY_DESTINATION_INDEX_PATTERN, + index: SUMMARY_DESTINATION_INDEX_PATTERN, query: { bool: { should: getDeleteQueryFilter([ @@ -232,7 +232,7 @@ describe('SloSummaryCleanupTask', () => { expect(esClient.deleteByQuery).toHaveBeenCalledTimes(2); expect(esClient.deleteByQuery).toHaveBeenNthCalledWith(1, { wait_for_completion: false, - index: SLO_SUMMARY_DESTINATION_INDEX_PATTERN, + index: SUMMARY_DESTINATION_INDEX_PATTERN, query: { bool: { should: getDeleteQueryFilter([ @@ -246,7 +246,7 @@ describe('SloSummaryCleanupTask', () => { }); expect(esClient.deleteByQuery).toHaveBeenLastCalledWith({ wait_for_completion: false, - index: SLO_SUMMARY_DESTINATION_INDEX_PATTERN, + index: SUMMARY_DESTINATION_INDEX_PATTERN, query: { bool: { should: getDeleteQueryFilter([ @@ -300,7 +300,7 @@ describe('SloSummaryCleanupTask', () => { expect(esClient.deleteByQuery).toHaveBeenNthCalledWith(1, { wait_for_completion: false, - index: SLO_SUMMARY_DESTINATION_INDEX_PATTERN, + index: SUMMARY_DESTINATION_INDEX_PATTERN, query: { bool: { should: getDeleteQueryFilter([ diff --git a/x-pack/solutions/observability/plugins/slo/server/services/tasks/orphan_summary_cleanup_task.ts b/x-pack/solutions/observability/plugins/slo/server/services/tasks/orphan_summary_cleanup_task.ts index 6d0aa1ee9c587..55316671ef05f 100644 --- a/x-pack/solutions/observability/plugins/slo/server/services/tasks/orphan_summary_cleanup_task.ts +++ b/x-pack/solutions/observability/plugins/slo/server/services/tasks/orphan_summary_cleanup_task.ts @@ -15,7 +15,7 @@ import { AggregationsCompositeAggregateKey } from '@elastic/elasticsearch/lib/ap import { ALL_SPACES_ID } from '@kbn/spaces-plugin/common/constants'; import { StoredSLODefinition } from '../../domain/models'; import { SO_SLO_TYPE } from '../../saved_objects'; -import { SLO_SUMMARY_DESTINATION_INDEX_PATTERN } from '../../../common/constants'; +import { SUMMARY_DESTINATION_INDEX_PATTERN } from '../../../common/constants'; import { SLOConfig } from '../../types'; export const TASK_TYPE = 'SLO:ORPHAN_SUMMARIES-CLEANUP-TASK'; @@ -106,7 +106,7 @@ export class SloOrphanSummaryCleanupTask { await this.esClient.deleteByQuery({ wait_for_completion: false, - index: SLO_SUMMARY_DESTINATION_INDEX_PATTERN, + index: SUMMARY_DESTINATION_INDEX_PATTERN, query: { bool: { should: getDeleteQueryFilter(sloSummaryIdsToDelete.sort()), @@ -149,7 +149,7 @@ export class SloOrphanSummaryCleanupTask { } >({ size: 0, - index: SLO_SUMMARY_DESTINATION_INDEX_PATTERN, + index: SUMMARY_DESTINATION_INDEX_PATTERN, aggs: { slos: { composite: { diff --git a/x-pack/solutions/observability/plugins/slo/server/services/transform_generators/apm_transaction_duration.ts b/x-pack/solutions/observability/plugins/slo/server/services/transform_generators/apm_transaction_duration.ts index 99361fa776789..71b14ac5c3477 100644 --- a/x-pack/solutions/observability/plugins/slo/server/services/transform_generators/apm_transaction_duration.ts +++ b/x-pack/solutions/observability/plugins/slo/server/services/transform_generators/apm_transaction_duration.ts @@ -16,7 +16,7 @@ import { } from '@kbn/slo-schema'; import { TransformGenerator, getElasticsearchQueryOrThrow } from '.'; import { - SLO_DESTINATION_INDEX_NAME, + SLI_DESTINATION_INDEX_NAME, getSLOPipelineId, getSLOTransformId, } from '../../../common/constants'; @@ -133,7 +133,7 @@ export class ApmTransactionDurationTransformGenerator extends TransformGenerator private buildDestination(slo: SLODefinition) { return { pipeline: getSLOPipelineId(slo.id, slo.revision), - index: SLO_DESTINATION_INDEX_NAME, + index: SLI_DESTINATION_INDEX_NAME, }; } diff --git a/x-pack/solutions/observability/plugins/slo/server/services/transform_generators/apm_transaction_error_rate.ts b/x-pack/solutions/observability/plugins/slo/server/services/transform_generators/apm_transaction_error_rate.ts index a65e4ae1d50dd..5e78b598cfd9c 100644 --- a/x-pack/solutions/observability/plugins/slo/server/services/transform_generators/apm_transaction_error_rate.ts +++ b/x-pack/solutions/observability/plugins/slo/server/services/transform_generators/apm_transaction_error_rate.ts @@ -15,7 +15,7 @@ import { } from '@kbn/slo-schema'; import { TransformGenerator, getElasticsearchQueryOrThrow } from '.'; import { - SLO_DESTINATION_INDEX_NAME, + SLI_DESTINATION_INDEX_NAME, getSLOPipelineId, getSLOTransformId, } from '../../../common/constants'; @@ -132,7 +132,7 @@ export class ApmTransactionErrorRateTransformGenerator extends TransformGenerato private buildDestination(slo: SLODefinition) { return { pipeline: getSLOPipelineId(slo.id, slo.revision), - index: SLO_DESTINATION_INDEX_NAME, + index: SLI_DESTINATION_INDEX_NAME, }; } diff --git a/x-pack/solutions/observability/plugins/slo/server/services/transform_generators/histogram.ts b/x-pack/solutions/observability/plugins/slo/server/services/transform_generators/histogram.ts index 805e18c9c31db..6a2b0cc5d7a85 100644 --- a/x-pack/solutions/observability/plugins/slo/server/services/transform_generators/histogram.ts +++ b/x-pack/solutions/observability/plugins/slo/server/services/transform_generators/histogram.ts @@ -14,7 +14,7 @@ import { } from '@kbn/slo-schema'; import { TransformGenerator, getElasticsearchQueryOrThrow, parseIndex } from '.'; import { - SLO_DESTINATION_INDEX_NAME, + SLI_DESTINATION_INDEX_NAME, getSLOPipelineId, getSLOTransformId, } from '../../../common/constants'; @@ -70,7 +70,7 @@ export class HistogramTransformGenerator extends TransformGenerator { private buildDestination(slo: SLODefinition) { return { pipeline: getSLOPipelineId(slo.id, slo.revision), - index: SLO_DESTINATION_INDEX_NAME, + index: SLI_DESTINATION_INDEX_NAME, }; } diff --git a/x-pack/solutions/observability/plugins/slo/server/services/transform_generators/kql_custom.ts b/x-pack/solutions/observability/plugins/slo/server/services/transform_generators/kql_custom.ts index 61238c82ab600..31ba600f04ede 100644 --- a/x-pack/solutions/observability/plugins/slo/server/services/transform_generators/kql_custom.ts +++ b/x-pack/solutions/observability/plugins/slo/server/services/transform_generators/kql_custom.ts @@ -10,7 +10,7 @@ import { DataViewsService } from '@kbn/data-views-plugin/common'; import { kqlCustomIndicatorSchema, timeslicesBudgetingMethodSchema } from '@kbn/slo-schema'; import { TransformGenerator, getElasticsearchQueryOrThrow, parseIndex } from '.'; import { - SLO_DESTINATION_INDEX_NAME, + SLI_DESTINATION_INDEX_NAME, getSLOPipelineId, getSLOTransformId, } from '../../../common/constants'; @@ -64,7 +64,7 @@ export class KQLCustomTransformGenerator extends TransformGenerator { private buildDestination(slo: SLODefinition) { return { pipeline: getSLOPipelineId(slo.id, slo.revision), - index: SLO_DESTINATION_INDEX_NAME, + index: SLI_DESTINATION_INDEX_NAME, }; } diff --git a/x-pack/solutions/observability/plugins/slo/server/services/transform_generators/metric_custom.ts b/x-pack/solutions/observability/plugins/slo/server/services/transform_generators/metric_custom.ts index f2259955bdfb0..eada58df14160 100644 --- a/x-pack/solutions/observability/plugins/slo/server/services/transform_generators/metric_custom.ts +++ b/x-pack/solutions/observability/plugins/slo/server/services/transform_generators/metric_custom.ts @@ -13,7 +13,7 @@ import { getElasticsearchQueryOrThrow, parseIndex, TransformGenerator } from '.' import { getSLOPipelineId, getSLOTransformId, - SLO_DESTINATION_INDEX_NAME, + SLI_DESTINATION_INDEX_NAME, } from '../../../common/constants'; import { getSLOTransformTemplate } from '../../assets/transform_templates/slo_transform_template'; import { MetricCustomIndicator, SLODefinition } from '../../domain/models'; @@ -68,7 +68,7 @@ export class MetricCustomTransformGenerator extends TransformGenerator { private buildDestination(slo: SLODefinition) { return { pipeline: getSLOPipelineId(slo.id, slo.revision), - index: SLO_DESTINATION_INDEX_NAME, + index: SLI_DESTINATION_INDEX_NAME, }; } diff --git a/x-pack/solutions/observability/plugins/slo/server/services/transform_generators/synthetics_availability.ts b/x-pack/solutions/observability/plugins/slo/server/services/transform_generators/synthetics_availability.ts index 65fda9c3fc222..479674a325b78 100644 --- a/x-pack/solutions/observability/plugins/slo/server/services/transform_generators/synthetics_availability.ts +++ b/x-pack/solutions/observability/plugins/slo/server/services/transform_generators/synthetics_availability.ts @@ -18,7 +18,7 @@ import { getElasticsearchQueryOrThrow, TransformGenerator } from '.'; import { getSLOPipelineId, getSLOTransformId, - SLO_DESTINATION_INDEX_NAME, + SLI_DESTINATION_INDEX_NAME, SYNTHETICS_DEFAULT_GROUPINGS, SYNTHETICS_INDEX_PATTERN, } from '../../../common/constants'; @@ -163,7 +163,7 @@ export class SyntheticsAvailabilityTransformGenerator extends TransformGenerator private buildDestination(slo: SLODefinition) { return { pipeline: getSLOPipelineId(slo.id, slo.revision), - index: SLO_DESTINATION_INDEX_NAME, + index: SLI_DESTINATION_INDEX_NAME, }; } diff --git a/x-pack/solutions/observability/plugins/slo/server/services/transform_generators/timeslice_metric.ts b/x-pack/solutions/observability/plugins/slo/server/services/transform_generators/timeslice_metric.ts index e2f305e68fee8..04cf94d489cc8 100644 --- a/x-pack/solutions/observability/plugins/slo/server/services/transform_generators/timeslice_metric.ts +++ b/x-pack/solutions/observability/plugins/slo/server/services/transform_generators/timeslice_metric.ts @@ -17,7 +17,7 @@ import { getElasticsearchQueryOrThrow, parseIndex, TransformGenerator } from '.' import { getSLOPipelineId, getSLOTransformId, - SLO_DESTINATION_INDEX_NAME, + SLI_DESTINATION_INDEX_NAME, } from '../../../common/constants'; import { getSLOTransformTemplate } from '../../assets/transform_templates/slo_transform_template'; import { SLODefinition } from '../../domain/models'; @@ -73,7 +73,7 @@ export class TimesliceMetricTransformGenerator extends TransformGenerator { private buildDestination(slo: SLODefinition) { return { pipeline: getSLOPipelineId(slo.id, slo.revision), - index: SLO_DESTINATION_INDEX_NAME, + index: SLI_DESTINATION_INDEX_NAME, }; } diff --git a/x-pack/solutions/observability/plugins/slo/server/services/update_slo.test.ts b/x-pack/solutions/observability/plugins/slo/server/services/update_slo.test.ts index 81084683d7978..2f4d9729bf977 100644 --- a/x-pack/solutions/observability/plugins/slo/server/services/update_slo.test.ts +++ b/x-pack/solutions/observability/plugins/slo/server/services/update_slo.test.ts @@ -20,9 +20,9 @@ import { SecurityHasPrivilegesResponse } from '@elastic/elasticsearch/lib/api/ty import { getSLOSummaryTransformId, getSLOTransformId, - SLO_DESTINATION_INDEX_PATTERN, + SLI_DESTINATION_INDEX_PATTERN, SLO_RESOURCES_VERSION, - SLO_SUMMARY_DESTINATION_INDEX_PATTERN, + SUMMARY_DESTINATION_INDEX_PATTERN, } from '../../common/constants'; import { SLODefinition } from '../domain/models'; import { fiveMinute, oneMinute } from './fixtures/duration'; @@ -498,7 +498,7 @@ describe('UpdateSLO', () => { expect(mockEsClient.deleteByQuery).toHaveBeenNthCalledWith( 1, expect.objectContaining({ - index: SLO_DESTINATION_INDEX_PATTERN, + index: SLI_DESTINATION_INDEX_PATTERN, query: { bool: { filter: [ @@ -512,7 +512,7 @@ describe('UpdateSLO', () => { expect(mockEsClient.deleteByQuery).toHaveBeenNthCalledWith( 2, expect.objectContaining({ - index: SLO_SUMMARY_DESTINATION_INDEX_PATTERN, + index: SUMMARY_DESTINATION_INDEX_PATTERN, query: { bool: { filter: [ diff --git a/x-pack/solutions/observability/plugins/slo/server/services/update_slo.ts b/x-pack/solutions/observability/plugins/slo/server/services/update_slo.ts index 05f518f0946a9..b526d4ff6fba9 100644 --- a/x-pack/solutions/observability/plugins/slo/server/services/update_slo.ts +++ b/x-pack/solutions/observability/plugins/slo/server/services/update_slo.ts @@ -10,17 +10,17 @@ import { UpdateSLOParams, UpdateSLOResponse, updateSLOResponseSchema } from '@kb import { asyncForEach } from '@kbn/std'; import { isEqual, pick } from 'lodash'; import { - SLO_DESTINATION_INDEX_PATTERN, + SLI_DESTINATION_INDEX_PATTERN, SLO_RESOURCES_VERSION, - SLO_SUMMARY_DESTINATION_INDEX_PATTERN, - SLO_SUMMARY_TEMP_INDEX_NAME, + SUMMARY_DESTINATION_INDEX_PATTERN, + SUMMARY_TEMP_INDEX_NAME, getSLOPipelineId, getSLOSummaryPipelineId, getSLOSummaryTransformId, getSLOTransformId, } from '../../common/constants'; -import { getSLOPipelineTemplate } from '../assets/ingest_templates/slo_pipeline_template'; -import { getSLOSummaryPipelineTemplate } from '../assets/ingest_templates/slo_summary_pipeline_template'; +import { getSLIPipelineTemplate } from '../assets/ingest_templates/sli_pipeline_template'; +import { getSummaryPipelineTemplate } from '../assets/ingest_templates/summary_pipeline_template'; import { SLODefinition } from '../domain/models'; import { validateSLO } from '../domain/services'; import { SecurityException } from '../errors'; @@ -77,7 +77,7 @@ export class UpdateSLO { await retryTransientEsErrors( () => this.scopedClusterClient.asSecondaryAuthUser.ingest.putPipeline( - getSLOSummaryPipelineTemplate(updatedSlo, this.spaceId, this.basePath) + getSummaryPipelineTemplate(updatedSlo, this.spaceId, this.basePath) ), { logger: this.logger } ); @@ -111,7 +111,7 @@ export class UpdateSLO { await retryTransientEsErrors( () => this.scopedClusterClient.asSecondaryAuthUser.ingest.putPipeline( - getSLOPipelineTemplate(updatedSlo) + getSLIPipelineTemplate(updatedSlo) ), { logger: this.logger } ); @@ -131,7 +131,7 @@ export class UpdateSLO { await retryTransientEsErrors( () => this.scopedClusterClient.asSecondaryAuthUser.ingest.putPipeline( - getSLOSummaryPipelineTemplate(updatedSlo, this.spaceId, this.basePath) + getSummaryPipelineTemplate(updatedSlo, this.spaceId, this.basePath) ), { logger: this.logger } ); @@ -153,7 +153,7 @@ export class UpdateSLO { await retryTransientEsErrors( () => this.esClient.index({ - index: SLO_SUMMARY_TEMP_INDEX_NAME, + index: SUMMARY_TEMP_INDEX_NAME, id: `slo-${updatedSlo.id}`, document: createTempSummaryDocument(updatedSlo, this.spaceId, this.basePath), refresh: true, @@ -238,7 +238,7 @@ export class UpdateSLO { private async deleteRollupData(sloId: string, sloRevision: number): Promise { await this.esClient.deleteByQuery({ - index: SLO_DESTINATION_INDEX_PATTERN, + index: SLI_DESTINATION_INDEX_PATTERN, wait_for_completion: false, query: { bool: { @@ -250,7 +250,7 @@ export class UpdateSLO { private async deleteSummaryData(sloId: string, sloRevision: number): Promise { await this.esClient.deleteByQuery({ - index: SLO_SUMMARY_DESTINATION_INDEX_PATTERN, + index: SUMMARY_DESTINATION_INDEX_PATTERN, refresh: true, query: { bool: { diff --git a/x-pack/solutions/observability/plugins/synthetics/common/runtime_types/monitor_management/synthetics_private_locations.ts b/x-pack/solutions/observability/plugins/synthetics/common/runtime_types/monitor_management/synthetics_private_locations.ts index 7e402848a2986..ec8db15e5e7dd 100644 --- a/x-pack/solutions/observability/plugins/synthetics/common/runtime_types/monitor_management/synthetics_private_locations.ts +++ b/x-pack/solutions/observability/plugins/synthetics/common/runtime_types/monitor_management/synthetics_private_locations.ts @@ -22,6 +22,7 @@ export const PrivateLocationCodec = t.intersection([ lon: t.number, }), namespace: t.string, + spaces: t.array(t.string), }), ]); diff --git a/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/getting_started/getting_started_page.test.tsx b/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/getting_started/getting_started_page.test.tsx index 2587fe21fba21..1a35504699cbe 100644 --- a/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/getting_started/getting_started_page.test.tsx +++ b/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/getting_started/getting_started_page.test.tsx @@ -23,7 +23,7 @@ describe('GettingStartedPage', () => { deleteLoading: false, onSubmit: jest.fn(), onDelete: jest.fn(), - formData: undefined, + createLoading: false, }); jest.spyOn(permissionsHooks, 'useCanManagePrivateLocation').mockReturnValue(true); }); @@ -81,9 +81,11 @@ describe('GettingStartedPage', () => { locationsLoaded: true, loading: false, }, + privateLocations: { + isCreatePrivateLocationFlyoutVisible: true, + }, agentPolicies: { data: [], - isAddingNewPrivateLocation: true, }, }, }); @@ -108,7 +110,9 @@ describe('GettingStartedPage', () => { }, agentPolicies: { data: [{}], - isAddingNewPrivateLocation: true, + }, + privateLocations: { + isCreatePrivateLocationFlyoutVisible: true, }, }, }); @@ -145,7 +149,9 @@ describe('GettingStartedPage', () => { }, agentPolicies: { data: [{}], - isAddingNewPrivateLocation: true, + }, + privateLocations: { + isCreatePrivateLocationFlyoutVisible: true, }, }, } diff --git a/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/getting_started/getting_started_page.tsx b/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/getting_started/getting_started_page.tsx index eb61726742400..c102536e04540 100644 --- a/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/getting_started/getting_started_page.tsx +++ b/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/getting_started/getting_started_page.tsx @@ -24,18 +24,14 @@ import { useKibana } from '@kbn/kibana-react-plugin/public'; import { useBreadcrumbs, useEnablement, useLocations } from '../../hooks'; import { usePrivateLocationsAPI } from '../settings/private_locations/hooks/use_locations_api'; import { LoadingState } from '../monitors_page/overview/overview/monitor_detail_flyout'; -import { - getServiceLocations, - selectAddingNewPrivateLocation, - setAddingNewPrivateLocation, - getAgentPoliciesAction, - selectAgentPolicies, - cleanMonitorListState, -} from '../../state'; +import { getServiceLocations, cleanMonitorListState } from '../../state'; import { MONITOR_ADD_ROUTE } from '../../../../../common/constants/ui'; import { SimpleMonitorForm } from './simple_monitor_form'; import { AddLocationFlyout, NewLocation } from '../settings/private_locations/add_location_flyout'; import type { ClientPluginsStart } from '../../../../plugin'; +import { getAgentPoliciesAction, selectAgentPolicies } from '../../state/agent_policies'; +import { selectAddingNewPrivateLocation } from '../../state/settings/selectors'; +import { setIsCreatePrivateLocationFlyoutVisible } from '../../state/private_locations/actions'; export const GettingStartedPage = () => { const dispatch = useDispatch(); @@ -134,11 +130,11 @@ export const GettingStartedOnPrem = () => { const isAddingNewLocation = useSelector(selectAddingNewPrivateLocation); const setIsAddingNewLocation = useCallback( - (val: boolean) => dispatch(setAddingNewPrivateLocation(val)), + (val: boolean) => dispatch(setIsCreatePrivateLocationFlyoutVisible(val)), [dispatch] ); - const { onSubmit, privateLocations, loading } = usePrivateLocationsAPI(); + const { onSubmit, privateLocations } = usePrivateLocationsAPI(); const handleSubmit = (formData: NewLocation) => { onSubmit(formData); @@ -182,7 +178,6 @@ export const GettingStartedOnPrem = () => { setIsOpen={setIsAddingNewLocation} onSubmit={handleSubmit} privateLocations={privateLocations} - isLoading={loading} /> ) : null} diff --git a/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/settings/components/spaces_select.tsx b/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/settings/components/spaces_select.tsx new file mode 100644 index 0000000000000..ce002a189c8ef --- /dev/null +++ b/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/settings/components/spaces_select.tsx @@ -0,0 +1,127 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license 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, { useEffect } from 'react'; +import { i18n } from '@kbn/i18n'; +import { useKibana } from '@kbn/kibana-react-plugin/public'; +import { EuiComboBox, EuiFormRow } from '@elastic/eui'; +import { Controller, useFormContext } from 'react-hook-form'; +import { ALL_SPACES_ID } from '@kbn/security-plugin/public'; + +import { ClientPluginsStart } from '../../../../../plugin'; +import { PrivateLocation } from '../../../../../../common/runtime_types'; + +export const NAMESPACES_NAME = 'spaces'; + +export const SpaceSelector: React.FC = () => { + const { services } = useKibana(); + const [spacesList, setSpacesList] = React.useState>([]); + const data = services.spaces?.ui.useSpaces(); + + const { + control, + formState: { isSubmitted }, + trigger, + } = useFormContext(); + const { isTouched, error } = control.getFieldState(NAMESPACES_NAME); + + const showFieldInvalid = (isSubmitted || isTouched) && !!error; + + useEffect(() => { + if (data) { + data.spacesDataPromise.then((spacesData) => { + setSpacesList([ + allSpacesOption, + ...[...spacesData.spacesMap].map(([spaceId, dataS]) => ({ + id: spaceId, + label: dataS.name, + })), + ]); + }); + } + }, [data]); + + return ( + + ( + { + await trigger(); + }} + options={spacesList} + selectedOptions={(field.value ?? []).map((id) => { + const sp = spacesList.find((space) => space.id === id); + if (!sp) { + return { + id, + label: id, + }; + } + return { id: sp.id, label: sp.label }; + })} + isClearable={true} + onChange={(selected) => { + const selectedIds = selected.map((option) => option.id); + + // if last value is not all spaces, remove all spaces value + if ( + selectedIds.length > 0 && + selectedIds[selectedIds.length - 1] !== allSpacesOption.id + ) { + field.onChange(selectedIds.filter((id) => id !== allSpacesOption.id)); + return; + } + + // if last value is all spaces, remove all other values + if ( + selectedIds.length > 0 && + selectedIds[selectedIds.length - 1] === allSpacesOption.id + ) { + field.onChange([allSpacesOption.id]); + return; + } + + field.onChange(selectedIds); + }} + /> + )} + /> + + ); +}; + +export const ALL_SPACES_LABEL = i18n.translate('xpack.synthetics.spaceList.allSpacesLabel', { + defaultMessage: `* All spaces`, +}); + +const allSpacesOption = { + id: ALL_SPACES_ID, + label: ALL_SPACES_LABEL, +}; + +const SPACES_LABEL = i18n.translate('xpack.synthetics.privateLocation.spacesLabel', { + defaultMessage: 'Spaces ', +}); + +const HELP_TEXT = i18n.translate('xpack.synthetics.privateLocation.spacesHelpText', { + defaultMessage: 'Select the spaces where this location will be available.', +}); diff --git a/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/add_location_flyout.tsx b/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/add_location_flyout.tsx index 36dc8be1cd0e5..25027d5f02e01 100644 --- a/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/add_location_flyout.tsx +++ b/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/add_location_flyout.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import React from 'react'; +import React, { useMemo } from 'react'; import { FormProvider } from 'react-hook-form'; import { EuiButtonEmpty, @@ -19,22 +19,27 @@ import { EuiButton, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; +import { useKibana } from '@kbn/kibana-react-plugin/public'; +import { SpacesContextProps } from '@kbn/spaces-plugin/public'; +import { ALL_SPACES_ID } from '@kbn/security-plugin/public'; +import { useSelector } from 'react-redux'; import { NoPermissionsTooltip } from '../../common/components/permissions'; import { useSyntheticsSettingsContext } from '../../../contexts'; import { useFormWrapped } from '../../../../../hooks/use_form_wrapped'; import { PrivateLocation } from '../../../../../../common/runtime_types'; import { LocationForm } from './location_form'; import { ManageEmptyState } from './manage_empty_state'; +import { ClientPluginsStart } from '../../../../../plugin'; +import { selectPrivateLocationsState } from '../../../state/private_locations/selectors'; export type NewLocation = Omit; +const getEmptyFunctionComponent: React.FC = ({ children }) => <>{children}; export const AddLocationFlyout = ({ onSubmit, setIsOpen, privateLocations, - isLoading, }: { - isLoading: boolean; onSubmit: (val: NewLocation) => void; setIsOpen: (val: boolean) => void; privateLocations: PrivateLocation[]; @@ -50,10 +55,21 @@ export const AddLocationFlyout = ({ lat: 0, lon: 0, }, + spaces: [ALL_SPACES_ID], }, }); - const { canSave } = useSyntheticsSettingsContext(); + const { canSave, canManagePrivateLocations } = useSyntheticsSettingsContext(); + + const { createLoading } = useSelector(selectPrivateLocationsState); + + const { spaces: spacesApi } = useKibana().services; + + const ContextWrapper = useMemo( + () => + spacesApi ? spacesApi.ui.components.getSpacesContextProvider : getEmptyFunctionComponent, + [spacesApi] + ); const { handleSubmit } = form; const closeFlyout = () => { @@ -61,48 +77,50 @@ export const AddLocationFlyout = ({ }; return ( - - - - -

{ADD_PRIVATE_LOCATION}

-
-
- - - - - - - - - - {CANCEL_LABEL} - - - - - + + + + +

{ADD_PRIVATE_LOCATION}

+
+
+ + + + + + + + + - {SAVE_LABEL} -
-
-
-
-
-
-
+ {CANCEL_LABEL} + + + + + + {SAVE_LABEL} + + + + + + + + ); }; diff --git a/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/agent_policy_callout.tsx b/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/agent_policy_callout.tsx new file mode 100644 index 0000000000000..84f87bcee4cee --- /dev/null +++ b/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/agent_policy_callout.tsx @@ -0,0 +1,46 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { EuiCallOut, EuiLink } from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n-react'; +import React from 'react'; +import { AGENT_MISSING_CALLOUT_TITLE } from './location_form'; + +export const AgentPolicyCallout: React.FC = () => { + return ( + +

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

+
+ ); +}; diff --git a/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/browser_monitor_callout.tsx b/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/browser_monitor_callout.tsx new file mode 100644 index 0000000000000..17f120e6db00f --- /dev/null +++ b/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/browser_monitor_callout.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 { EuiCallOut, EuiCode, EuiLink } from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n-react'; +import React from 'react'; +import { AGENT_CALLOUT_TITLE } from './location_form'; + +export const BrowserMonitorCallout: React.FC = () => { + return ( + +

+ { + elastic-agent-complete, + link: ( + + + + ), + }} + /> + } +

+
+ ); +}; diff --git a/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/empty_locations.tsx b/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/empty_locations.tsx index 8a3af2c275584..9d871c7507add 100644 --- a/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/empty_locations.tsx +++ b/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/empty_locations.tsx @@ -13,7 +13,10 @@ import { useDispatch } from 'react-redux'; import { NoPermissionsTooltip } from '../../common/components/permissions'; import { useSyntheticsSettingsContext } from '../../../contexts'; import { PRIVATE_LOCATIOSN_ROUTE } from '../../../../../../common/constants'; -import { setAddingNewPrivateLocation, setManageFlyoutOpen } from '../../../state/private_locations'; +import { + setIsCreatePrivateLocationFlyoutVisible, + setManageFlyoutOpen, +} from '../../../state/private_locations/actions'; export const EmptyLocations = ({ inFlyout = true, @@ -64,7 +67,7 @@ export const EmptyLocations = ({ onClick={() => { setIsAddingNew?.(true); dispatch(setManageFlyoutOpen(true)); - dispatch(setAddingNewPrivateLocation(true)); + dispatch(setIsCreatePrivateLocationFlyoutVisible(true)); }} > {ADD_LOCATION} diff --git a/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/hooks/use_locations_api.test.tsx b/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/hooks/use_locations_api.test.tsx deleted file mode 100644 index 279a0b2a57af6..0000000000000 --- a/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/hooks/use_locations_api.test.tsx +++ /dev/null @@ -1,116 +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 { createElement } from 'react'; -import { act, waitFor, renderHook } from '@testing-library/react'; -import { WrappedHelper } from '../../../../utils/testing'; -import { getServiceLocations } from '../../../../state/service_locations'; -import { setAddingNewPrivateLocation } from '../../../../state/private_locations'; -import { usePrivateLocationsAPI } from './use_locations_api'; -import * as locationAPI from '../../../../state/private_locations/api'; -import * as reduxHooks from 'react-redux'; - -describe('usePrivateLocationsAPI', () => { - const dispatch = jest.fn(); - const addAPI = jest.spyOn(locationAPI, 'addSyntheticsPrivateLocations').mockResolvedValue([]); - const deletedAPI = jest - .spyOn(locationAPI, 'deleteSyntheticsPrivateLocations') - .mockResolvedValue([]); - jest.spyOn(locationAPI, 'getSyntheticsPrivateLocations'); - jest.spyOn(reduxHooks, 'useDispatch').mockReturnValue(dispatch); - - it('returns expected results', () => { - const { result } = renderHook(() => usePrivateLocationsAPI(), { - wrapper: ({ children }) => createElement(WrappedHelper, null, children), - }); - - expect(result.current).toEqual( - expect.objectContaining({ - loading: true, - privateLocations: [], - }) - ); - expect(dispatch).toHaveBeenCalledTimes(1); - }); - jest.spyOn(locationAPI, 'getSyntheticsPrivateLocations').mockResolvedValue([ - { - id: 'Test', - agentPolicyId: 'testPolicy', - } as any, - ]); - it('returns expected results after data', async () => { - const { result } = renderHook(() => usePrivateLocationsAPI(), { - wrapper: ({ children }) => createElement(WrappedHelper, null, children), - }); - - expect(result.current).toEqual( - expect.objectContaining({ - loading: true, - privateLocations: [], - }) - ); - - await waitFor(() => - expect(result.current).toEqual( - expect.objectContaining({ - loading: false, - privateLocations: [], - }) - ) - ); - }); - - it('adds location on submit', async () => { - const { result } = renderHook(() => usePrivateLocationsAPI(), { - wrapper: ({ children }) => createElement(WrappedHelper, null, children), - }); - - await waitFor(() => new Promise((resolve) => resolve(null))); - - act(() => { - result.current.onSubmit({ - agentPolicyId: 'newPolicy', - label: 'new', - geo: { - lat: 0, - lon: 0, - }, - }); - }); - - await waitFor(() => { - expect(addAPI).toHaveBeenCalledWith({ - geo: { - lat: 0, - lon: 0, - }, - label: 'new', - agentPolicyId: 'newPolicy', - }); - expect(dispatch).toBeCalledWith(setAddingNewPrivateLocation(false)); - expect(dispatch).toBeCalledWith(getServiceLocations()); - }); - }); - - it('deletes location on delete', async () => { - const { result } = renderHook(() => usePrivateLocationsAPI(), { - wrapper: ({ children }) => createElement(WrappedHelper, null, children), - }); - - await waitFor(() => new Promise((resolve) => resolve(null))); - - act(() => { - result.current.onDelete('Test'); - }); - - await waitFor(() => { - expect(deletedAPI).toHaveBeenLastCalledWith('Test'); - expect(dispatch).toBeCalledWith(setAddingNewPrivateLocation(false)); - expect(dispatch).toBeCalledWith(getServiceLocations()); - }); - }); -}); diff --git a/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/hooks/use_locations_api.ts b/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/hooks/use_locations_api.ts index 4f3790edddec4..162f8ff59f87d 100644 --- a/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/hooks/use_locations_api.ts +++ b/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/hooks/use_locations_api.ts @@ -5,75 +5,45 @@ * 2.0. */ -import { useFetcher } from '@kbn/observability-shared-plugin/public'; -import { useState, useEffect } from 'react'; +import { useEffect } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import { NewLocation } from '../add_location_flyout'; -import { getServiceLocations } from '../../../../state/service_locations'; import { + createPrivateLocationAction, + deletePrivateLocationAction, getPrivateLocationsAction, - selectPrivateLocations, - selectPrivateLocationsLoading, - setAddingNewPrivateLocation, -} from '../../../../state/private_locations'; -import { - addSyntheticsPrivateLocations, - deleteSyntheticsPrivateLocations, -} from '../../../../state/private_locations/api'; +} from '../../../../state/private_locations/actions'; +import { selectPrivateLocationsState } from '../../../../state/private_locations/selectors'; export const usePrivateLocationsAPI = () => { - const [formData, setFormData] = useState(); - const [deleteId, setDeleteId] = useState(); - const dispatch = useDispatch(); - const setIsAddingNew = (val: boolean) => dispatch(setAddingNewPrivateLocation(val)); - const privateLocations = useSelector(selectPrivateLocations); - const fetchLoading = useSelector(selectPrivateLocationsLoading); + const { loading, createLoading, deleteLoading, data } = useSelector(selectPrivateLocationsState); useEffect(() => { dispatch(getPrivateLocationsAction.get()); }, [dispatch]); - const { loading: saveLoading } = useFetcher(async () => { - if (formData) { - const result = await addSyntheticsPrivateLocations(formData); - setFormData(undefined); - setIsAddingNew(false); - dispatch(getServiceLocations()); + useEffect(() => { + if (data === null) { dispatch(getPrivateLocationsAction.get()); - return result; } - // FIXME: Dario thinks there is a better way to do this but - // he's getting tired and maybe the Synthetics folks can fix it - }, [formData]); + }, [data, dispatch]); - const onSubmit = (data: NewLocation) => { - setFormData(data); + const onSubmit = (newLoc: NewLocation) => { + dispatch(createPrivateLocationAction.get(newLoc)); }; const onDelete = (id: string) => { - setDeleteId(id); + dispatch(deletePrivateLocationAction.get(id)); }; - const { loading: deleteLoading } = useFetcher(async () => { - if (deleteId) { - const result = await deleteSyntheticsPrivateLocations(deleteId); - setDeleteId(undefined); - dispatch(getServiceLocations()); - dispatch(getPrivateLocationsAction.get()); - return result; - } - // FIXME: Dario thinks there is a better way to do this but - // he's getting tired and maybe the Synthetics folks can fix it - }, [deleteId]); - return { - formData, onSubmit, onDelete, - deleteLoading: Boolean(deleteLoading), - loading: Boolean(fetchLoading || saveLoading), - privateLocations, + deleteLoading, + loading, + createLoading, + privateLocations: data ?? [], }; }; diff --git a/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/location_form.tsx b/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/location_form.tsx index a0d98ae78b4ed..ee58ed2165e42 100644 --- a/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/location_form.tsx +++ b/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/location_form.tsx @@ -6,32 +6,22 @@ */ import React, { Ref } from 'react'; -import { FormattedMessage } from '@kbn/i18n-react'; -import { - EuiFieldText, - EuiForm, - EuiFormRow, - EuiSpacer, - EuiCallOut, - EuiCode, - EuiLink, - EuiFieldTextProps, -} from '@elastic/eui'; +import { EuiFieldText, EuiForm, EuiFormRow, EuiSpacer, EuiFieldTextProps } from '@elastic/eui'; import { useSelector } from 'react-redux'; import { i18n } from '@kbn/i18n'; import { useFormContext, useFormState } from 'react-hook-form'; +import { selectAgentPolicies } from '../../../state/agent_policies'; +import { BrowserMonitorCallout } from './browser_monitor_callout'; +import { SpaceSelector } from '../components/spaces_select'; import { TagsField } from '../components/tags_field'; import { PrivateLocation } from '../../../../../../common/runtime_types'; import { AgentPolicyNeeded } from './agent_policy_needed'; -import { PolicyHostsField, AGENT_POLICY_FIELD_NAME } from './policy_hosts'; -import { selectAgentPolicies } from '../../../state/private_locations'; +import { PolicyHostsField } from './policy_hosts'; export const LocationForm = ({ privateLocations }: { privateLocations: PrivateLocation[] }) => { const { data } = useSelector(selectAgentPolicies); - const { control, register, getValues } = useFormContext(); + const { control, register } = useFormContext(); const { errors } = useFormState(); - const selectedPolicyId = getValues(AGENT_POLICY_FIELD_NAME); - const selectedPolicy = data?.find((item) => item.id === selectedPolicyId); const tagsList = privateLocations.reduce((acc, item) => { const tags = item.tags || []; @@ -70,66 +60,9 @@ export const LocationForm = ({ privateLocations }: { privateLocations: PrivateLo - -

- { - elastic-agent-complete, - link: ( - - - - ), - }} - /> - } -

-
- + - {selectedPolicy?.agents === 0 && ( - -

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

-
- )} + ); diff --git a/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/locations_table.tsx b/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/locations_table.tsx index ac6b471c9046f..af51265feee21 100644 --- a/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/locations_table.tsx +++ b/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/locations_table.tsx @@ -18,12 +18,12 @@ import { import { i18n } from '@kbn/i18n'; import { useDispatch } from 'react-redux'; import { Criteria } from '@elastic/eui/src/components/basic_table/basic_table'; +import { useKibana } from '@kbn/kibana-react-plugin/public'; import { CopyName } from './copy_name'; import { ViewLocationMonitors } from './view_location_monitors'; import { TableTitle } from '../../common/components/table_title'; import { TAGS_LABEL } from '../components/tags_field'; import { useSyntheticsSettingsContext } from '../../../contexts'; -import { setAddingNewPrivateLocation } from '../../../state/private_locations'; import { PrivateLocationDocsLink, START_ADDING_LOCATIONS_DESCRIPTION } from './empty_locations'; import { PrivateLocation } from '../../../../../../common/runtime_types'; import { NoPermissionsTooltip } from '../../common/components/permissions'; @@ -31,6 +31,8 @@ import { DeleteLocation } from './delete_location'; import { useLocationMonitors } from './hooks/use_location_monitors'; import { PolicyName } from './policy_name'; import { LOCATION_NAME_LABEL } from './location_form'; +import { setIsCreatePrivateLocationFlyoutVisible } from '../../../state/private_locations/actions'; +import { ClientPluginsStart } from '../../../../../plugin'; interface ListItem extends PrivateLocation { monitors: number; @@ -41,7 +43,7 @@ export const PrivateLocationsTable = ({ onDelete, privateLocations, }: { - deleteLoading: boolean; + deleteLoading?: boolean; onDelete: (id: string) => void; privateLocations: PrivateLocation[]; }) => { @@ -54,6 +56,10 @@ export const PrivateLocationsTable = ({ const { canSave, canManagePrivateLocations } = useSyntheticsSettingsContext(); + const { services } = useKibana(); + + const LazySpaceList = services.spaces?.ui.components.getSpaceList ?? (() => null); + const tagsList = privateLocations.reduce((acc, item) => { const tags = item.tags || []; return new Set([...acc, ...tags]); @@ -97,6 +103,14 @@ export const PrivateLocationsTable = ({ ); }, }, + { + name: 'Spaces', + field: 'spaces', + sortable: true, + render: (spaces: string[]) => { + return ; + }, + }, { name: ACTIONS_LABEL, actions: [ @@ -124,7 +138,7 @@ export const PrivateLocationsTable = ({ monitors: locationMonitors?.find((l) => l.id === location.id)?.count ?? 0, })); - const setIsAddingNew = (val: boolean) => dispatch(setAddingNewPrivateLocation(val)); + const setIsAddingNew = (val: boolean) => dispatch(setIsCreatePrivateLocationFlyoutVisible(val)); const renderToolRight = () => { return [ diff --git a/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/manage_empty_state.tsx b/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/manage_empty_state.tsx index ff0ffea15bd36..dd0b5d8b99934 100644 --- a/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/manage_empty_state.tsx +++ b/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/manage_empty_state.tsx @@ -10,7 +10,7 @@ import { useSelector } from 'react-redux'; import { PrivateLocation } from '../../../../../../common/runtime_types'; import { AgentPolicyNeeded } from './agent_policy_needed'; import { EmptyLocations } from './empty_locations'; -import { selectAgentPolicies } from '../../../state/private_locations'; +import { selectAgentPolicies } from '../../../state/agent_policies'; export const ManageEmptyState: FC< PropsWithChildren<{ diff --git a/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/manage_private_locations.test.tsx b/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/manage_private_locations.test.tsx index 5cabd6cf13742..a6d6ccfb1af7c 100644 --- a/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/manage_private_locations.test.tsx +++ b/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/manage_private_locations.test.tsx @@ -12,7 +12,6 @@ import * as locationHooks from './hooks/use_locations_api'; import * as settingsHooks from '../../../contexts/synthetics_settings_context'; import type { SyntheticsSettingsContextValues } from '../../../contexts'; import { ManagePrivateLocations } from './manage_private_locations'; -import { PrivateLocation } from '../../../../../../common/runtime_types'; import { fireEvent } from '@testing-library/react'; jest.mock('../../../hooks'); @@ -28,12 +27,12 @@ describe('', () => { canCreateAgentPolicies: false, }); jest.spyOn(locationHooks, 'usePrivateLocationsAPI').mockReturnValue({ - formData: {} as PrivateLocation, loading: false, onSubmit: jest.fn(), privateLocations: [], onDelete: jest.fn(), deleteLoading: false, + createLoading: false, }); jest.spyOn(permissionsHooks, 'useEnablement').mockReturnValue({ isServiceAllowed: true, @@ -59,8 +58,9 @@ describe('', () => { data: [], loading: false, error: null, - isManageFlyoutOpen: false, - isAddingNewPrivateLocation: false, + }, + privateLocations: { + isCreatePrivateLocationFlyoutVisible: false, }, }, }); @@ -93,8 +93,9 @@ describe('', () => { data: [{}], loading: false, error: null, - isManageFlyoutOpen: false, - isAddingNewPrivateLocation: false, + }, + privateLocations: { + isCreatePrivateLocationFlyoutVisible: false, }, }, }); @@ -123,7 +124,6 @@ describe('', () => { } as SyntheticsSettingsContextValues); jest.spyOn(locationHooks, 'usePrivateLocationsAPI').mockReturnValue({ - formData: {} as PrivateLocation, loading: false, onSubmit: jest.fn(), privateLocations: [ @@ -136,6 +136,7 @@ describe('', () => { ], onDelete: jest.fn(), deleteLoading: false, + createLoading: false, }); const { getByText, getByRole, findByText } = render(, { state: { @@ -143,8 +144,9 @@ describe('', () => { data: [{}], loading: false, error: null, - isManageFlyoutOpen: false, - isAddingNewPrivateLocation: false, + }, + privateLocations: { + isCreatePrivateLocationFlyoutVisible: false, }, }, }); diff --git a/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/manage_private_locations.tsx b/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/manage_private_locations.tsx index 1f61e88bb762a..4478c973f7eac 100644 --- a/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/manage_private_locations.tsx +++ b/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/manage_private_locations.tsx @@ -4,39 +4,48 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import React, { useEffect, useCallback } from 'react'; +import React, { useEffect, useCallback, useMemo } from 'react'; import { useDispatch, useSelector } from 'react-redux'; +import { useKibana } from '@kbn/kibana-react-plugin/public'; +import { SpacesContextProps } from '@kbn/spaces-plugin/public'; import { LoadingState } from '../../monitors_page/overview/overview/monitor_detail_flyout'; import { PrivateLocationsTable } from './locations_table'; import { ManageEmptyState } from './manage_empty_state'; import { AddLocationFlyout, NewLocation } from './add_location_flyout'; import { usePrivateLocationsAPI } from './hooks/use_locations_api'; -import { - getAgentPoliciesAction, - selectAddingNewPrivateLocation, - setAddingNewPrivateLocation, -} from '../../../state/private_locations'; +import { selectAddingNewPrivateLocation } from '../../../state/private_locations/selectors'; import { getServiceLocations } from '../../../state'; +import { getAgentPoliciesAction } from '../../../state/agent_policies'; +import { setIsCreatePrivateLocationFlyoutVisible } from '../../../state/private_locations/actions'; +import { ClientPluginsStart } from '../../../../../plugin'; + +const getEmptyFunctionComponent: React.FC = ({ children }) => <>{children}; export const ManagePrivateLocations = () => { const dispatch = useDispatch(); + const { services } = useKibana(); + + const spacesApi = services.spaces; + + const SpacesContextProvider = useMemo( + () => + spacesApi ? spacesApi.ui.components.getSpacesContextProvider : getEmptyFunctionComponent, + [spacesApi] + ); const isAddingNew = useSelector(selectAddingNewPrivateLocation); const setIsAddingNew = useCallback( - (val: boolean) => dispatch(setAddingNewPrivateLocation(val)), + (val: boolean) => dispatch(setIsCreatePrivateLocationFlyoutVisible(val)), [dispatch] ); const { onSubmit, loading, privateLocations, onDelete, deleteLoading } = usePrivateLocationsAPI(); - // make sure flyout is closed when first visiting the page - useEffect(() => { - setIsAddingNew(false); - }, [setIsAddingNew]); - useEffect(() => { dispatch(getAgentPoliciesAction.get()); dispatch(getServiceLocations()); + // make sure flyout is closed when first visiting the page + dispatch(setIsCreatePrivateLocationFlyoutVisible(false)); }, [dispatch]); const handleSubmit = (formData: NewLocation) => { @@ -44,7 +53,7 @@ export const ManagePrivateLocations = () => { }; return ( - <> + {loading ? ( ) : ( @@ -62,9 +71,8 @@ export const ManagePrivateLocations = () => { setIsOpen={setIsAddingNew} onSubmit={handleSubmit} privateLocations={privateLocations} - isLoading={loading} /> ) : null} - + ); }; diff --git a/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/policy_hosts.tsx b/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/policy_hosts.tsx index 4b0f74120b90e..f5743479015b1 100644 --- a/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/policy_hosts.tsx +++ b/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/policy_hosts.tsx @@ -17,23 +17,33 @@ import { EuiSuperSelect, EuiText, EuiToolTip, + EuiSpacer, + EuiButtonEmpty, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; +import { useSyntheticsSettingsContext } from '../../../contexts'; +import { AgentPolicyCallout } from './agent_policy_callout'; import { PrivateLocation } from '../../../../../../common/runtime_types'; -import { selectAgentPolicies } from '../../../state/private_locations'; +import { selectAgentPolicies } from '../../../state/agent_policies'; export const AGENT_POLICY_FIELD_NAME = 'agentPolicyId'; export const PolicyHostsField = ({ privateLocations }: { privateLocations: PrivateLocation[] }) => { const { data } = useSelector(selectAgentPolicies); + const { basePath } = useSyntheticsSettingsContext(); + const { control, formState: { isSubmitted }, trigger, + getValues, } = useFormContext(); const { isTouched, error } = control.getFieldState(AGENT_POLICY_FIELD_NAME); const showFieldInvalid = (isSubmitted || isTouched) && !!error; + const selectedPolicyId = getValues(AGENT_POLICY_FIELD_NAME); + + const selectedPolicy = data?.find((item) => item.id === selectedPolicyId); const policyHostsOptions = data?.map((item) => { const hasLocation = privateLocations.find((location) => location.agentPolicyId === item.id); @@ -89,36 +99,47 @@ export const PolicyHostsField = ({ privateLocations }: { privateLocations: Priva }); return ( - - ( - { - await trigger(); - }} - /> - )} - /> - + <> + + {i18n.translate('xpack.synthetics.policyHostsField.createButtonEmptyLabel', { + defaultMessage: 'Create policy', + })} + + } + helpText={showFieldInvalid ? SELECT_POLICY_HOSTS_HELP_TEXT : undefined} + isInvalid={showFieldInvalid} + error={showFieldInvalid ? SELECT_POLICY_HOSTS : undefined} + > + ( + { + await trigger(); + }} + /> + )} + /> + + + {selectedPolicy?.agents === 0 && } + ); }; diff --git a/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/policy_name.tsx b/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/policy_name.tsx index ea4ac5b75688b..37017cbebf632 100644 --- a/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/policy_name.tsx +++ b/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/components/settings/private_locations/policy_name.tsx @@ -11,7 +11,7 @@ import { useSelector } from 'react-redux'; import { i18n } from '@kbn/i18n'; import { useSyntheticsSettingsContext } from '../../../contexts'; import { useFleetPermissions } from '../../../hooks'; -import { selectAgentPolicies } from '../../../state/private_locations'; +import { selectAgentPolicies } from '../../../state/agent_policies'; export const PolicyName = ({ agentPolicyId }: { agentPolicyId: string }) => { const { canReadAgentPolicies } = useFleetPermissions(); diff --git a/x-pack/solutions/security/plugins/kubernetes_security/public/components/tree_view_container/tree_nav/types.ts b/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/state/agent_policies/actions.ts similarity index 52% rename from x-pack/solutions/security/plugins/kubernetes_security/public/components/tree_view_container/tree_nav/types.ts rename to x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/state/agent_policies/actions.ts index 0643f84e26119..07f3cd7f8d0b2 100644 --- a/x-pack/solutions/security/plugins/kubernetes_security/public/components/tree_view_container/tree_nav/types.ts +++ b/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/state/agent_policies/actions.ts @@ -5,10 +5,9 @@ * 2.0. */ -export type TreeViewKind = 'infrastructure' | 'logical'; +import { AgentPolicyInfo } from '../../../../../common/types'; +import { createAsyncAction } from '../utils/actions'; -export interface TreeViewOptionsGroup { - id: string; - label: string; - value: TreeViewKind; -} +export const getAgentPoliciesAction = createAsyncAction( + '[AGENT POLICIES] GET' +); diff --git a/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/state/agent_policies/api.ts b/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/state/agent_policies/api.ts new file mode 100644 index 0000000000000..e83482d544f54 --- /dev/null +++ b/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/state/agent_policies/api.ts @@ -0,0 +1,38 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { NewLocation } from '../../components/settings/private_locations/add_location_flyout'; +import { AgentPolicyInfo } from '../../../../../common/types'; +import { INITIAL_REST_VERSION, SYNTHETICS_API_URLS } from '../../../../../common/constants'; +import { SyntheticsPrivateLocations } from '../../../../../common/runtime_types'; +import { apiService } from '../../../../utils/api_service/api_service'; + +export const fetchAgentPolicies = async (): Promise => { + return await apiService.get(SYNTHETICS_API_URLS.AGENT_POLICIES); +}; + +export const addSyntheticsPrivateLocations = async ( + newLocation: NewLocation +): Promise => { + return await apiService.post(SYNTHETICS_API_URLS.PRIVATE_LOCATIONS, newLocation, undefined, { + version: INITIAL_REST_VERSION, + }); +}; + +export const getSyntheticsPrivateLocations = async (): Promise => { + return await apiService.get(SYNTHETICS_API_URLS.PRIVATE_LOCATIONS, { + version: INITIAL_REST_VERSION, + }); +}; + +export const deleteSyntheticsPrivateLocations = async ( + locationId: string +): Promise => { + return await apiService.delete(SYNTHETICS_API_URLS.PRIVATE_LOCATIONS + `/${locationId}`, { + version: INITIAL_REST_VERSION, + }); +}; diff --git a/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/state/agent_policies/effects.ts b/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/state/agent_policies/effects.ts new file mode 100644 index 0000000000000..c8889585676b4 --- /dev/null +++ b/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/state/agent_policies/effects.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 { takeLeading } from 'redux-saga/effects'; +import { fetchEffectFactory } from '../utils/fetch_effect'; +import { fetchAgentPolicies } from './api'; +import { getAgentPoliciesAction } from './actions'; + +export function* fetchAgentPoliciesEffect() { + yield takeLeading( + getAgentPoliciesAction.get, + fetchEffectFactory( + fetchAgentPolicies, + getAgentPoliciesAction.success, + getAgentPoliciesAction.fail + ) + ); +} diff --git a/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/state/agent_policies/index.ts b/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/state/agent_policies/index.ts new file mode 100644 index 0000000000000..0042b9f1a9fb2 --- /dev/null +++ b/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/state/agent_policies/index.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 { createReducer } from '@reduxjs/toolkit'; +import { AgentPolicyInfo } from '../../../../../common/types'; +import { IHttpSerializedFetchError } from '..'; +import { getAgentPoliciesAction } from './actions'; + +export interface AgentPoliciesState { + data: AgentPolicyInfo[] | null; + loading: boolean; + error: IHttpSerializedFetchError | null; +} + +const initialState: AgentPoliciesState = { + data: null, + loading: false, + error: null, +}; + +export const agentPoliciesReducer = createReducer(initialState, (builder) => { + builder + .addCase(getAgentPoliciesAction.get, (state) => { + state.loading = true; + }) + .addCase(getAgentPoliciesAction.success, (state, action) => { + state.data = action.payload; + state.loading = false; + }) + .addCase(getAgentPoliciesAction.fail, (state, action) => { + state.error = action.payload; + state.loading = false; + }); +}); + +export * from './actions'; +export * from './effects'; +export * from './selectors'; diff --git a/x-pack/solutions/security/plugins/security_solution/public/kubernetes/index.ts b/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/state/agent_policies/selectors.ts similarity index 54% rename from x-pack/solutions/security/plugins/security_solution/public/kubernetes/index.ts rename to x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/state/agent_policies/selectors.ts index 4956a01d06974..a5d93d8423107 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/kubernetes/index.ts +++ b/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/state/agent_policies/selectors.ts @@ -5,15 +5,8 @@ * 2.0. */ -import type { SecuritySubPlugin } from '../app/types'; -import { routes } from './routes'; +import { createSelector } from 'reselect'; +import { AppState } from '..'; -export class Kubernetes { - public setup() {} - - public start(): SecuritySubPlugin { - return { - routes, - }; - } -} +const getState = (appState: AppState) => appState.agentPolicies; +export const selectAgentPolicies = createSelector(getState, (state) => state); diff --git a/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/state/private_locations/actions.ts b/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/state/private_locations/actions.ts index 42a464797807d..29cf7510111f8 100644 --- a/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/state/private_locations/actions.ts +++ b/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/state/private_locations/actions.ts @@ -6,18 +6,24 @@ */ import { createAction } from '@reduxjs/toolkit'; -import { SyntheticsPrivateLocations } from '../../../../../common/runtime_types'; -import { AgentPolicyInfo } from '../../../../../common/types'; +import { NewLocation } from '../../components/settings/private_locations/add_location_flyout'; +import { PrivateLocation, SyntheticsPrivateLocations } from '../../../../../common/runtime_types'; import { createAsyncAction } from '../utils/actions'; -export const getAgentPoliciesAction = createAsyncAction( - '[AGENT POLICIES] GET' -); - export const getPrivateLocationsAction = createAsyncAction( '[PRIVATE LOCATIONS] GET' ); +export const createPrivateLocationAction = createAsyncAction( + 'CREATE PRIVATE LOCATION' +); + +export const deletePrivateLocationAction = createAsyncAction( + 'DELETE PRIVATE LOCATION' +); + export const setManageFlyoutOpen = createAction('SET MANAGE FLYOUT OPEN'); -export const setAddingNewPrivateLocation = createAction('SET MANAGE FLYOUT ADDING NEW'); +export const setIsCreatePrivateLocationFlyoutVisible = createAction( + 'SET IS CREATE PRIVATE LOCATION FLYOUT VISIBLE' +); diff --git a/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/state/private_locations/api.ts b/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/state/private_locations/api.ts index e83482d544f54..afa722302c89c 100644 --- a/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/state/private_locations/api.ts +++ b/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/state/private_locations/api.ts @@ -8,16 +8,16 @@ import { NewLocation } from '../../components/settings/private_locations/add_location_flyout'; import { AgentPolicyInfo } from '../../../../../common/types'; import { INITIAL_REST_VERSION, SYNTHETICS_API_URLS } from '../../../../../common/constants'; -import { SyntheticsPrivateLocations } from '../../../../../common/runtime_types'; +import { PrivateLocation, SyntheticsPrivateLocations } from '../../../../../common/runtime_types'; import { apiService } from '../../../../utils/api_service/api_service'; export const fetchAgentPolicies = async (): Promise => { return await apiService.get(SYNTHETICS_API_URLS.AGENT_POLICIES); }; -export const addSyntheticsPrivateLocations = async ( +export const createSyntheticsPrivateLocation = async ( newLocation: NewLocation -): Promise => { +): Promise => { return await apiService.post(SYNTHETICS_API_URLS.PRIVATE_LOCATIONS, newLocation, undefined, { version: INITIAL_REST_VERSION, }); @@ -29,7 +29,7 @@ export const getSyntheticsPrivateLocations = async (): Promise => { return await apiService.delete(SYNTHETICS_API_URLS.PRIVATE_LOCATIONS + `/${locationId}`, { diff --git a/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/state/private_locations/effects.ts b/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/state/private_locations/effects.ts index 7be5abbdc4078..0642e1d697cae 100644 --- a/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/state/private_locations/effects.ts +++ b/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/state/private_locations/effects.ts @@ -6,28 +6,60 @@ */ import { takeLeading } from 'redux-saga/effects'; +import { i18n } from '@kbn/i18n'; import { fetchEffectFactory } from '../utils/fetch_effect'; -import { fetchAgentPolicies, getSyntheticsPrivateLocations } from './api'; -import { getAgentPoliciesAction, getPrivateLocationsAction } from './actions'; +import { + createSyntheticsPrivateLocation, + deleteSyntheticsPrivateLocation, + getSyntheticsPrivateLocations, +} from './api'; +import { + createPrivateLocationAction, + deletePrivateLocationAction, + getPrivateLocationsAction, +} from './actions'; -export function* fetchAgentPoliciesEffect() { +export function* fetchPrivateLocationsEffect() { yield takeLeading( - getAgentPoliciesAction.get, + getPrivateLocationsAction.get, fetchEffectFactory( - fetchAgentPolicies, - getAgentPoliciesAction.success, - getAgentPoliciesAction.fail + getSyntheticsPrivateLocations, + getPrivateLocationsAction.success, + getPrivateLocationsAction.fail ) ); } -export function* fetchPrivateLocationsEffect() { +export function* createPrivateLocationEffect() { yield takeLeading( - getPrivateLocationsAction.get, + createPrivateLocationAction.get, fetchEffectFactory( - getSyntheticsPrivateLocations, - getPrivateLocationsAction.success, - getPrivateLocationsAction.fail + createSyntheticsPrivateLocation, + createPrivateLocationAction.success, + createPrivateLocationAction.fail, + i18n.translate('xpack.synthetics.createPrivateLocationSuccess', { + defaultMessage: 'Successfully created private location.', + }), + i18n.translate('xpack.synthetics.createPrivateLocationFailure', { + defaultMessage: 'Failed to create private location.', + }) + ) + ); +} + +export function* deletePrivateLocationEffect() { + yield takeLeading( + deletePrivateLocationAction.get, + fetchEffectFactory( + deleteSyntheticsPrivateLocation, + deletePrivateLocationAction.success, + deletePrivateLocationAction.fail ) ); } + +export const privateLocationsEffects = [ + fetchPrivateLocationsEffect, + createPrivateLocationEffect, + deletePrivateLocationEffect, +]; diff --git a/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/state/private_locations/index.ts b/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/state/private_locations/index.ts index 96634c74232be..45c9ba4ece577 100644 --- a/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/state/private_locations/index.ts +++ b/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/state/private_locations/index.ts @@ -6,62 +6,69 @@ */ import { createReducer } from '@reduxjs/toolkit'; -import { SyntheticsPrivateLocations } from '../../../../../common/runtime_types'; -import { AgentPolicyInfo } from '../../../../../common/types'; -import { IHttpSerializedFetchError } from '..'; -import { - getAgentPoliciesAction, - setAddingNewPrivateLocation, - getPrivateLocationsAction, -} from './actions'; +import { PrivateLocation, SyntheticsPrivateLocations } from '../../../../../common/runtime_types'; +import { createPrivateLocationAction, deletePrivateLocationAction } from './actions'; +import { setIsCreatePrivateLocationFlyoutVisible, getPrivateLocationsAction } from './actions'; +import { IHttpSerializedFetchError } from '../utils/http_error'; -export interface AgentPoliciesState { - data: AgentPolicyInfo[] | null; - privateLocations?: SyntheticsPrivateLocations | null; +export interface PrivateLocationsState { + data?: SyntheticsPrivateLocations | null; loading: boolean; - fetchLoading?: boolean; + createLoading?: boolean; + deleteLoading?: boolean; error: IHttpSerializedFetchError | null; isManageFlyoutOpen?: boolean; - isAddingNewPrivateLocation?: boolean; + isCreatePrivateLocationFlyoutVisible?: boolean; + newLocation?: PrivateLocation; } -const initialState: AgentPoliciesState = { +const initialState: PrivateLocationsState = { data: null, loading: false, error: null, isManageFlyoutOpen: false, - isAddingNewPrivateLocation: false, + isCreatePrivateLocationFlyoutVisible: false, + createLoading: false, }; -export const agentPoliciesReducer = createReducer(initialState, (builder) => { +export const privateLocationsStateReducer = createReducer(initialState, (builder) => { builder - .addCase(getAgentPoliciesAction.get, (state) => { + .addCase(getPrivateLocationsAction.get, (state) => { state.loading = true; }) - .addCase(getAgentPoliciesAction.success, (state, action) => { + .addCase(getPrivateLocationsAction.success, (state, action) => { state.data = action.payload; state.loading = false; }) - .addCase(getAgentPoliciesAction.fail, (state, action) => { + .addCase(getPrivateLocationsAction.fail, (state, action) => { state.error = action.payload; state.loading = false; }) - .addCase(getPrivateLocationsAction.get, (state) => { - state.fetchLoading = true; + .addCase(createPrivateLocationAction.get, (state) => { + state.createLoading = true; }) - .addCase(getPrivateLocationsAction.success, (state, action) => { - state.privateLocations = action.payload; - state.fetchLoading = false; + .addCase(createPrivateLocationAction.success, (state, action) => { + state.newLocation = action.payload; + state.createLoading = false; + state.data = null; + state.isCreatePrivateLocationFlyoutVisible = false; }) - .addCase(getPrivateLocationsAction.fail, (state, action) => { + .addCase(createPrivateLocationAction.fail, (state, action) => { state.error = action.payload; - state.fetchLoading = false; + state.createLoading = false; }) - .addCase(setAddingNewPrivateLocation, (state, action) => { - state.isAddingNewPrivateLocation = action.payload; + .addCase(deletePrivateLocationAction.get, (state) => { + state.deleteLoading = true; + }) + .addCase(deletePrivateLocationAction.success, (state, action) => { + state.deleteLoading = false; + state.data = null; + }) + .addCase(deletePrivateLocationAction.fail, (state, action) => { + state.error = action.payload; + state.deleteLoading = false; + }) + .addCase(setIsCreatePrivateLocationFlyoutVisible, (state, action) => { + state.isCreatePrivateLocationFlyoutVisible = action.payload; }); }); - -export * from './actions'; -export * from './effects'; -export * from './selectors'; diff --git a/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/state/private_locations/selectors.ts b/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/state/private_locations/selectors.ts index 0f504d189c0c6..a9ce772175792 100644 --- a/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/state/private_locations/selectors.ts +++ b/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/state/private_locations/selectors.ts @@ -8,14 +8,21 @@ import { createSelector } from 'reselect'; import { AppState } from '..'; -const getState = (appState: AppState) => appState.agentPolicies; +const getState = (appState: AppState) => appState.privateLocations; export const selectAgentPolicies = createSelector(getState, (state) => state); export const selectAddingNewPrivateLocation = (state: AppState) => - state.agentPolicies.isAddingNewPrivateLocation ?? false; + state.privateLocations.isCreatePrivateLocationFlyoutVisible ?? false; export const selectPrivateLocationsLoading = (state: AppState) => - state.agentPolicies.fetchLoading ?? false; + state.privateLocations.loading ?? false; -export const selectPrivateLocations = (state: AppState) => - state.agentPolicies.privateLocations ?? []; +export const selectPrivateLocationCreating = (state: AppState) => + state.privateLocations.createLoading ?? false; + +export const selectPrivateLocationDeleting = (state: AppState) => + state.privateLocations.deleteLoading ?? false; + +export const selectPrivateLocationsState = (state: AppState) => state.privateLocations; + +export const selectPrivateLocations = (state: AppState) => state.privateLocations.data ?? []; diff --git a/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/state/root_effect.ts b/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/state/root_effect.ts index e38a1b5ad918f..9295e318104a6 100644 --- a/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/state/root_effect.ts +++ b/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/state/root_effect.ts @@ -28,7 +28,7 @@ import { setDynamicSettingsEffect, } from './settings/effects'; import { syncGlobalParamsEffect } from './settings'; -import { fetchAgentPoliciesEffect, fetchPrivateLocationsEffect } from './private_locations'; +import { privateLocationsEffects } from './private_locations/effects'; import { fetchNetworkEventsEffect } from './network_events/effects'; import { fetchSyntheticsMonitorEffect } from './monitor_details'; import { fetchSyntheticsEnablementEffect } from './synthetics_enablement'; @@ -44,6 +44,7 @@ import { browserJourneyEffects, fetchJourneyStepsEffect } from './browser_journe import { fetchOverviewStatusEffect } from './overview_status'; import { fetchMonitorStatusHeatmap, quietFetchMonitorStatusHeatmap } from './status_heatmap'; import { fetchOverviewTrendStats, refreshOverviewTrendStats } from './overview/effects'; +import { fetchAgentPoliciesEffect } from './agent_policies'; export const rootEffect = function* root(): Generator { yield all([ @@ -57,7 +58,6 @@ export const rootEffect = function* root(): Generator { fork(fetchOverviewStatusEffect), fork(fetchNetworkEventsEffect), fork(fetchAgentPoliciesEffect), - fork(fetchPrivateLocationsEffect), fork(fetchDynamicSettingsEffect), fork(fetchLocationMonitorsEffect), fork(setDynamicSettingsEffect), @@ -80,5 +80,6 @@ export const rootEffect = function* root(): Generator { fork(quietFetchMonitorStatusHeatmap), fork(fetchOverviewTrendStats), fork(refreshOverviewTrendStats), + ...privateLocationsEffects.map((effect) => fork(effect)), ]); }; diff --git a/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/state/root_reducer.ts b/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/state/root_reducer.ts index f8ace41e93191..70dcfb1aed9ea 100644 --- a/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/state/root_reducer.ts +++ b/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/state/root_reducer.ts @@ -21,7 +21,7 @@ import { SettingsState, } from './settings'; import { elasticsearchReducer, QueriesState } from './elasticsearch'; -import { agentPoliciesReducer, AgentPoliciesState } from './private_locations'; +import { PrivateLocationsState, privateLocationsStateReducer } from './private_locations'; import { networkEventsReducer, NetworkEventsState } from './network_events'; import { monitorDetailsReducer, MonitorDetailsState } from './monitor_details'; import { uiReducer, UiState } from './ui'; @@ -31,47 +31,50 @@ import { serviceLocationsReducer, ServiceLocationsState } from './service_locati import { monitorOverviewReducer, MonitorOverviewState } from './overview'; import { BrowserJourneyState } from './browser_journey/models'; import { monitorStatusHeatmapReducer, MonitorStatusHeatmap } from './status_heatmap'; +import { agentPoliciesReducer, AgentPoliciesState } from './agent_policies'; export interface SyntheticsAppState { - ui: UiState; - settings: SettingsState; - elasticsearch: QueriesState; - monitorList: MonitorListState; - overview: MonitorOverviewState; - certificates: CertificatesState; - globalParams: GlobalParamsState; - networkEvents: NetworkEventsState; agentPolicies: AgentPoliciesState; - manualTestRuns: ManualTestRunsState; - monitorDetails: MonitorDetailsState; browserJourney: BrowserJourneyState; + certificates: CertificatesState; certsList: CertsListState; defaultAlerting: DefaultAlertingState; dynamicSettings: DynamicSettingsState; - serviceLocations: ServiceLocationsState; + elasticsearch: QueriesState; + globalParams: GlobalParamsState; + manualTestRuns: ManualTestRunsState; + monitorDetails: MonitorDetailsState; + monitorList: MonitorListState; + monitorStatusHeatmap: MonitorStatusHeatmap; + networkEvents: NetworkEventsState; + overview: MonitorOverviewState; overviewStatus: OverviewStatusStateReducer; + privateLocations: PrivateLocationsState; + serviceLocations: ServiceLocationsState; + settings: SettingsState; syntheticsEnablement: SyntheticsEnablementState; - monitorStatusHeatmap: MonitorStatusHeatmap; + ui: UiState; } export const rootReducer = combineReducers({ - ui: uiReducer, - settings: settingsReducer, - monitorList: monitorListReducer, - overview: monitorOverviewReducer, - globalParams: globalParamsReducer, - networkEvents: networkEventsReducer, - elasticsearch: elasticsearchReducer, agentPolicies: agentPoliciesReducer, - monitorDetails: monitorDetailsReducer, browserJourney: browserJourneyReducer, - manualTestRuns: manualTestRunsReducer, - overviewStatus: overviewStatusReducer, + certificates: certificatesReducer, + certsList: certsListReducer, defaultAlerting: defaultAlertingReducer, dynamicSettings: dynamicSettingsReducer, + elasticsearch: elasticsearchReducer, + globalParams: globalParamsReducer, + manualTestRuns: manualTestRunsReducer, + monitorDetails: monitorDetailsReducer, + monitorList: monitorListReducer, + monitorStatusHeatmap: monitorStatusHeatmapReducer, + networkEvents: networkEventsReducer, + overview: monitorOverviewReducer, + overviewStatus: overviewStatusReducer, + privateLocations: privateLocationsStateReducer, serviceLocations: serviceLocationsReducer, + settings: settingsReducer, syntheticsEnablement: syntheticsEnablementReducer, - certificates: certificatesReducer, - certsList: certsListReducer, - monitorStatusHeatmap: monitorStatusHeatmapReducer, + ui: uiReducer, }); diff --git a/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/state/settings/selectors.ts b/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/state/settings/selectors.ts index e73fe77423d44..195c1380ebc9c 100644 --- a/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/state/settings/selectors.ts +++ b/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/state/settings/selectors.ts @@ -14,7 +14,7 @@ const getState = (appState: AppState) => appState.agentPolicies; export const selectAgentPolicies = createSelector(getState, (state) => state); export const selectAddingNewPrivateLocation = (state: AppState) => - state.agentPolicies.isAddingNewPrivateLocation ?? false; + state.privateLocations.isCreatePrivateLocationFlyoutVisible ?? false; export const selectLocationMonitors = (state: AppState) => ({ locationMonitors: state.dynamicSettings.locationMonitors, diff --git a/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/utils/testing/__mocks__/synthetics_store.mock.ts b/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/utils/testing/__mocks__/synthetics_store.mock.ts index fe2ad5f7512cc..dc71f90ea9e18 100644 --- a/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/utils/testing/__mocks__/synthetics_store.mock.ts +++ b/x-pack/solutions/observability/plugins/synthetics/public/apps/synthetics/utils/testing/__mocks__/synthetics_store.mock.ts @@ -114,6 +114,12 @@ export const mockState: SyntheticsAppState = { error: null, data: null, }, + privateLocations: { + isCreatePrivateLocationFlyoutVisible: false, + loading: false, + error: null, + data: [], + }, settings: { loading: false, error: null, diff --git a/x-pack/solutions/observability/plugins/synthetics/server/repositories/private_location_repository.ts b/x-pack/solutions/observability/plugins/synthetics/server/repositories/private_location_repository.ts new file mode 100644 index 0000000000000..f42947b8252cf --- /dev/null +++ b/x-pack/solutions/observability/plugins/synthetics/server/repositories/private_location_repository.ts @@ -0,0 +1,112 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import { i18n } from '@kbn/i18n'; +import type { ISavedObjectsRepository } from '@kbn/core-saved-objects-api-server'; +import { isEmpty } from 'lodash'; +import { getAgentPoliciesAsInternalUser } from '../routes/settings/private_locations/get_agent_policies'; +import { PrivateLocationAttributes } from '../runtime_types/private_locations'; +import { PrivateLocationObject } from '../routes/settings/private_locations/add_private_location'; +import { RouteContext } from '../routes/types'; +import { privateLocationSavedObjectName } from '../../common/saved_objects/private_locations'; + +export class PrivateLocationRepository { + internalSOClient: ISavedObjectsRepository; + constructor(private routeContext: RouteContext) { + const { server } = routeContext; + this.internalSOClient = server.coreStart.savedObjects.createInternalRepository(); + } + + async createPrivateLocation(formattedLocation: PrivateLocationAttributes, newId: string) { + const { savedObjectsClient } = this.routeContext; + const { spaces } = formattedLocation; + + return await savedObjectsClient.create( + privateLocationSavedObjectName, + formattedLocation, + { + id: newId, + initialNamespaces: isEmpty(spaces) || spaces?.includes('*') ? ['*'] : spaces, + } + ); + } + async validatePrivateLocation() { + const { response, request, server } = this.routeContext; + + let errorMessages = ''; + + const location = request.body as PrivateLocationObject; + + const { spaces } = location; + + const [data, agentPolicies] = await Promise.all([ + this.internalSOClient.find({ + type: privateLocationSavedObjectName, + perPage: 10000, + namespaces: spaces, + }), + await getAgentPoliciesAsInternalUser({ server }), + ]); + + const locations = data.saved_objects.map((loc) => ({ + ...loc.attributes, + spaces: loc.attributes.spaces || loc.namespaces, + })); + + const locWithAgentPolicyId = locations.find( + (loc) => loc.agentPolicyId === location.agentPolicyId + ); + + if (locWithAgentPolicyId) { + errorMessages = i18n.translate( + 'xpack.synthetics.privateLocations.create.errorMessages.policyExists', + { + defaultMessage: `Private location with agentPolicyId {agentPolicyId} already exists in spaces {spaces}`, + values: { + agentPolicyId: location.agentPolicyId, + spaces: formatSpaces(locWithAgentPolicyId.spaces), + }, + } + ); + } + + // return if name is already taken + const locWithSameLabel = locations.find((loc) => loc.label === location.label); + if (locWithSameLabel) { + errorMessages = i18n.translate( + 'xpack.synthetics.privateLocations.create.errorMessages.labelExists', + { + defaultMessage: `Private location with label {label} already exists in spaces: {spaces}`, + values: { label: location.label, spaces: formatSpaces(locWithSameLabel.spaces) }, + } + ); + } + + const agentPolicy = agentPolicies?.find((policy) => policy.id === location.agentPolicyId); + if (!agentPolicy) { + errorMessages = `Agent policy with id ${location.agentPolicyId} does not exist`; + } + if (errorMessages) { + return response.badRequest({ + body: { + message: errorMessages, + }, + }); + } + } +} + +const formatSpaces = (spaces: string[] | undefined) => { + return ( + spaces + ?.map((space) => + space === '*' + ? i18n.translate('xpack.synthetics.formatSpaces.', { defaultMessage: '* All Spaces' }) + : space + ) + .join(', ') ?? 'Unknown' + ); +}; diff --git a/x-pack/solutions/observability/plugins/synthetics/server/routes/settings/private_locations/add_private_location.ts b/x-pack/solutions/observability/plugins/synthetics/server/routes/settings/private_locations/add_private_location.ts index fa88de31e3ec8..fe4d547ff9f6a 100644 --- a/x-pack/solutions/observability/plugins/synthetics/server/routes/settings/private_locations/add_private_location.ts +++ b/x-pack/solutions/observability/plugins/synthetics/server/routes/settings/private_locations/add_private_location.ts @@ -6,13 +6,13 @@ */ import { schema, TypeOf } from '@kbn/config-schema'; +import { SavedObjectsErrorHelpers } from '@kbn/core/server'; +import { v4 as uuidV4 } from 'uuid'; +import { PrivateLocationRepository } from '../../../repositories/private_location_repository'; import { PRIVATE_LOCATION_WRITE_API } from '../../../feature'; import { migrateLegacyPrivateLocations } from './migrate_legacy_private_locations'; import { SyntheticsRestApiRouteFactory } from '../../types'; -import { getPrivateLocationsAndAgentPolicies } from './get_private_locations'; -import { privateLocationSavedObjectName } from '../../../../common/saved_objects/private_locations'; import { SYNTHETICS_API_URLS } from '../../../../common/constants'; -import { PrivateLocationAttributes } from '../../../runtime_types/private_locations'; import { toClientContract, toSavedObjectContract } from './helpers'; import { PrivateLocation } from '../../../../common/runtime_types'; @@ -26,6 +26,11 @@ export const PrivateLocationSchema = schema.object({ lon: schema.number(), }) ), + spaces: schema.maybe( + schema.arrayOf(schema.string(), { + minSize: 1, + }) + ), }); export type PrivateLocationObject = TypeOf; @@ -41,60 +46,43 @@ export const addPrivateLocationRoute: SyntheticsRestApiRouteFactory { - const { response, request, savedObjectsClient, syntheticsMonitorClient, server } = routeContext; + const { response, request, server } = routeContext; const internalSOClient = server.coreStart.savedObjects.createInternalRepository(); - await migrateLegacyPrivateLocations(internalSOClient, server.logger); - const location = request.body as PrivateLocationObject; - - const { locations, agentPolicies } = await getPrivateLocationsAndAgentPolicies( - savedObjectsClient, - syntheticsMonitorClient - ); - - if (locations.find((loc) => loc.agentPolicyId === location.agentPolicyId)) { - return response.badRequest({ - body: { - message: `Private location with agentPolicyId ${location.agentPolicyId} already exists`, - }, - }); - } + const repo = new PrivateLocationRepository(routeContext); - // return if name is already taken - if (locations.find((loc) => loc.label === location.label)) { - return response.badRequest({ - body: { - message: `Private location with label ${location.label} already exists`, - }, - }); + const invalidError = await repo.validatePrivateLocation(); + if (invalidError) { + return invalidError; } - const formattedLocation = toSavedObjectContract({ - ...location, - id: location.agentPolicyId, - }); - - const agentPolicy = agentPolicies?.find((policy) => policy.id === location.agentPolicyId); - if (!agentPolicy) { - return response.badRequest({ - body: { - message: `Agent policy with id ${location.agentPolicyId} does not exist`, - }, - }); - } + const location = request.body as PrivateLocationObject; + const newId = uuidV4(); + const formattedLocation = toSavedObjectContract({ ...location, id: newId }); + const { spaces } = location; - const soClient = routeContext.server.coreStart.savedObjects.createInternalRepository(); + try { + const result = await repo.createPrivateLocation(formattedLocation, newId); - const result = await soClient.create( - privateLocationSavedObjectName, - formattedLocation, - { - id: location.agentPolicyId, - initialNamespaces: ['*'], + return toClientContract(result); + } catch (error) { + if (SavedObjectsErrorHelpers.isForbiddenError(error)) { + if (spaces?.includes('*')) { + return response.badRequest({ + body: { + message: `You do not have permission to create a location in all spaces.`, + }, + }); + } + return response.customError({ + statusCode: error.output.statusCode, + body: { + message: error.message, + }, + }); } - ); - - return toClientContract(result.attributes, agentPolicies); + throw error; + } }, }); diff --git a/x-pack/solutions/observability/plugins/synthetics/server/routes/settings/private_locations/helpers.ts b/x-pack/solutions/observability/plugins/synthetics/server/routes/settings/private_locations/helpers.ts index 8df065ad3e48d..956fdec42335b 100644 --- a/x-pack/solutions/observability/plugins/synthetics/server/routes/settings/private_locations/helpers.ts +++ b/x-pack/solutions/observability/plugins/synthetics/server/routes/settings/private_locations/helpers.ts @@ -4,6 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ +import { SavedObject } from '@kbn/core/server'; import { AgentPolicyInfo } from '../../../../common/types'; import type { SyntheticsPrivateLocations } from '../../../../common/runtime_types'; import type { @@ -13,18 +14,18 @@ import type { import { PrivateLocation } from '../../../../common/runtime_types'; export const toClientContract = ( - location: PrivateLocationAttributes, - agentPolicies?: AgentPolicyInfo[] + locationObject: SavedObject ): PrivateLocation => { - const agPolicy = agentPolicies?.find((policy) => policy.id === location.agentPolicyId); + const location = locationObject.attributes; return { label: location.label, id: location.id, agentPolicyId: location.agentPolicyId, isServiceManaged: false, - isInvalid: !Boolean(agPolicy), + isInvalid: false, tags: location.tags, geo: location.geo, + spaces: locationObject.namespaces, }; }; @@ -42,6 +43,7 @@ export const allLocationsToClientContract = ( isInvalid: !Boolean(agPolicy), tags: location.tags, geo: location.geo, + spaces: location.spaces, }; }); }; @@ -55,5 +57,6 @@ export const toSavedObjectContract = (location: PrivateLocation): PrivateLocatio isServiceManaged: false, geo: location.geo, namespace: location.namespace, + spaces: location.spaces, }; }; diff --git a/x-pack/solutions/observability/plugins/synthetics/server/synthetics_service/get_private_locations.ts b/x-pack/solutions/observability/plugins/synthetics/server/synthetics_service/get_private_locations.ts index a476df9dfe038..3bfa62988a16a 100644 --- a/x-pack/solutions/observability/plugins/synthetics/server/synthetics_service/get_private_locations.ts +++ b/x-pack/solutions/observability/plugins/synthetics/server/synthetics_service/get_private_locations.ts @@ -25,22 +25,18 @@ export const getPrivateLocations = async ( client: SavedObjectsClientContract ): Promise => { try { - const finder = client.createPointInTimeFinder({ - type: privateLocationSavedObjectName, - perPage: 1000, - }); + const [results, legacyLocations] = await Promise.all([ + getNewPrivateLocations(client), + getLegacyPrivateLocations(client), + ]); - const results: Array> = []; - - for await (const response of finder.find()) { - results.push(...response.saved_objects); - } - - finder.close().catch((e) => {}); - - const legacyLocations = await getLegacyPrivateLocations(client); - - return uniqBy([...results.map((r) => r.attributes), ...legacyLocations], 'id'); + return uniqBy( + [ + ...results.map((r) => ({ ...r.attributes, spaces: r.namespaces, id: r.id })), + ...legacyLocations, + ], + 'id' + ); } catch (getErr) { if (SavedObjectsErrorHelpers.isNotFoundError(getErr)) { return []; @@ -49,6 +45,22 @@ export const getPrivateLocations = async ( } }; +const getNewPrivateLocations = async (client: SavedObjectsClientContract) => { + const finder = client.createPointInTimeFinder({ + type: privateLocationSavedObjectName, + perPage: 1000, + }); + + const results: Array> = []; + + for await (const response of finder.find()) { + results.push(...response.saved_objects); + } + + finder.close().catch((e) => {}); + return results; +}; + const getLegacyPrivateLocations = async (client: SavedObjectsClientContract) => { try { const obj = await client.get( diff --git a/x-pack/solutions/observability/plugins/synthetics/server/synthetics_service/project_monitor/normalizers/common_fields.ts b/x-pack/solutions/observability/plugins/synthetics/server/synthetics_service/project_monitor/normalizers/common_fields.ts index c67e7decbe984..5dc6abe0453b0 100644 --- a/x-pack/solutions/observability/plugins/synthetics/server/synthetics_service/project_monitor/normalizers/common_fields.ts +++ b/x-pack/solutions/observability/plugins/synthetics/server/synthetics_service/project_monitor/normalizers/common_fields.ts @@ -217,10 +217,9 @@ export const getMonitorLocations = ({ }) || []; const privateLocs = monitorLocations.privateLocations?.map((locationName) => { + const loc = locationName.toLowerCase(); const locationFound = allPrivateLocations.find( - (location) => - location.label.toLowerCase() === locationName.toLowerCase() || - location.id.toLowerCase() === locationName.toLowerCase() + (location) => location.label.toLowerCase() === loc || location.id.toLowerCase() === loc ); if (locationFound) { return locationFound; diff --git a/x-pack/solutions/search/packages/search/shared_ui/README.md b/x-pack/solutions/search/packages/shared_ui/README.md similarity index 100% rename from x-pack/solutions/search/packages/search/shared_ui/README.md rename to x-pack/solutions/search/packages/shared_ui/README.md diff --git a/x-pack/solutions/search/packages/search/shared_ui/index.ts b/x-pack/solutions/search/packages/shared_ui/index.ts similarity index 93% rename from x-pack/solutions/search/packages/search/shared_ui/index.ts rename to x-pack/solutions/search/packages/shared_ui/index.ts index 66b35fc503371..5db02d31b4f97 100644 --- a/x-pack/solutions/search/packages/search/shared_ui/index.ts +++ b/x-pack/solutions/search/packages/shared_ui/index.ts @@ -9,3 +9,4 @@ export * from './src/connector_icon'; export * from './src/decorative_horizontal_stepper'; export * from './src/form_info_field/form_info_field'; export * from './src/search_empty_prompt'; +export * from './src/icons'; diff --git a/x-pack/solutions/search/packages/search/shared_ui/jest.config.js b/x-pack/solutions/search/packages/shared_ui/jest.config.js similarity index 63% rename from x-pack/solutions/search/packages/search/shared_ui/jest.config.js rename to x-pack/solutions/search/packages/shared_ui/jest.config.js index a3e90e91ce935..b18e5ba2e0965 100644 --- a/x-pack/solutions/search/packages/search/shared_ui/jest.config.js +++ b/x-pack/solutions/search/packages/shared_ui/jest.config.js @@ -7,12 +7,10 @@ module.exports = { coverageDirectory: - '/target/kibana-coverage/jest/x-pack/solutions/search/packages/search/shared_ui', + '/target/kibana-coverage/jest/x-pack/solutions/search/packages/shared_ui', coverageReporters: ['text', 'html'], - collectCoverageFrom: [ - '/x-pack/solutions/search/packages/search/shared_ui/**/*.{ts,tsx}', - ], + collectCoverageFrom: ['/x-pack/solutions/search/packages/shared_ui/**/*.{ts,tsx}'], preset: '@kbn/test', - rootDir: '../../../../../..', - roots: ['/x-pack/solutions/search/packages/search/shared_ui'], + rootDir: '../../../../..', + roots: ['/x-pack/solutions/search/packages/shared_ui'], }; diff --git a/x-pack/solutions/search/packages/search/shared_ui/kibana.jsonc b/x-pack/solutions/search/packages/shared_ui/kibana.jsonc similarity index 100% rename from x-pack/solutions/search/packages/search/shared_ui/kibana.jsonc rename to x-pack/solutions/search/packages/shared_ui/kibana.jsonc diff --git a/x-pack/solutions/search/packages/search/shared_ui/package.json b/x-pack/solutions/search/packages/shared_ui/package.json similarity index 100% rename from x-pack/solutions/search/packages/search/shared_ui/package.json rename to x-pack/solutions/search/packages/shared_ui/package.json diff --git a/x-pack/solutions/search/packages/search/shared_ui/src/connector_icon/connector_icon.tsx b/x-pack/solutions/search/packages/shared_ui/src/connector_icon/connector_icon.tsx similarity index 100% rename from x-pack/solutions/search/packages/search/shared_ui/src/connector_icon/connector_icon.tsx rename to x-pack/solutions/search/packages/shared_ui/src/connector_icon/connector_icon.tsx diff --git a/x-pack/solutions/search/packages/search/shared_ui/src/connector_icon/index.ts b/x-pack/solutions/search/packages/shared_ui/src/connector_icon/index.ts similarity index 100% rename from x-pack/solutions/search/packages/search/shared_ui/src/connector_icon/index.ts rename to x-pack/solutions/search/packages/shared_ui/src/connector_icon/index.ts diff --git a/x-pack/solutions/search/packages/search/shared_ui/src/decorative_horizontal_stepper/decorative_horizontal_stepper.tsx b/x-pack/solutions/search/packages/shared_ui/src/decorative_horizontal_stepper/decorative_horizontal_stepper.tsx similarity index 100% rename from x-pack/solutions/search/packages/search/shared_ui/src/decorative_horizontal_stepper/decorative_horizontal_stepper.tsx rename to x-pack/solutions/search/packages/shared_ui/src/decorative_horizontal_stepper/decorative_horizontal_stepper.tsx diff --git a/x-pack/solutions/search/packages/search/shared_ui/src/decorative_horizontal_stepper/index.ts b/x-pack/solutions/search/packages/shared_ui/src/decorative_horizontal_stepper/index.ts similarity index 100% rename from x-pack/solutions/search/packages/search/shared_ui/src/decorative_horizontal_stepper/index.ts rename to x-pack/solutions/search/packages/shared_ui/src/decorative_horizontal_stepper/index.ts diff --git a/x-pack/solutions/search/packages/search/shared_ui/src/form_info_field/form_info_field.tsx b/x-pack/solutions/search/packages/shared_ui/src/form_info_field/form_info_field.tsx similarity index 100% rename from x-pack/solutions/search/packages/search/shared_ui/src/form_info_field/form_info_field.tsx rename to x-pack/solutions/search/packages/shared_ui/src/form_info_field/form_info_field.tsx diff --git a/x-pack/solutions/search/packages/shared_ui/src/icons/EuiIconPlugs.tsx b/x-pack/solutions/search/packages/shared_ui/src/icons/EuiIconPlugs.tsx new file mode 100644 index 0000000000000..ce7af9b282747 --- /dev/null +++ b/x-pack/solutions/search/packages/shared_ui/src/icons/EuiIconPlugs.tsx @@ -0,0 +1,32 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +// Temporary custom asset while it's available in EUI + +import * as React from 'react'; +import type { SVGProps } from 'react'; +interface SVGRProps { + title?: string; + titleId?: string; +} +export const EuiIconPlugs = ({ title, titleId, ...props }: SVGProps & SVGRProps) => ( + + {title ? {title} : null} + + +); diff --git a/x-pack/solutions/search/packages/shared_ui/src/icons/EuiIconWeb.tsx b/x-pack/solutions/search/packages/shared_ui/src/icons/EuiIconWeb.tsx new file mode 100644 index 0000000000000..32200171345bf --- /dev/null +++ b/x-pack/solutions/search/packages/shared_ui/src/icons/EuiIconWeb.tsx @@ -0,0 +1,32 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +// Temporary custom asset while it's available in EUI + +import * as React from 'react'; +import type { SVGProps } from 'react'; +interface SVGRProps { + title?: string; + titleId?: string; +} +export const EuiIconWeb = ({ title, titleId, ...props }: SVGProps & SVGRProps) => ( + + {title ? {title} : null} + + +); diff --git a/x-pack/solutions/search/plugins/enterprise_search/public/applications/shared/log_stream/index.ts b/x-pack/solutions/search/packages/shared_ui/src/icons/index.ts similarity index 80% rename from x-pack/solutions/search/plugins/enterprise_search/public/applications/shared/log_stream/index.ts rename to x-pack/solutions/search/packages/shared_ui/src/icons/index.ts index fc37e9ae317f4..6d4485a3296cf 100644 --- a/x-pack/solutions/search/plugins/enterprise_search/public/applications/shared/log_stream/index.ts +++ b/x-pack/solutions/search/packages/shared_ui/src/icons/index.ts @@ -4,5 +4,5 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ - -export { EntSearchLogStream } from './log_stream'; +export * from './EuiIconPlugs'; +export * from './EuiIconWeb'; diff --git a/x-pack/solutions/search/packages/search/shared_ui/src/search_empty_prompt/index.ts b/x-pack/solutions/search/packages/shared_ui/src/search_empty_prompt/index.ts similarity index 100% rename from x-pack/solutions/search/packages/search/shared_ui/src/search_empty_prompt/index.ts rename to x-pack/solutions/search/packages/shared_ui/src/search_empty_prompt/index.ts diff --git a/x-pack/solutions/search/packages/search/shared_ui/src/search_empty_prompt/search_empty_prompt.tsx b/x-pack/solutions/search/packages/shared_ui/src/search_empty_prompt/search_empty_prompt.tsx similarity index 100% rename from x-pack/solutions/search/packages/search/shared_ui/src/search_empty_prompt/search_empty_prompt.tsx rename to x-pack/solutions/search/packages/shared_ui/src/search_empty_prompt/search_empty_prompt.tsx diff --git a/x-pack/solutions/search/packages/search/shared_ui/tsconfig.json b/x-pack/solutions/search/packages/shared_ui/tsconfig.json similarity index 83% rename from x-pack/solutions/search/packages/search/shared_ui/tsconfig.json rename to x-pack/solutions/search/packages/shared_ui/tsconfig.json index 3c4dba3860f10..395089ce5332a 100644 --- a/x-pack/solutions/search/packages/search/shared_ui/tsconfig.json +++ b/x-pack/solutions/search/packages/shared_ui/tsconfig.json @@ -1,5 +1,5 @@ { - "extends": "../../../../../../tsconfig.base.json", + "extends": "../../../../../tsconfig.base.json", "compilerOptions": { "outDir": "target/types", "types": [ diff --git a/x-pack/solutions/search/plugins/enterprise_search/public/applications/enterprise_search_content/components/connectors/create_connector/components/choose_connector.tsx b/x-pack/solutions/search/plugins/enterprise_search/public/applications/enterprise_search_content/components/connectors/create_connector/components/choose_connector.tsx index f8d1d6e824e95..d630ab9ff7005 100644 --- a/x-pack/solutions/search/plugins/enterprise_search/public/applications/enterprise_search_content/components/connectors/create_connector/components/choose_connector.tsx +++ b/x-pack/solutions/search/plugins/enterprise_search/public/applications/enterprise_search_content/components/connectors/create_connector/components/choose_connector.tsx @@ -24,8 +24,8 @@ import { } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; +import { EuiIconPlugs } from '@kbn/search-shared-ui'; -import connectorLogo from '../../../../../../assets/images/connector.svg'; import { BETA_LABEL, TECH_PREVIEW_LABEL, @@ -151,7 +151,7 @@ export const ChooseConnector: React.FC = ({ 'xpack.enterpriseSearch.createConnector.chooseConnectorSelectable.euiComboBox.accessibleScreenReaderLabelLabel', { defaultMessage: 'Select a data source for your connector to use.' } )} - prepend={} + prepend={} singleSelection fullWidth placeholder={i18n.translate( diff --git a/x-pack/solutions/search/plugins/enterprise_search/public/applications/enterprise_search_content/components/connectors/elastic_managed_web_crawler_empty_prompt.tsx b/x-pack/solutions/search/plugins/enterprise_search/public/applications/enterprise_search_content/components/connectors/elastic_managed_web_crawler_empty_prompt.tsx index 9871238a4bcf1..9e42c5114544a 100644 --- a/x-pack/solutions/search/plugins/enterprise_search/public/applications/enterprise_search_content/components/connectors/elastic_managed_web_crawler_empty_prompt.tsx +++ b/x-pack/solutions/search/plugins/enterprise_search/public/applications/enterprise_search_content/components/connectors/elastic_managed_web_crawler_empty_prompt.tsx @@ -8,10 +8,9 @@ import React from 'react'; import { EuiFlexGroup, EuiFlexItem, EuiIcon, EuiPanel, EuiText } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { SearchEmptyPrompt, DecorativeHorizontalStepper } from '@kbn/search-shared-ui'; +import { SearchEmptyPrompt, DecorativeHorizontalStepper, EuiIconWeb } from '@kbn/search-shared-ui'; import { BACK_BUTTON_LABEL, COMING_SOON_LABEL } from '../../../shared/constants'; -import CrawlerIcon from '../../../shared/icons/web_crawlers.svg'; import { KibanaLogic } from '../../../shared/kibana'; import { CRAWLERS_PATH } from '../../routes'; @@ -22,7 +21,7 @@ export const ElasticManagedWebCrawlerEmptyPrompt: React.FC = () => { label: BACK_BUTTON_LABEL, onClickBack: () => KibanaLogic.values.navigateToUrl(CRAWLERS_PATH), }} - icon={CrawlerIcon} + icon={EuiIconWeb} title={i18n.translate('xpack.enterpriseSearch.elasticManagedWebCrawlerEmpty.title', { defaultMessage: 'Elastic managed web crawlers', })} @@ -86,7 +85,7 @@ export const ElasticManagedWebCrawlerEmptyPrompt: React.FC = () => { justifyContent="center" > - + diff --git a/x-pack/solutions/search/plugins/enterprise_search/public/applications/enterprise_search_content/components/connectors/self_managed_web_crawler_empty_prompt.tsx b/x-pack/solutions/search/plugins/enterprise_search/public/applications/enterprise_search_content/components/connectors/self_managed_web_crawler_empty_prompt.tsx index cf10b5a0603c6..64f3764412449 100644 --- a/x-pack/solutions/search/plugins/enterprise_search/public/applications/enterprise_search_content/components/connectors/self_managed_web_crawler_empty_prompt.tsx +++ b/x-pack/solutions/search/plugins/enterprise_search/public/applications/enterprise_search_content/components/connectors/self_managed_web_crawler_empty_prompt.tsx @@ -18,18 +18,17 @@ import { } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; -import { SearchEmptyPrompt, DecorativeHorizontalStepper } from '@kbn/search-shared-ui'; +import { SearchEmptyPrompt, DecorativeHorizontalStepper, EuiIconWeb } from '@kbn/search-shared-ui'; import { COMING_SOON_LABEL } from '../../../shared/constants'; import { GithubIcon } from '../../../shared/icons/github_icon'; -import CrawlerIcon from '../../../shared/icons/web_crawlers.svg'; import { KibanaLogic } from '../../../shared/kibana'; import { CRAWLERS_ELASTIC_MANAGED_PATH } from '../../routes'; export const SelfManagedWebCrawlerEmptyPrompt: React.FC = () => { return ( { justifyContent="center" > - + @@ -153,7 +152,7 @@ export const SelfManagedWebCrawlerEmptyPrompt: React.FC = () => { - + diff --git a/x-pack/solutions/search/plugins/enterprise_search/public/applications/shared/log_stream/log_stream.test.tsx b/x-pack/solutions/search/plugins/enterprise_search/public/applications/shared/log_stream/log_stream.test.tsx deleted file mode 100644 index 3d94a6e3b22e2..0000000000000 --- a/x-pack/solutions/search/plugins/enterprise_search/public/applications/shared/log_stream/log_stream.test.tsx +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React from 'react'; - -import { shallow } from 'enzyme'; - -import { LogStream } from '@kbn/logs-shared-plugin/public'; - -import { EntSearchLogStream } from '.'; - -const fakeSourceId = 'fake-source-id'; - -describe('EntSearchLogStream', () => { - const mockDateNow = jest.spyOn(global.Date, 'now').mockReturnValue(160000000); - - describe('renders with default props', () => { - const wrapper = shallow( - - ); - - it('renders a LogStream (wrapped in React.Suspense) component', () => { - expect(wrapper.type()).toEqual(LogStream); - }); - - it('renders with the empty sourceId', () => { - expect(wrapper.prop('sourceId')).toBeUndefined(); - }); - - it('renders with a default last-24-hours timestamp if no timestamp is passed', () => { - expect(wrapper.prop('startTimestamp')).toEqual(73600000); - expect(wrapper.prop('endTimestamp')).toEqual(160000000); - }); - }); - - describe('renders custom props', () => { - it('overrides the default props', () => { - const wrapper = shallow( - - ); - - expect(wrapper.prop('logView')).toEqual({ type: 'log-view-reference', logViewId: 'test' }); - expect(wrapper.prop('startTimestamp')).toEqual(1); - expect(wrapper.prop('endTimestamp')).toEqual(2); - }); - - it('allows passing a custom hoursAgo that modifies the default start timestamp', () => { - const wrapper = shallow( - - ); - - expect(wrapper.prop('startTimestamp')).toEqual(156400000); - expect(wrapper.prop('endTimestamp')).toEqual(160000000); - }); - - it('allows passing any prop that the LogStream component takes', () => { - const wrapper = shallow( - - ); - - expect(wrapper.prop('height')).toEqual(500); - expect(wrapper.prop('highlight')).toEqual('some-log-id'); - expect(wrapper.prop('columns')).toBeTruthy(); - expect(wrapper.prop('filters')).toEqual([]); - }); - }); - - afterAll(() => mockDateNow.mockRestore()); -}); diff --git a/x-pack/solutions/search/plugins/enterprise_search/public/applications/shared/log_stream/log_stream.tsx b/x-pack/solutions/search/plugins/enterprise_search/public/applications/shared/log_stream/log_stream.tsx deleted file mode 100644 index 5748d306b6319..0000000000000 --- a/x-pack/solutions/search/plugins/enterprise_search/public/applications/shared/log_stream/log_stream.tsx +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React from 'react'; - -import { LogStream, LogStreamProps } from '@kbn/logs-shared-plugin/public'; - -/* - * EnterpriseSearchLogStream is a light wrapper on top of logsShared's embeddable LogStream component. - * It prepopulates our log source ID (set in server/plugin.ts) and sets a basic 24-hours-ago - * default for timestamps. All other props get passed as-is to the underlying LogStream. - * - * Documentation links for reference: - * - https://github.com/elastic/kibana/blob/main/x-pack/plugins/observability_solution/logs_shared/public/components/log_stream/log_stream.stories.mdx - * - Run `yarn storybook logsShared` for live docs - */ - -interface Props extends Omit { - startTimestamp?: LogStreamProps['startTimestamp']; - endTimestamp?: LogStreamProps['endTimestamp']; - hoursAgo?: number; -} - -export const EntSearchLogStream: React.FC = ({ - startTimestamp, - endTimestamp, - hoursAgo = 24, - ...props -}) => { - if (!endTimestamp) endTimestamp = Date.now(); - if (!startTimestamp) startTimestamp = endTimestamp - hoursAgo * 60 * 60 * 1000; - - return ; -}; diff --git a/x-pack/solutions/search/plugins/enterprise_search/public/assets/images/crawler.svg b/x-pack/solutions/search/plugins/enterprise_search/public/assets/images/crawler.svg index 94aafafddf68b..6e7e2de93f3e7 100644 --- a/x-pack/solutions/search/plugins/enterprise_search/public/assets/images/crawler.svg +++ b/x-pack/solutions/search/plugins/enterprise_search/public/assets/images/crawler.svg @@ -1,4 +1,3 @@ - - - + + diff --git a/x-pack/solutions/search/plugins/enterprise_search/public/plugin.ts b/x-pack/solutions/search/plugins/enterprise_search/public/plugin.ts index c548b07f87911..98e5fa35be834 100644 --- a/x-pack/solutions/search/plugins/enterprise_search/public/plugin.ts +++ b/x-pack/solutions/search/plugins/enterprise_search/public/plugin.ts @@ -59,8 +59,6 @@ import { hasEnterpriseLicense } from '../common/utils/licensing'; import { SEARCH_APPLICATIONS_PATH } from './applications/applications/routes'; import { CONNECTORS_PATH, CRAWLERS_PATH } from './applications/enterprise_search_content/routes'; import { docLinks } from './applications/shared/doc_links'; -import connectorIcon from './assets/images/connector.svg'; -import crawlerIcon from './assets/images/crawler.svg'; import type { DynamicSideNavItems } from './navigation_tree'; @@ -108,7 +106,6 @@ export type UpdateSideNavDefinitionFn = (items: Partial) => const contentLinks: AppDeepLink[] = [ { - euiIconType: connectorIcon, id: 'connectors', path: `/${CONNECTORS_PATH}`, title: i18n.translate('xpack.enterpriseSearch.navigation.contentConnectorsLinkLabel', { @@ -116,7 +113,6 @@ const contentLinks: AppDeepLink[] = [ }), }, { - euiIconType: crawlerIcon, id: 'webCrawlers', path: `/${CRAWLERS_PATH}`, title: i18n.translate('xpack.enterpriseSearch.navigation.contentWebcrawlersLinkLabel', { diff --git a/x-pack/solutions/search/plugins/search_indices/public/components/create_index/create_index.tsx b/x-pack/solutions/search/plugins/search_indices/public/components/create_index/create_index.tsx index 29d01907b8688..34a5b36f10f14 100644 --- a/x-pack/solutions/search/plugins/search_indices/public/components/create_index/create_index.tsx +++ b/x-pack/solutions/search/plugins/search_indices/public/components/create_index/create_index.tsx @@ -112,8 +112,8 @@ export const CreateIndex = ({ indicesData }: CreateIndexProps) => { changeWorkflowId={(workflowId: WorkflowId) => { setSelectedWorkflowId(workflowId); usageTracker.click([ - AnalyticsEvents.startCreateIndexWorkflowSelect, - `${AnalyticsEvents.startCreateIndexWorkflowSelect}_${workflowId}`, + AnalyticsEvents.createIndexWorkflowSelect, + `${AnalyticsEvents.createIndexWorkflowSelect}_${workflowId}`, ]); }} selectedWorkflow={workflow} diff --git a/x-pack/solutions/search/plugins/search_inference_endpoints/public/assets/images/providers/jinaai.svg b/x-pack/solutions/search/plugins/search_inference_endpoints/public/assets/images/providers/jinaai.svg new file mode 100644 index 0000000000000..605c0cff86942 --- /dev/null +++ b/x-pack/solutions/search/plugins/search_inference_endpoints/public/assets/images/providers/jinaai.svg @@ -0,0 +1,13 @@ + + + Jina-color + + + + + + + + + + \ No newline at end of file diff --git a/x-pack/solutions/search/plugins/serverless_search/public/application/components/connectors/edit_service_type.tsx b/x-pack/solutions/search/plugins/serverless_search/public/application/components/connectors/edit_service_type.tsx index ab50acbbfed2f..8c7927887836d 100644 --- a/x-pack/solutions/search/plugins/serverless_search/public/application/components/connectors/edit_service_type.tsx +++ b/x-pack/solutions/search/plugins/serverless_search/public/application/components/connectors/edit_service_type.tsx @@ -20,10 +20,10 @@ import { EuiTextTruncate, EuiBadgeGroup, } from '@elastic/eui'; +import { EuiIconPlugs } from '@kbn/search-shared-ui'; import { useMutation, useQueryClient } from '@tanstack/react-query'; import { Connector as BaseConnector } from '@kbn/search-connectors'; import { css } from '@emotion/react'; -import { useAssetBasePath } from '../../hooks/use_asset_base_path'; import { BETA_LABEL, TECH_PREVIEW_LABEL } from '../../../../common/i18n_string'; @@ -56,7 +56,6 @@ export const EditServiceType: React.FC = ({ connector, isD const connectorTypes = useConnectorTypes(); const queryClient = useQueryClient(); const { queryKey } = useConnector(connector.id); - const assetBasePath = useAssetBasePath(); const allConnectors = useMemo( () => connectorTypes.sort((a, b) => a.name.localeCompare(b.name)), @@ -234,7 +233,7 @@ export const EditServiceType: React.FC = ({ connector, isD connector.service_type ? connectorTypes.find((conn) => conn.serviceType === connector.service_type) ?.iconPath ?? '' - : `${assetBasePath}/connectors.svg` + : EuiIconPlugs } size="l" /> diff --git a/x-pack/solutions/search/plugins/serverless_search/public/application/components/connectors/elastic_managed_connectors_empty_prompt.tsx b/x-pack/solutions/search/plugins/serverless_search/public/application/components/connectors/elastic_managed_connectors_empty_prompt.tsx index ed1e1a6dfc0ac..2212d4f4c0efe 100644 --- a/x-pack/solutions/search/plugins/serverless_search/public/application/components/connectors/elastic_managed_connectors_empty_prompt.tsx +++ b/x-pack/solutions/search/plugins/serverless_search/public/application/components/connectors/elastic_managed_connectors_empty_prompt.tsx @@ -9,12 +9,15 @@ import React from 'react'; import { EuiFlexGroup, EuiFlexItem, EuiPanel, EuiIcon, EuiText } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { ConnectorIcon } from '@kbn/search-shared-ui'; -import { SearchEmptyPrompt, DecorativeHorizontalStepper } from '@kbn/search-shared-ui'; +import { + SearchEmptyPrompt, + DecorativeHorizontalStepper, + EuiIconPlugs, +} from '@kbn/search-shared-ui'; import { SERVERLESS_ES_CONNECTORS_ID } from '@kbn/deeplinks-search/constants'; import { BACK_LABEL, COMING_SOON_LABEL } from '../../../../common/i18n_string'; import { useKibanaServices } from '../../hooks/use_kibana'; import { useConnectorTypes } from '../../hooks/api/use_connector_types'; -import { useAssetBasePath } from '../../hooks/use_asset_base_path'; export const ElasticManagedConnectorsEmptyPrompt: React.FC = () => { const connectorTypes = useConnectorTypes(); @@ -22,8 +25,6 @@ export const ElasticManagedConnectorsEmptyPrompt: React.FC = () => { ['Gmail', 'Sharepoint Online', 'Jira Cloud', 'Dropbox'].includes(connector.name) ); - const assetBasePath = useAssetBasePath(); - const connectorsIcon = assetBasePath + '/connectors.svg'; const { application: { navigateToApp }, } = useKibanaServices(); @@ -34,7 +35,7 @@ export const ElasticManagedConnectorsEmptyPrompt: React.FC = () => { label: BACK_LABEL, onClickBack: () => navigateToApp(SERVERLESS_ES_CONNECTORS_ID), }} - icon={connectorsIcon} + icon={EuiIconPlugs} title={i18n.translate('xpack.serverlessSearch.elasticManagedConnectorEmpty.title', { defaultMessage: 'Elastic managed connectors', })} @@ -113,7 +114,7 @@ export const ElasticManagedConnectorsEmptyPrompt: React.FC = () => { justifyContent="center" > - + diff --git a/x-pack/solutions/search/plugins/serverless_search/public/application/components/connectors/self_managed_connectors_empty_prompt.tsx b/x-pack/solutions/search/plugins/serverless_search/public/application/components/connectors/self_managed_connectors_empty_prompt.tsx index d8805ceb63408..90789d913fb2a 100644 --- a/x-pack/solutions/search/plugins/serverless_search/public/application/components/connectors/self_managed_connectors_empty_prompt.tsx +++ b/x-pack/solutions/search/plugins/serverless_search/public/application/components/connectors/self_managed_connectors_empty_prompt.tsx @@ -19,12 +19,15 @@ import { i18n } from '@kbn/i18n'; import React from 'react'; import { FormattedMessage } from '@kbn/i18n-react'; import { ConnectorIcon } from '@kbn/search-shared-ui'; -import { SearchEmptyPrompt, DecorativeHorizontalStepper } from '@kbn/search-shared-ui'; +import { + SearchEmptyPrompt, + DecorativeHorizontalStepper, + EuiIconPlugs, +} from '@kbn/search-shared-ui'; import { docLinks } from '../../../../common/doc_links'; import { useKibanaServices } from '../../hooks/use_kibana'; import { useConnectorTypes } from '../../hooks/api/use_connector_types'; import { useCreateConnector } from '../../hooks/api/use_create_connector'; -import { useAssetBasePath } from '../../hooks/use_asset_base_path'; import { useConnectors } from '../../hooks/api/use_connectors'; import { ELASTIC_MANAGED_CONNECTOR_PATH, BASE_CONNECTORS_PATH } from '../../constants'; import { BACK_LABEL } from '../../../../common/i18n_string'; @@ -36,15 +39,13 @@ export const SelfManagedConnectorsEmptyPrompt: React.FC = () => { ); const { createConnector, isLoading } = useCreateConnector(); const { data } = useConnectors(); - const assetBasePath = useAssetBasePath(); - const connectorsIcon = assetBasePath + '/connectors.svg'; const { application: { navigateToUrl }, } = useKibanaServices(); return ( { justifyContent="center" > - + @@ -183,7 +184,7 @@ export const SelfManagedConnectorsEmptyPrompt: React.FC = () => { - + diff --git a/x-pack/solutions/search/plugins/serverless_search/public/application/components/web_crawlers/elastic_managed_web_crawlers_empty_prompt.tsx b/x-pack/solutions/search/plugins/serverless_search/public/application/components/web_crawlers/elastic_managed_web_crawlers_empty_prompt.tsx index 15160fc1b6a1d..6f6cdb767591b 100644 --- a/x-pack/solutions/search/plugins/serverless_search/public/application/components/web_crawlers/elastic_managed_web_crawlers_empty_prompt.tsx +++ b/x-pack/solutions/search/plugins/serverless_search/public/application/components/web_crawlers/elastic_managed_web_crawlers_empty_prompt.tsx @@ -7,18 +7,15 @@ import React from 'react'; import { EuiFlexGroup, EuiFlexItem, EuiIcon, EuiPanel, EuiText } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { SearchEmptyPrompt, DecorativeHorizontalStepper } from '@kbn/search-shared-ui'; +import { SearchEmptyPrompt, DecorativeHorizontalStepper, EuiIconWeb } from '@kbn/search-shared-ui'; import { SERVERLESS_ES_WEB_CRAWLERS_ID } from '@kbn/deeplinks-search/constants'; import { BACK_LABEL, COMING_SOON_LABEL } from '../../../../common/i18n_string'; -import { useAssetBasePath } from '../../hooks/use_asset_base_path'; import { useKibanaServices } from '../../hooks/use_kibana'; export const ElasticManagedWebCrawlersEmptyPrompt = () => { const { application: { navigateToApp }, } = useKibanaServices(); - const assetBasePath = useAssetBasePath(); - const webCrawlersIcon = assetBasePath + '/web_crawlers.svg'; return ( { label: BACK_LABEL, onClickBack: () => navigateToApp(SERVERLESS_ES_WEB_CRAWLERS_ID), }} - icon={webCrawlersIcon} + icon={EuiIconWeb} title={i18n.translate('xpack.serverlessSearch.elasticManagedWebCrawlerEmpty.title', { defaultMessage: 'Elastic managed web crawlers', })} @@ -90,7 +87,7 @@ export const ElasticManagedWebCrawlersEmptyPrompt = () => { justifyContent="center" > - + diff --git a/x-pack/solutions/search/plugins/serverless_search/public/application/components/web_crawlers/self_managed_web_crawlers_empty_prompt.tsx b/x-pack/solutions/search/plugins/serverless_search/public/application/components/web_crawlers/self_managed_web_crawlers_empty_prompt.tsx index b820e7704c856..f35664defb113 100644 --- a/x-pack/solutions/search/plugins/serverless_search/public/application/components/web_crawlers/self_managed_web_crawlers_empty_prompt.tsx +++ b/x-pack/solutions/search/plugins/serverless_search/public/application/components/web_crawlers/self_managed_web_crawlers_empty_prompt.tsx @@ -16,7 +16,7 @@ import { EuiText, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { SearchEmptyPrompt, DecorativeHorizontalStepper } from '@kbn/search-shared-ui'; +import { SearchEmptyPrompt, DecorativeHorizontalStepper, EuiIconWeb } from '@kbn/search-shared-ui'; import { FormattedMessage } from '@kbn/i18n-react'; import { ELASTIC_MANAGED_WEB_CRAWLERS_PATH, BASE_WEB_CRAWLERS_PATH } from '../../constants'; import { COMING_SOON_LABEL } from '../../../../common/i18n_string'; @@ -29,12 +29,11 @@ export const SelfManagedWebCrawlersEmptyPrompt = () => { } = useKibanaServices(); const assetBasePath = useAssetBasePath(); - const webCrawlersIcon = assetBasePath + '/web_crawlers.svg'; const githubIcon = assetBasePath + '/github_white.svg'; return ( { justifyContent="center" > - + @@ -158,7 +157,7 @@ export const SelfManagedWebCrawlersEmptyPrompt = () => { - + diff --git a/x-pack/solutions/search/plugins/serverless_search/public/plugin.ts b/x-pack/solutions/search/plugins/serverless_search/public/plugin.ts index 1b804e4bab307..1e37bfbd2880a 100644 --- a/x-pack/solutions/search/plugins/serverless_search/public/plugin.ts +++ b/x-pack/solutions/search/plugins/serverless_search/public/plugin.ts @@ -157,8 +157,6 @@ export class ServerlessSearchPlugin }, }); - setupDeps.discover.showInlineTopNav(); - return {}; } diff --git a/x-pack/solutions/security/packages/side_nav/src/solution_side_nav.tsx b/x-pack/solutions/security/packages/side_nav/src/solution_side_nav.tsx index 0b06dfd75169a..22f1207a6c01b 100644 --- a/x-pack/solutions/security/packages/side_nav/src/solution_side_nav.tsx +++ b/x-pack/solutions/security/packages/side_nav/src/solution_side_nav.tsx @@ -270,12 +270,12 @@ const SolutionSideNavItem: React.FC = React.memo( return ( {label} - + ); - }, [label, iconType]); + }, [iconType, label, id]); return ( <> diff --git a/x-pack/solutions/security/plugins/cloud_defend/kibana.jsonc b/x-pack/solutions/security/plugins/cloud_defend/kibana.jsonc index f0155401048d2..ec5850b1dc49b 100644 --- a/x-pack/solutions/security/plugins/cloud_defend/kibana.jsonc +++ b/x-pack/solutions/security/plugins/cloud_defend/kibana.jsonc @@ -23,8 +23,7 @@ "kibanaReact", "cloud", "security", - "licensing", - "kubernetesSecurity" + "licensing" ], "optionalPlugins": [ "usageCollection" diff --git a/x-pack/solutions/security/plugins/cloud_defend/public/common/navigation/constants.ts b/x-pack/solutions/security/plugins/cloud_defend/public/common/navigation/constants.ts index f063ad0acab7e..c4de6caa61b84 100644 --- a/x-pack/solutions/security/plugins/cloud_defend/public/common/navigation/constants.ts +++ b/x-pack/solutions/security/plugins/cloud_defend/public/common/navigation/constants.ts @@ -6,7 +6,6 @@ */ import { i18n } from '@kbn/i18n'; -import { KUBERNETES_PATH, KUBERNETES_TITLE } from '@kbn/kubernetes-security-plugin/public'; import type { CloudDefendPage, CloudDefendPageNavigationItem } from './types'; const NAV_ITEMS_NAMES = { @@ -24,9 +23,4 @@ export const cloudDefendPages: Record { - const { application } = useKibana().services; - - const views: CustomAssetsAccordionProps['views'] = [ - { - name: cloudDefendPages.dashboard.name, - url: application.getUrlForApp(SECURITY_APP_NAME, { path: cloudDefendPages.dashboard.path }), - description: i18n.translate( - 'xpack.cloudDefend.createPackagePolicy.customAssetsTab.dashboardViewLabel', - { defaultMessage: 'View k8s dashboard' } - ), - }, - ]; - - return ; -}; -// eslint-disable-next-line import/no-default-export -export { CloudDefendCustomAssetsExtension as default }; diff --git a/x-pack/solutions/security/plugins/cloud_defend/public/plugin.tsx b/x-pack/solutions/security/plugins/cloud_defend/public/plugin.tsx index 43224794cddd6..e9cb2d8957ad1 100755 --- a/x-pack/solutions/security/plugins/cloud_defend/public/plugin.tsx +++ b/x-pack/solutions/security/plugins/cloud_defend/public/plugin.tsx @@ -23,10 +23,6 @@ const LazyPolicyReplaceDefineStepExtension = lazy( () => import('./components/fleet_extensions/package_policy_replace_define_step_extension') ); -const LazyCustomAssets = lazy( - () => import('./components/fleet_extensions/custom_assets_extension') -); - const RouterLazy = lazy(() => import('./application/router')); const Router = (props: CloudDefendRouterProps) => ( }> @@ -62,12 +58,6 @@ export class CloudDefendPlugin Component: LazyPolicyReplaceDefineStepExtension, }); - plugins.fleet.registerExtension({ - package: INTEGRATION_PACKAGE_NAME, - view: 'package-detail-assets', - Component: LazyCustomAssets, - }); - const CloudDefendRouter = (props: CloudDefendRouterProps) => ( diff --git a/x-pack/solutions/security/plugins/cloud_defend/tsconfig.json b/x-pack/solutions/security/plugins/cloud_defend/tsconfig.json index cce09d24d8d58..f35522a9cf0dd 100755 --- a/x-pack/solutions/security/plugins/cloud_defend/tsconfig.json +++ b/x-pack/solutions/security/plugins/cloud_defend/tsconfig.json @@ -32,7 +32,6 @@ "@kbn/es-types", "@kbn/data-views-plugin", "@kbn/utility-types", - "@kbn/kubernetes-security-plugin", "@kbn/core-http-router-server-mocks", "@kbn/core-elasticsearch-server", "@kbn/code-editor", diff --git a/x-pack/solutions/security/plugins/kubernetes_security/.eslintrc.json b/x-pack/solutions/security/plugins/kubernetes_security/.eslintrc.json deleted file mode 100644 index 2aab6c2d9093b..0000000000000 --- a/x-pack/solutions/security/plugins/kubernetes_security/.eslintrc.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "rules": { - "@typescript-eslint/consistent-type-definitions": 0 - } -} diff --git a/x-pack/solutions/security/plugins/kubernetes_security/README.md b/x-pack/solutions/security/plugins/kubernetes_security/README.md deleted file mode 100644 index 9ff29c7471430..0000000000000 --- a/x-pack/solutions/security/plugins/kubernetes_security/README.md +++ /dev/null @@ -1,41 +0,0 @@ -# Kubernetes Security -This plugin provides interactive visualizations of your Kubernetes workload and session data. - -## Overview -Allow users to explore the data stream from k8s environment that being monitored by Elastic Agent(+ endpoint integration) in a session view with cloud and k8s context. For more context, see internal [doc](https://github.com/elastic/security-team/issues/3337). - -This plugin is currently being used as a part of Security Solution features under the `/app/security/kubernetes` page. - -## API - -#### `getKubernetesPage` -Returns the kubernetes page. -Parameters -| Property | Description | Type | -| ----------------------- | ----------------- | ------ | -| kubernetesSecurityDeps | Parameters object | object | - -`kubernetesSecurityDeps` -| Property | Description | Type | -| ------------------- | ------------------------------------------------------------- | --------- | -| filter | The global filter component used across pages in Kibana | ReactNode | -| renderSessionsView | Function to render sessions view table | function | -| indexPattern | Index pattern used for the data source in the Kubernetes page | object | -| globalFilter | Includes query and timerange used for filtering | object | - -`indexPattern` -| Property | Description | Type | -| --------- | ----------------------------------- | -------------------------------------------- | -| fields | A list of `FieldSpec` | `FieldSpec[]` from `@kbn/data-plugin/common` | -| title | Index pattern string representation | string | - -`globalFilter` -| Property | Description | Type | -| ----------- | -------------------------------------------------------------------------------------------------------------------------------------------- | ----------------- | -| filterQuery | Stringified Elasticsearch filter query. See [doc](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-filter-context.html). | Optional, string | -| startDate | Start date time of timerange filter, in ISO format | string | -| endDate | End date time of timerange filter, in ISO format | string | - - -## Page preview -![preview](https://user-images.githubusercontent.com/91196877/171646384-ff7041ae-13ae-4abc-bb25-636c38e7efbb.png) \ No newline at end of file diff --git a/x-pack/solutions/security/plugins/kubernetes_security/common/constants.ts b/x-pack/solutions/security/plugins/kubernetes_security/common/constants.ts deleted file mode 100644 index 69b2c8068db2c..0000000000000 --- a/x-pack/solutions/security/plugins/kubernetes_security/common/constants.ts +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -export const KUBERNETES_PATH = '/kubernetes' as const; -export const KUBERNETES_TITLE = 'Kubernetes'; -export const LOCAL_STORAGE_HIDE_WIDGETS_KEY = 'kubernetesSecurity:shouldHideWidgets'; -export const LOCAL_STORAGE_TREE_NAV_KEY = 'kubernetesSecurity:treeNavSelection'; - -export const CURRENT_API_VERSION = '1'; -export const AGGREGATE_ROUTE = '/internal/kubernetes_security/aggregate'; -export const COUNT_ROUTE = '/internal/kubernetes_security/count'; -export const MULTI_TERMS_AGGREGATE_ROUTE = '/internal/kubernetes_security/multi_terms_aggregate'; - -export const AGGREGATE_PAGE_SIZE = 10; - -// so, bucket sort can only page through what we request at the top level agg, which means there is a ceiling to how many aggs we can page through. -// we should also test this approach at scale. -export const AGGREGATE_MAX_BUCKETS = 2000; - -// react-query caching keys -export const QUERY_KEY_PERCENT_WIDGET = 'kubernetesSecurityPercentWidget'; -export const QUERY_KEY_COUNT_WIDGET = 'kubernetesSecurityCountWidget'; -export const QUERY_KEY_CONTAINER_NAME_WIDGET = 'kubernetesSecurityContainerNameWidget'; -export const QUERY_KEY_PROCESS_EVENTS = 'kubernetesSecurityProcessEvents'; -export const QUERY_KEY_AGENT_ID = 'kubernetesSecurityAgentId'; - -// ECS fields -export const ENTRY_LEADER_INTERACTIVE = 'process.entry_leader.interactive'; -export const ENTRY_LEADER_USER_ID = 'process.entry_leader.user.id'; -export const ENTRY_LEADER_ENTITY_ID = 'process.entry_leader.entity_id'; - -export const ORCHESTRATOR_CLUSTER_ID = 'orchestrator.cluster.id'; -export const ORCHESTRATOR_CLUSTER_NAME = 'orchestrator.cluster.name'; -export const ORCHESTRATOR_NAMESPACE = 'orchestrator.namespace'; -export const CLOUD_INSTANCE_NAME = 'cloud.instance.name'; -export const ORCHESTRATOR_RESOURCE_ID = 'orchestrator.resource.name'; -export const CONTAINER_IMAGE_NAME = 'container.image.name'; - -export const COUNT_WIDGET_KEY_CLUSTERS = 'CountClustersWidget'; -export const COUNT_WIDGET_KEY_NAMESPACE = 'CountNamespaceWidgets'; -export const COUNT_WIDGET_KEY_NODES = 'CountNodesWidgets'; -export const COUNT_WIDGET_KEY_PODS = 'CountPodsWidgets'; -export const COUNT_WIDGET_KEY_CONTAINER_IMAGES = 'CountContainerImagesWidgets'; - -export const DEFAULT_FILTER = { - bool: { - should: [ - { - exists: { - field: ORCHESTRATOR_CLUSTER_ID, - }, - }, - ], - minimum_should_match: 1, - }, -}; - -export const DEFAULT_FILTER_QUERY = JSON.stringify({ - bool: { - must: [], - filter: [DEFAULT_FILTER], - should: [], - must_not: [], - }, -}); diff --git a/x-pack/solutions/security/plugins/kubernetes_security/common/translations.ts b/x-pack/solutions/security/plugins/kubernetes_security/common/translations.ts deleted file mode 100644 index 7ccf59c9f3bb5..0000000000000 --- a/x-pack/solutions/security/plugins/kubernetes_security/common/translations.ts +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { i18n } from '@kbn/i18n'; - -export const SEARCH_GROUP_CLUSTER = i18n.translate('xpack.kubernetesSecurity.searchGroup.cluster', { - defaultMessage: 'Cluster', -}); - -export const SEARCH_GROUP_GROUP_BY = i18n.translate( - 'xpack.kubernetesSecurity.searchGroup.groupBy', - { - defaultMessage: 'Group by', - } -); - -export const SEARCH_GROUP_SORT_BY = i18n.translate('xpack.kubernetesSecurity.searchGroup.sortBy', { - defaultMessage: 'Sort by', -}); - -export const TREE_VIEW_LOGICAL_VIEW = i18n.translate( - 'xpack.kubernetesSecurity.treeView.logicalView', - { - defaultMessage: 'Logical view', - } -); - -export const TREE_VIEW_INFRASTRUCTURE_VIEW = i18n.translate( - 'xpack.kubernetesSecurity.treeView.infrastructureView', - { - defaultMessage: 'Infrastructure view', - } -); - -export const TREE_VIEW_SWITCHER_LEGEND = i18n.translate( - 'xpack.kubernetesSecurity.treeView.switherLegend', - { - defaultMessage: 'You can switch between the Logical and Infrastructure view', - } -); - -export const TREE_NAVIGATION_LOADING = i18n.translate( - 'xpack.kubernetesSecurity.treeNavigation.loading', - { - defaultMessage: 'Loading', - } -); -export const TREE_NAVIGATION_EMPTY = i18n.translate( - 'xpack.kubernetesSecurity.treeNavigation.empty', - { - defaultMessage: 'No data available', - } -); -export const TREE_NAVIGATION_SHOW_MORE = (name: string) => - i18n.translate('xpack.kubernetesSecurity.treeNavigation.loadMore', { - values: { name }, - defaultMessage: 'Show more {name}', - }); - -export const TREE_NAVIGATION_COLLAPSE = i18n.translate( - 'xpack.kubernetesSecurity.treeNavigation.collapse', - { - defaultMessage: 'Collapse tree navigation', - } -); - -export const TREE_NAVIGATION_EXPAND = i18n.translate( - 'xpack.kubernetesSecurity.treeNavigation.expand', - { - defaultMessage: 'Expand tree navigation', - } -); - -export const CHART_TOGGLE_SHOW = i18n.translate('xpack.kubernetesSecurity.chartsToggle.show', { - defaultMessage: 'Show charts', -}); - -export const CHART_TOGGLE_HIDE = i18n.translate('xpack.kubernetesSecurity.chartsToggle.hide', { - defaultMessage: 'Hide charts', -}); - -export const COUNT_WIDGET_CLUSTERS = i18n.translate( - 'xpack.kubernetesSecurity.countWidget.clusters', - { - defaultMessage: 'Clusters', - } -); - -export const COUNT_WIDGET_NAMESPACE = i18n.translate( - 'xpack.kubernetesSecurity.countWidget.namespace', - { - defaultMessage: 'Namespace', - } -); - -export const COUNT_WIDGET_NODES = i18n.translate('xpack.kubernetesSecurity.countWidget.nodes', { - defaultMessage: 'Nodes', -}); - -export const COUNT_WIDGET_PODS = i18n.translate('xpack.kubernetesSecurity.countWidget.pods', { - defaultMessage: 'Pods', -}); - -export const COUNT_WIDGET_CONTAINER_IMAGES = i18n.translate( - 'xpack.kubernetesSecurity.countWidget.containerImages', - { - defaultMessage: 'Container images', - } -); - -export const CONTAINER_NAME_SESSION = i18n.translate( - 'xpack.kubernetesSecurity.containerNameWidget.containerImage', - { - defaultMessage: 'Container image', - } -); - -export const CONTAINER_NAME_SESSION_COUNT_COLUMN = i18n.translate( - 'xpack.kubernetesSecurity.containerNameWidget.containerImageCountColumn', - { - defaultMessage: 'Session count', - } -); - -export const CONTAINER_NAME_SESSION_ARIA_LABEL = i18n.translate( - 'xpack.kubernetesSecurity.containerNameWidget.containerImageAriaLabel', - { - defaultMessage: 'Container name session widget', - } -); diff --git a/x-pack/solutions/security/plugins/kubernetes_security/common/types/index.ts b/x-pack/solutions/security/plugins/kubernetes_security/common/types/index.ts deleted file mode 100644 index f38221e38bf2f..0000000000000 --- a/x-pack/solutions/security/plugins/kubernetes_security/common/types/index.ts +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -export type { - AggregateResult, - AggregateBucketPaginationResult, - MultiTermsAggregateGroupBy, - MultiTermsAggregateResult, - MultiTermsAggregateBucketPaginationResult, - MultiTermsBucket, -} from './latest'; - -import * as v1 from './v1'; -export type { v1 }; diff --git a/x-pack/solutions/security/plugins/kubernetes_security/common/types/v1.ts b/x-pack/solutions/security/plugins/kubernetes_security/common/types/v1.ts deleted file mode 100644 index 40e5c800245b0..0000000000000 --- a/x-pack/solutions/security/plugins/kubernetes_security/common/types/v1.ts +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -interface Aggregate { - key: string | number; - doc_count: number; -} - -interface Bucket extends Aggregate { - key_as_string?: string; - count_by_aggs?: { - value: number; - }; -} - -export interface AggregateResult { - buckets: Bucket[]; - hasNextPage: boolean; -} - -export interface AggregateBucketPaginationResult { - buckets: Bucket[]; - hasNextPage: boolean; -} - -export interface MultiTermsAggregateGroupBy { - field: string; - maybe?: string; -} - -interface MultiTermsAggregate { - key: Array; - doc_count: number; -} - -export interface MultiTermsBucket extends MultiTermsAggregate { - key_as_string?: string; - count_by_aggs?: { - value: number; - }; -} - -export interface MultiTermsAggregateResult { - buckets: Bucket[]; - hasNextPage: boolean; -} - -export interface MultiTermsAggregateBucketPaginationResult { - buckets: Bucket[]; - hasNextPage: boolean; -} diff --git a/x-pack/solutions/security/plugins/kubernetes_security/jest.config.js b/x-pack/solutions/security/plugins/kubernetes_security/jest.config.js deleted file mode 100644 index 0ab8dfc19a081..0000000000000 --- a/x-pack/solutions/security/plugins/kubernetes_security/jest.config.js +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -module.exports = { - preset: '@kbn/test', - rootDir: '../../../../..', - roots: ['/x-pack/solutions/security/plugins/kubernetes_security'], - coverageDirectory: - '/target/kibana-coverage/jest/x-pack/solutions/security/plugins/kubernetes_security', - coverageReporters: ['text', 'html'], - collectCoverageFrom: [ - '/x-pack/solutions/security/plugins/kubernetes_security/{common,public,server}/**/*.{ts,tsx}', - ], - setupFiles: ['jest-canvas-mock'], -}; diff --git a/x-pack/solutions/security/plugins/kubernetes_security/kibana.jsonc b/x-pack/solutions/security/plugins/kubernetes_security/kibana.jsonc deleted file mode 100644 index 793b5dcce3c6e..0000000000000 --- a/x-pack/solutions/security/plugins/kubernetes_security/kibana.jsonc +++ /dev/null @@ -1,23 +0,0 @@ -{ - "type": "plugin", - "id": "@kbn/kubernetes-security-plugin", - "owner": [ - "@elastic/kibana-cloud-security-posture" - ], - "group": "security", - "visibility": "private", - "plugin": { - "id": "kubernetesSecurity", - "browser": true, - "server": true, - "requiredPlugins": [ - "data", - "timelines", - "ruleRegistry", - "sessionView" - ], - "requiredBundles": [ - "kibanaReact" - ] - } -} \ No newline at end of file diff --git a/x-pack/solutions/security/plugins/kubernetes_security/package.json b/x-pack/solutions/security/plugins/kubernetes_security/package.json deleted file mode 100644 index b54e2d0381c93..0000000000000 --- a/x-pack/solutions/security/plugins/kubernetes_security/package.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "author": "Elastic", - "name": "@kbn/kubernetes-security-plugin", - "version": "1.0.0", - "private": true, - "license": "Elastic License 2.0", - "scripts": { - "test:jest": "node ../../../../scripts/jest", - "test:coverage": "node ../../../../scripts/jest --coverage" - } -} diff --git a/x-pack/solutions/security/plugins/kubernetes_security/public/components/charts_toggle/index.test.tsx b/x-pack/solutions/security/plugins/kubernetes_security/public/components/charts_toggle/index.test.tsx deleted file mode 100644 index e0d8249326d55..0000000000000 --- a/x-pack/solutions/security/plugins/kubernetes_security/public/components/charts_toggle/index.test.tsx +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React from 'react'; -import { AppContextTestRender, createAppRootMockRenderer } from '../../test'; -import { CHART_TOGGLE_SHOW, CHART_TOGGLE_HIDE } from '../../../common/translations'; -import { ChartsToggle, TOGGLE_TEST_ID } from '.'; - -describe('ChartsToggle component', () => { - let render: () => ReturnType; - let renderResult: ReturnType; - let mockedContext: AppContextTestRender; - const handleToggleHideCharts = jest.fn(); - - beforeEach(() => { - mockedContext = createAppRootMockRenderer(); - }); - - describe('When ChartsToggle is mounted', () => { - it('show "hide charts" text when shouldHideCharts is false', async () => { - renderResult = mockedContext.render( - - ); - - expect(renderResult.getByText(CHART_TOGGLE_HIDE)).toBeVisible(); - }); - it('show "show charts" text when shouldHideCharts is true', async () => { - renderResult = mockedContext.render( - - ); - - expect(renderResult.getByText(CHART_TOGGLE_SHOW)).toBeVisible(); - }); - it('shouldHideCharts defaults to false when not provided', async () => { - renderResult = mockedContext.render( - - ); - - expect(renderResult.getByText(CHART_TOGGLE_HIDE)).toBeVisible(); - }); - it('clicking the toggle fires the callback', async () => { - renderResult = mockedContext.render( - - ); - - renderResult.queryByTestId(TOGGLE_TEST_ID)?.click(); - expect(handleToggleHideCharts).toHaveBeenCalledTimes(1); - }); - }); -}); diff --git a/x-pack/solutions/security/plugins/kubernetes_security/public/components/charts_toggle/index.tsx b/x-pack/solutions/security/plugins/kubernetes_security/public/components/charts_toggle/index.tsx deleted file mode 100644 index d38d1fed3c7aa..0000000000000 --- a/x-pack/solutions/security/plugins/kubernetes_security/public/components/charts_toggle/index.tsx +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ -import React from 'react'; -import { EuiButtonEmpty } from '@elastic/eui'; -import { CHART_TOGGLE_SHOW, CHART_TOGGLE_HIDE } from '../../../common/translations'; - -export const TOGGLE_TEST_ID = 'kubernetesSecurity:chartToggle'; - -interface ChartsToggleDeps { - handleToggleHideCharts: () => void; - shouldHideCharts?: boolean; -} - -export const ChartsToggle = ({ - handleToggleHideCharts, - shouldHideCharts = false, -}: ChartsToggleDeps) => ( - - {shouldHideCharts ? CHART_TOGGLE_SHOW : CHART_TOGGLE_HIDE} - -); diff --git a/x-pack/solutions/security/plugins/kubernetes_security/public/components/container_name_widget/container_name_row.test.tsx b/x-pack/solutions/security/plugins/kubernetes_security/public/components/container_name_widget/container_name_row.test.tsx deleted file mode 100644 index 2abceaf0784af..0000000000000 --- a/x-pack/solutions/security/plugins/kubernetes_security/public/components/container_name_widget/container_name_row.test.tsx +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React from 'react'; -import { AppContextTestRender, createAppRootMockRenderer } from '../../test'; -import { ContainerNameRow } from './container_name_row'; -import { fireEvent } from '@testing-library/react'; - -const TEST_NAME = 'TEST ROW'; -const TEST_BUTTON_FILTER =
Filter In
; -const TEST_BUTTON_FILTER_OUT =
Filter Out
; -const TEST_BUTTON_COPY =
Copy
; - -describe('ContainerNameRow component with valid row', () => { - let renderResult: ReturnType; - const mockedContext = createAppRootMockRenderer(); - const render: () => ReturnType = () => - (renderResult = mockedContext.render( - - )); - - it('should show the row element as well as the pop up filter button when mouse hovers above it', async () => { - render(); - expect(renderResult.getByText(TEST_NAME)).toBeVisible(); - fireEvent.mouseOver(renderResult.queryByText(TEST_NAME)!); - expect(renderResult.getByText('Filter In')).toBeVisible(); - expect(renderResult.getByText('Filter Out')).toBeVisible(); - expect(renderResult.getByText('Copy')).toBeVisible(); - }); - - it('should show the row element but not the pop up filter button outside mouse hover', async () => { - render(); - expect(renderResult.getByText(TEST_NAME)).toBeVisible(); - expect(renderResult.queryByText('Filter In')).toBeFalsy(); - expect(renderResult.queryByText('Filter Out')).toBeFalsy(); - expect(renderResult.queryByText('Copy')).toBeFalsy(); - }); -}); diff --git a/x-pack/solutions/security/plugins/kubernetes_security/public/components/container_name_widget/container_name_row.tsx b/x-pack/solutions/security/plugins/kubernetes_security/public/components/container_name_widget/container_name_row.tsx deleted file mode 100644 index f282f3aedb698..0000000000000 --- a/x-pack/solutions/security/plugins/kubernetes_security/public/components/container_name_widget/container_name_row.tsx +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React, { ReactNode, useState } from 'react'; -import { EuiFlexItem, EuiText } from '@elastic/eui'; -import { useStyles } from './styles'; - -export interface ContainerNameRowDeps { - name: string; - filterButtonIn?: ReactNode; - filterButtonOut?: ReactNode; - copyToClipboardButton?: ReactNode; -} - -export const ROW_TEST_ID = 'kubernetesSecurity:containerNameSessionRow'; - -export const ContainerNameRow = ({ - name, - filterButtonIn, - filterButtonOut, - copyToClipboardButton, -}: ContainerNameRowDeps) => { - const [isHover, setIsHover] = useState(false); - - const styles = useStyles(); - - return ( - setIsHover(true)} - onMouseLeave={() => setIsHover(false)} - data-test-subj={ROW_TEST_ID} - css={styles.flexWidth} - > - -
{name}
- {isHover && ( -
- {filterButtonIn} - {filterButtonOut} - {copyToClipboardButton} -
- )} -
-
- ); -}; diff --git a/x-pack/solutions/security/plugins/kubernetes_security/public/components/container_name_widget/hooks.ts b/x-pack/solutions/security/plugins/kubernetes_security/public/components/container_name_widget/hooks.ts deleted file mode 100644 index 46ade9525e961..0000000000000 --- a/x-pack/solutions/security/plugins/kubernetes_security/public/components/container_name_widget/hooks.ts +++ /dev/null @@ -1,61 +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 { useInfiniteQuery } from '@tanstack/react-query'; -import { CoreStart } from '@kbn/core/public'; -import { useKibana } from '@kbn/kibana-react-plugin/public'; -import { - QUERY_KEY_CONTAINER_NAME_WIDGET, - AGGREGATE_ROUTE, - CURRENT_API_VERSION, -} from '../../../common/constants'; -import { AggregateResult } from '../../../common/types'; - -export const useFetchContainerNameData = ( - filterQuery: string, - widgetKey: string, - groupBy: string, - countBy?: string, - index?: string, - sortByCount?: string, - pageNumber?: number -) => { - const { http } = useKibana().services; - const cachingKeys = [ - QUERY_KEY_CONTAINER_NAME_WIDGET, - widgetKey, - filterQuery, - groupBy, - countBy, - sortByCount, - pageNumber, - ]; - const query = useInfiniteQuery( - cachingKeys, - async ({ pageParam = 0 }) => { - const res = await http.get(AGGREGATE_ROUTE, { - version: CURRENT_API_VERSION, - query: { - query: filterQuery, - groupBy, - countBy, - page: pageParam, - index, - sortByCount, - }, - }); - return res; - }, - { - refetchOnWindowFocus: false, - refetchOnMount: false, - refetchOnReconnect: false, - getNextPageParam: (lastPage, pages) => (lastPage.hasNextPage ? pages.length : undefined), - } - ); - return query; -}; diff --git a/x-pack/solutions/security/plugins/kubernetes_security/public/components/container_name_widget/index.test.tsx b/x-pack/solutions/security/plugins/kubernetes_security/public/components/container_name_widget/index.test.tsx deleted file mode 100644 index 8bc3b1634777a..0000000000000 --- a/x-pack/solutions/security/plugins/kubernetes_security/public/components/container_name_widget/index.test.tsx +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React from 'react'; -import { ENTRY_LEADER_ENTITY_ID, CONTAINER_IMAGE_NAME } from '../../../common/constants'; -import { AppContextTestRender, createAppRootMockRenderer } from '../../test'; -import { GlobalFilter } from '../../types'; -import { - ContainerNameWidget, - LOADING_TEST_ID, - NAME_COLUMN_TEST_ID, - COUNT_COLUMN_TEST_ID, - CONTAINER_NAME_TABLE_TEST_ID, -} from '.'; -import { useFetchContainerNameData } from './hooks'; -import { ROW_TEST_ID } from './container_name_row'; - -const TABLE_SORT_BUTTON_ID = 'tableHeaderSortButton'; - -const TITLE = 'Container image'; -const GLOBAL_FILTER: GlobalFilter = { - endDate: '2022-06-15T14:15:25.777Z', - filterQuery: '{"bool":{"must":[],"filter":[],"should":[],"must_not":[]}}', - startDate: '2022-05-15T14:15:25.777Z', -}; -const MOCK_DATA = { - pages: [ - { - buckets: [ - { key: 'Container A', doc_count: 295, count_by_aggs: { value: 1 } }, - { key: 'Container B', doc_count: 295, count_by_aggs: { value: 3 } }, - { key: 'Container C', doc_count: 295, count_by_aggs: { value: 2 } }, - { key: 'Container D', doc_count: 295, count_by_aggs: { value: 4 } }, - { key: 'Container E', doc_count: 295, count_by_aggs: { value: 1 } }, - { key: 'Container F', doc_count: 295, count_by_aggs: { value: 1 } }, - { key: 'Container G', doc_count: 295, count_by_aggs: { value: 0 } }, - { key: 'Container H', doc_count: 295, count_by_aggs: { value: 1 } }, - { key: 'Container J', doc_count: 295, count_by_aggs: { value: 1 } }, - { key: 'Container K', doc_count: 295, count_by_aggs: { value: 1 } }, - { key: 'Container L', doc_count: 295, count_by_aggs: { value: 5 } }, - ], - hasNextPage: true, - }, - { - buckets: [ - { key: 'Container A2', doc_count: 295, count_by_aggs: { value: 2 } }, - { key: 'Container B2', doc_count: 295, count_by_aggs: { value: 1 } }, - { key: 'Container C2', doc_count: 295, count_by_aggs: { value: 6 } }, - { key: 'Container D2', doc_count: 295, count_by_aggs: { value: 1 } }, - { key: 'Container E2', doc_count: 295, count_by_aggs: { value: 3 } }, - { key: 'Container F2', doc_count: 295, count_by_aggs: { value: 1 } }, - ], - hasNextPage: false, - }, - ], - pageParams: [undefined], -}; -const MOCK_DATA_VIEW_ID = 'dataViewId'; - -jest.mock('../../hooks/use_filter', () => ({ - useSetFilter: () => ({ - getFilterForValueButton: jest.fn(), - getFilterOutValueButton: jest.fn(), - getCopyButton: jest.fn(), - filterManager: {}, - }), -})); - -jest.mock('./hooks'); -const mockUseFetchData = useFetchContainerNameData as jest.Mock; - -describe('ContainerNameWidget component', () => { - let renderResult: ReturnType; - const mockedContext = createAppRootMockRenderer(); - const render: () => ReturnType = () => - (renderResult = mockedContext.render( - - )); - - describe('When ContainerNameWidget is mounted', () => { - describe('with data', () => { - beforeEach(() => { - mockUseFetchData.mockImplementation(() => ({ - data: MOCK_DATA, - isFetchingNextPage: true, - })); - }); - - it('should show the table, table title, table columns, sort button', async () => { - render(); - expect(renderResult.queryByTestId(CONTAINER_NAME_TABLE_TEST_ID)).toBeVisible(); - expect(renderResult.queryAllByTestId(TABLE_SORT_BUTTON_ID)).toHaveLength(1); - expect(renderResult.queryAllByTestId(NAME_COLUMN_TEST_ID)).toHaveLength(17); - expect(renderResult.queryAllByTestId(COUNT_COLUMN_TEST_ID)).toHaveLength(17); - }); - - it('should show data value names and value', async () => { - render(); - expect(renderResult.queryAllByTestId(ROW_TEST_ID)).toHaveLength(17); - }); - }); - - describe('without data ', () => { - it('should show no items found text', async () => { - mockUseFetchData.mockImplementation(() => ({ - data: undefined, - isFetchingNextPage: false, - })); - render(); - expect(renderResult.getByText(TITLE)).toBeVisible(); - expect(renderResult.getByText('No items found')).toBeVisible(); - expect(renderResult.getByTestId(CONTAINER_NAME_TABLE_TEST_ID)).toBeVisible(); - }); - }); - - describe('when loading data', () => { - it('should show progress bar', async () => { - mockUseFetchData.mockImplementation(() => ({ - data: MOCK_DATA, - isFetchingNextPage: false, - isLoading: true, - })); - render(); - expect(renderResult.getByTestId(LOADING_TEST_ID)).toBeVisible(); - }); - }); - }); -}); diff --git a/x-pack/solutions/security/plugins/kubernetes_security/public/components/container_name_widget/index.tsx b/x-pack/solutions/security/plugins/kubernetes_security/public/components/container_name_widget/index.tsx deleted file mode 100644 index 57d3e3288d613..0000000000000 --- a/x-pack/solutions/security/plugins/kubernetes_security/public/components/container_name_widget/index.tsx +++ /dev/null @@ -1,270 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React, { ReactNode, useMemo, useState, useRef, useCallback } from 'react'; -import { EuiBasicTable, EuiTableSortingType, EuiProgress, EuiBasicTableColumn } from '@elastic/eui'; -import { useStyles } from './styles'; -import { ContainerNameRow } from './container_name_row'; -import type { IndexPattern, GlobalFilter } from '../../types'; -import { useSetFilter, useScroll } from '../../hooks'; -import { addTimerangeAndDefaultFilterToQuery } from '../../utils/add_timerange_and_default_filter_to_query'; -import { useFetchContainerNameData } from './hooks'; -import { CONTAINER_IMAGE_NAME } from '../../../common/constants'; -import { - CONTAINER_NAME_SESSION, - CONTAINER_NAME_SESSION_COUNT_COLUMN, - CONTAINER_NAME_SESSION_ARIA_LABEL, -} from '../../../common/translations'; -import { addCommasToNumber } from '../../utils/add_commas_to_number'; - -export const LOADING_TEST_ID = 'kubernetesSecurity:containerNameWidgetLoading'; -export const NAME_COLUMN_TEST_ID = 'kubernetesSecurity:containerImageNameSessionNameColumn'; -export const COUNT_COLUMN_TEST_ID = 'kubernetesSecurity:containerImageNameSessionCountColumn'; -export const CONTAINER_NAME_TABLE_TEST_ID = 'kubernetesSecurity:containerNameSessionTable'; - -export interface ContainerNameWidgetDataValueMap { - key: string; - doc_count: number; - count_by_aggs: { - value: number; - }; -} - -export interface ContainerNameArrayDataValue { - name: string; - count: string; -} - -export interface ContainerNameWidgetDeps { - widgetKey: string; - indexPattern?: IndexPattern; - globalFilter: GlobalFilter; - groupedBy: string; - countBy?: string; - dataViewId?: string; -} - -interface FilterButtons { - filterForButtons: ReactNode[]; - filterOutButtons: ReactNode[]; -} - -interface CopyButtons { - copyButtons: ReactNode[]; -} - -export const ContainerNameWidget = ({ - dataViewId, - widgetKey, - indexPattern, - globalFilter, - groupedBy, - countBy, -}: ContainerNameWidgetDeps) => { - const [sortField, setSortField] = useState('count'); - const [sortDirection, setSortDirection] = useState('desc'); - const styles = useStyles(); - - const filterQueryWithTimeRange = useMemo(() => { - return addTimerangeAndDefaultFilterToQuery( - globalFilter.filterQuery, - globalFilter.startDate, - globalFilter.endDate - ); - }, [globalFilter.filterQuery, globalFilter.startDate, globalFilter.endDate]); - - const { data, fetchNextPage, isFetchingNextPage, isLoading } = useFetchContainerNameData( - filterQueryWithTimeRange, - widgetKey, - groupedBy, - countBy, - indexPattern?.title, - sortDirection - ); - - const onTableChange = useCallback(({ sort = {} }: any) => { - // @ts-ignore - const { field: sortingField, direction: sortingDirection } = sort; - - setSortField(sortingField); - setSortDirection(sortingDirection); - }, []); - - const sorting: EuiTableSortingType = { - sort: { - field: sortField as keyof ContainerNameArrayDataValue, - direction: sortDirection as 'desc' | 'asc', - }, - enableAllColumns: true, - }; - - const { getFilterForValueButton, getFilterOutValueButton, getCopyButton, filterManager } = - useSetFilter(); - const filterButtons = useMemo((): FilterButtons => { - const result: FilterButtons = { - filterForButtons: - data?.pages - ?.map((aggsData) => { - return aggsData?.buckets.map((aggData) => { - return getFilterForValueButton({ - field: CONTAINER_IMAGE_NAME, - filterManager, - size: 'xs', - onClick: () => {}, - onFilterAdded: () => {}, - ownFocus: false, - showTooltip: true, - value: aggData.key as string, - dataViewId, - }); - }); - }) - .flat() || [], - - filterOutButtons: - data?.pages - ?.map((aggsData) => { - return aggsData?.buckets.map((aggData) => { - return getFilterOutValueButton({ - field: CONTAINER_IMAGE_NAME, - filterManager, - size: 'xs', - onClick: () => {}, - onFilterAdded: () => {}, - ownFocus: false, - showTooltip: true, - value: aggData.key as string, - dataViewId, - }); - }); - }) - .flat() || [], - }; - return result; - }, [data?.pages, getFilterForValueButton, dataViewId, filterManager, getFilterOutValueButton]); - - const copyToClipboardButtons = useMemo((): CopyButtons => { - const result: CopyButtons = { - copyButtons: - data?.pages - ?.map((aggsData) => { - return aggsData?.buckets.map((aggData) => { - return getCopyButton({ - field: CONTAINER_IMAGE_NAME, - size: 'xs', - onClick: () => {}, - ownFocus: false, - showTooltip: true, - value: aggData.key as string, - }); - }); - }) - .flat() || [], - }; - return result; - }, [data, getCopyButton]); - - const containerNameArray = useMemo((): ContainerNameArrayDataValue[] => { - return data - ? data?.pages - ?.map((aggsData) => { - return aggsData?.buckets.map((aggData) => { - return { - name: aggData.key as string, - count: addCommasToNumber(aggData.count_by_aggs?.value ?? 0), - }; - }); - }) - .flat() - : []; - }, [data]); - - const columns = useMemo((): Array> => { - return [ - { - field: 'name', - name: CONTAINER_NAME_SESSION, - 'data-test-subj': NAME_COLUMN_TEST_ID, - render: (name: string) => { - const indexHelper = containerNameArray.findIndex((obj) => { - return obj.name === name; - }); - return ( - - ); - }, - align: 'left', - width: '67%', - sortable: false, - }, - { - field: 'count', - name: CONTAINER_NAME_SESSION_COUNT_COLUMN, - width: '33%', - 'data-test-subj': COUNT_COLUMN_TEST_ID, - render: (count: number) => { - return {count}; - }, - sortable: true, - align: 'right', - }, - ]; - }, [ - filterButtons.filterForButtons, - filterButtons.filterOutButtons, - copyToClipboardButtons.copyButtons, - containerNameArray, - styles, - ]); - - const scrollerRef = useRef(null); - useScroll({ - div: scrollerRef.current, - handler: (pos: number, endReached: boolean) => { - if (!isFetchingNextPage && endReached) { - fetchNextPage(); - } - }, - }); - - const cellProps = useMemo(() => { - return { - css: styles.cellPad, - }; - }, [styles.cellPad]); - - return ( -
- {isLoading && ( - - )} - -
- ); -}; diff --git a/x-pack/solutions/security/plugins/kubernetes_security/public/components/container_name_widget/styles.ts b/x-pack/solutions/security/plugins/kubernetes_security/public/components/container_name_widget/styles.ts deleted file mode 100644 index 1ebe6347994ee..0000000000000 --- a/x-pack/solutions/security/plugins/kubernetes_security/public/components/container_name_widget/styles.ts +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { useMemo } from 'react'; -import { CSSObject } from '@emotion/react'; -import { transparentize } from '@elastic/eui'; -import { useEuiTheme } from '../../hooks'; - -export const useStyles = () => { - const { euiTheme } = useEuiTheme(); - - const cached = useMemo(() => { - const { size, colors } = euiTheme; - - const container: CSSObject = { - paddingTop: size.s, - paddingBottom: size.s, - paddingRight: size.base, - paddingLeft: size.base, - border: euiTheme.border.thin, - borderRadius: euiTheme.border.radius.medium, - overflow: 'auto', - height: '228px', - position: 'relative', - marginBottom: size.l, - }; - - const dataInfo: CSSObject = { - display: 'flex', - alignItems: 'center', - height: size.base, - position: 'relative', - }; - - const filters: CSSObject = { - marginLeft: size.s, - position: 'absolute', - left: '50%', - backgroundColor: colors.emptyShade, - borderRadius: euiTheme.border.radius.small, - border: euiTheme.border.thin, - bottom: '-25px', - boxShadow: `0 ${size.xs} ${size.xs} ${transparentize(euiTheme.colors.shadow, 0.04)}`, - display: 'flex', - zIndex: 1, - }; - - const countValue: CSSObject = { - fontSize: size.m, - }; - - const truncate: CSSObject = { - width: '100%', - overflow: 'hidden', - whiteSpace: 'nowrap', - textOverflow: 'ellipsis', - }; - - const flexWidth: CSSObject = { - width: '100%', - }; - - const cellPad: CSSObject = { - paddingBottom: '5px', - paddingTop: '5px', - }; - - return { - container, - dataInfo, - filters, - countValue, - truncate, - flexWidth, - cellPad, - }; - }, [euiTheme]); - - return cached; -}; diff --git a/x-pack/solutions/security/plugins/kubernetes_security/public/components/count_widget/helpers.test.ts b/x-pack/solutions/security/plugins/kubernetes_security/public/components/count_widget/helpers.test.ts deleted file mode 100644 index f3741e38d7947..0000000000000 --- a/x-pack/solutions/security/plugins/kubernetes_security/public/components/count_widget/helpers.test.ts +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { addResourceTypeToFilterQuery, numberFormatter } from './helpers'; - -const TEST_DATA_ARRAY: number[] = [ - 32, - 2200, - 999232, - 1310000, - 999999999, - 999999999999, - 1230000000000, - Infinity, - NaN, - -1, - -Infinity, - 1e15 - 1, -]; - -const TEST_QUERY = `{"bool":{"must":[],"filter":[],"should":[],"must_not":[]}}`; - -const RESULT_QUERY_NODE = - '{"bool":{"must":[],"filter":[{"bool":{"should":[{"match_phrase":{"orchestrator.resource.type":"node"}}]}}],"should":[],"must_not":[]}}'; -const RESULT_QUERY_POD = - '{"bool":{"must":[],"filter":[{"bool":{"should":[{"match_phrase":{"orchestrator.resource.type":"pod"}}]}}],"should":[],"must_not":[]}}'; - -describe('Testing Helper functions', () => { - it('Testing numberFormatter helper function', () => { - expect(numberFormatter(TEST_DATA_ARRAY[0])).toBe('32'); - expect(numberFormatter(TEST_DATA_ARRAY[1])).toBe('2K'); - expect(numberFormatter(TEST_DATA_ARRAY[2])).toBe('999K'); - expect(numberFormatter(TEST_DATA_ARRAY[3])).toBe('1.3M'); - expect(numberFormatter(TEST_DATA_ARRAY[4])).toBe('999M'); - expect(numberFormatter(TEST_DATA_ARRAY[5])).toBe('999B'); - expect(numberFormatter(TEST_DATA_ARRAY[6])).toBe('1.2T'); - expect(numberFormatter(TEST_DATA_ARRAY[7])).toBe('NaN'); - expect(numberFormatter(TEST_DATA_ARRAY[8])).toBe('NaN'); - expect(numberFormatter(TEST_DATA_ARRAY[9])).toBe('NaN'); - expect(numberFormatter(TEST_DATA_ARRAY[10])).toBe('NaN'); - expect(numberFormatter(TEST_DATA_ARRAY[11])).toBe('999T'); - }); - - it('Testing addResourceTypeToFilterQuery helper function', () => { - expect(addResourceTypeToFilterQuery(TEST_QUERY, 'node')).toBe(RESULT_QUERY_NODE); - expect(addResourceTypeToFilterQuery(TEST_QUERY, 'pod')).toBe(RESULT_QUERY_POD); - }); -}); diff --git a/x-pack/solutions/security/plugins/kubernetes_security/public/components/count_widget/helpers.ts b/x-pack/solutions/security/plugins/kubernetes_security/public/components/count_widget/helpers.ts deleted file mode 100644 index 65974d8ac1eb9..0000000000000 --- a/x-pack/solutions/security/plugins/kubernetes_security/public/components/count_widget/helpers.ts +++ /dev/null @@ -1,99 +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 { DEFAULT_FILTER_QUERY } from '../../../common/constants'; -import { QueryDslQueryContainerBool } from '../../types'; - -export const addResourceTypeToFilterQuery = ( - filterQuery: string | undefined, - resourceType: 'node' | 'pod' -) => { - let validFilterQuery = DEFAULT_FILTER_QUERY; - - try { - const parsedFilterQuery: QueryDslQueryContainerBool = JSON.parse(filterQuery || '{}'); - if (!(parsedFilterQuery?.bool?.filter && Array.isArray(parsedFilterQuery.bool.filter))) { - throw new Error('Invalid filter query'); - } - parsedFilterQuery.bool.filter.push({ - bool: { - should: [ - { - match_phrase: { - 'orchestrator.resource.type': resourceType, - }, - }, - ], - }, - }); - validFilterQuery = JSON.stringify(parsedFilterQuery); - } catch { - // no-op since validFilterQuery is initialized to be DEFAULT_FILTER_QUERY - } - - return validFilterQuery; -}; - -export const numberFormatter = (num: number) => { - if (Number.isFinite(num) && num >= 0) { - if (num >= 1e15 - 1) { - const newNum = Math.floor(num / 1e12) * 1e12; - return new Intl.NumberFormat('en-GB', { - // @ts-ignore - notation: 'compact', - compactDisplay: 'short', - }).format(newNum); - } - // Trillion - if (num >= 1e12 - 1) { - const newNum = Math.floor(num / 1e9) * 1e9; - return new Intl.NumberFormat('en-GB', { - // @ts-ignore - notation: 'compact', - compactDisplay: 'short', - }).format(newNum); - } - // Billion - if (num >= 1e9 - 1) { - const newNum = Math.floor(num / 1e6) * 1e6; - return new Intl.NumberFormat('en-GB', { - // @ts-ignore - notation: 'compact', - compactDisplay: 'short', - }).format(newNum); - } - // Hundreds Thousands - if (num >= 1e6 - 1) { - const newNum = Math.floor(num / 1000) * 1000; - return new Intl.NumberFormat('en-GB', { - // @ts-ignore - notation: 'compact', - compactDisplay: 'short', - }).format(newNum); - } - // Thousands - if (num >= 1e3 - 1) { - const newNum = Math.floor(num / 1000) * 1000; - return new Intl.NumberFormat('en-GB', { - // @ts-ignore - notation: 'compact', - compactDisplay: 'short', - }).format(newNum); - } - - if (num < 1e3) { - return num.toString(); - } - - return new Intl.NumberFormat('en-GB', { - // @ts-ignore - notation: 'compact', - compactDisplay: 'short', - }).format(num); - } - return 'NaN'; -}; diff --git a/x-pack/solutions/security/plugins/kubernetes_security/public/components/count_widget/hooks.ts b/x-pack/solutions/security/plugins/kubernetes_security/public/components/count_widget/hooks.ts deleted file mode 100644 index f935cf34f182a..0000000000000 --- a/x-pack/solutions/security/plugins/kubernetes_security/public/components/count_widget/hooks.ts +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { useInfiniteQuery } from '@tanstack/react-query'; -import { CoreStart } from '@kbn/core/public'; -import { useKibana } from '@kbn/kibana-react-plugin/public'; -import { - QUERY_KEY_COUNT_WIDGET, - COUNT_ROUTE, - CURRENT_API_VERSION, -} from '../../../common/constants'; - -export const useFetchCountWidgetData = ( - widgetKey: string, - filterQuery: string, - groupedBy: string, - index?: string -) => { - const { http } = useKibana().services; - const cachingKeys = [QUERY_KEY_COUNT_WIDGET, widgetKey, filterQuery, groupedBy, index]; - - const query = useInfiniteQuery( - cachingKeys, - async () => { - const res = await http.get(COUNT_ROUTE, { - version: CURRENT_API_VERSION, - query: { - query: filterQuery, - field: groupedBy, - index, - }, - }); - - return res; - }, - { - refetchOnWindowFocus: false, - refetchOnMount: false, - refetchOnReconnect: false, - } - ); - - return query; -}; diff --git a/x-pack/solutions/security/plugins/kubernetes_security/public/components/count_widget/index.test.tsx b/x-pack/solutions/security/plugins/kubernetes_security/public/components/count_widget/index.test.tsx deleted file mode 100644 index d3230a33f203e..0000000000000 --- a/x-pack/solutions/security/plugins/kubernetes_security/public/components/count_widget/index.test.tsx +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React from 'react'; -import { AppContextTestRender, createAppRootMockRenderer } from '../../test'; -import { GlobalFilter } from '../../types'; -import { CountWidget, LOADING_TEST_ID, TOOLTIP_TEST_ID, VALUE_TEST_ID } from '.'; -import { useFetchCountWidgetData } from './hooks'; -import { fireEvent, waitFor } from '@testing-library/react'; - -const TITLE = 'Count Widget Title'; -const GLOBAL_FILTER: GlobalFilter = { - endDate: '2022-06-15T14:15:25.777Z', - filterQuery: '{"bool":{"must":[],"filter":[],"should":[],"must_not":[]}}', - startDate: '2022-05-15T14:15:25.777Z', -}; - -const MOCK_DATA_NORMAL = { - pages: [12], -}; - -const MOCK_DATA_MILLION = { - pages: [1210000], -}; - -const MOCK_DATA_THOUSAND = { - pages: [5236], -}; - -const MOCK_DATA_CLOSE_TO_MILLION = { - pages: [999999], -}; - -jest.mock('../../hooks/use_filter', () => ({ - useSetFilter: () => ({ - getFilterForValueButton: jest.fn(), - getFilterOutValueButton: jest.fn(), - filterManager: {}, - }), -})); - -jest.mock('./hooks'); -const mockUseFetchData = useFetchCountWidgetData as jest.Mock; - -describe('CountWidget component', () => { - let renderResult: ReturnType; - const mockedContext = createAppRootMockRenderer(); - const render: () => ReturnType = () => - (renderResult = mockedContext.render( - - )); - - describe('When PercentWidget is mounted', () => { - describe('with small amount of data (less than 1000)', () => { - beforeEach(() => { - mockUseFetchData.mockImplementation(() => ({ - data: MOCK_DATA_NORMAL, - isLoading: false, - })); - }); - - it('should show title and count numbers correctly', async () => { - render(); - - expect(renderResult.getByText(TITLE)).toBeVisible(); - expect(renderResult.getByText('12')).toBeVisible(); - }); - }); - - describe('with moderate amount of data (more than 1000 less than 1 million)', () => { - beforeEach(() => { - mockUseFetchData.mockImplementation(() => ({ - data: MOCK_DATA_THOUSAND, - isLoading: false, - })); - }); - - it('should show title and count numbers (formatted thousands with comma)correctly', async () => { - render(); - - expect(renderResult.getByText(TITLE)).toBeVisible(); - expect(renderResult.getByText('5K')).toBeVisible(); - }); - }); - - describe('with huge amount of data (more than 1 million)', () => { - it('should show title and count numbers (formatted remove the zeroes and add M) correctly', async () => { - mockUseFetchData.mockImplementation(() => ({ - data: MOCK_DATA_MILLION, - isLoading: false, - })); - render(); - - expect(renderResult.getByText(TITLE)).toBeVisible(); - expect(renderResult.getByText('1.2M')).toBeVisible(); - }); - }); - - describe('with huge amount of data (Very close to 1 million)', () => { - it('should show title and count numbers (formatted remove the zeroes and add K) correctly', async () => { - mockUseFetchData.mockImplementation(() => ({ - data: MOCK_DATA_CLOSE_TO_MILLION, - isLoading: false, - })); - render(); - - expect(renderResult.getByText(TITLE)).toBeVisible(); - expect(renderResult.getByText('999K')).toBeVisible(); - }); - }); - - describe('When data is loading', () => { - it('should show the loading icon', async () => { - mockUseFetchData.mockImplementation(() => ({ - data: MOCK_DATA_MILLION, - isLoading: true, - })); - render(); - - expect(renderResult.getAllByTestId(LOADING_TEST_ID)).toHaveLength(1); - }); - }); - - describe('Testing Tooltips', () => { - it('Tooltips show the real count value (not formatted)', async () => { - mockUseFetchData.mockImplementation(() => ({ - data: MOCK_DATA_THOUSAND, - isLoading: false, - })); - render(); - fireEvent.mouseOver(renderResult.getByTestId(VALUE_TEST_ID)); - await waitFor(() => renderResult.getByTestId(TOOLTIP_TEST_ID)); - expect(renderResult.queryByText('5,236')).toBeTruthy(); - }); - }); - }); -}); diff --git a/x-pack/solutions/security/plugins/kubernetes_security/public/components/count_widget/index.tsx b/x-pack/solutions/security/plugins/kubernetes_security/public/components/count_widget/index.tsx deleted file mode 100644 index a6b1638efb002..0000000000000 --- a/x-pack/solutions/security/plugins/kubernetes_security/public/components/count_widget/index.tsx +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React, { useMemo } from 'react'; -import { EuiText, EuiLoadingSpinner, EuiToolTip } from '@elastic/eui'; -import { useStyles } from './styles'; -import type { IndexPattern, GlobalFilter } from '../../types'; -import { addCommasToNumber } from '../../utils/add_commas_to_number'; -import { addTimerangeAndDefaultFilterToQuery } from '../../utils/add_timerange_and_default_filter_to_query'; -import { useFetchCountWidgetData } from './hooks'; -import { addResourceTypeToFilterQuery, numberFormatter } from './helpers'; -import { COUNT_WIDGET_KEY_PODS } from '../../../common/constants'; - -export const LOADING_TEST_ID = 'kubernetesSecurity:countWidgetLoading'; -export const TOOLTIP_TEST_ID = 'kubernetesSecurity:countWidgetTooltip'; -export const VALUE_TEST_ID = 'kubernetesSecurity:countWidgetValue'; - -export interface CountWidgetDeps { - title: string; - widgetKey: string; - indexPattern?: IndexPattern; - globalFilter: GlobalFilter; - groupedBy: string; -} - -export const CountWidget = ({ - title, - widgetKey, - indexPattern, - globalFilter, - groupedBy, -}: CountWidgetDeps) => { - const styles = useStyles(); - - const filterQueryWithTimeRange = useMemo(() => { - let globalFilterModified = globalFilter.filterQuery; - - if (widgetKey === COUNT_WIDGET_KEY_PODS) { - globalFilterModified = addResourceTypeToFilterQuery(globalFilter.filterQuery, 'pod'); - } - return addTimerangeAndDefaultFilterToQuery( - globalFilterModified, - globalFilter.startDate, - globalFilter.endDate - ); - }, [globalFilter.filterQuery, globalFilter.startDate, globalFilter.endDate, widgetKey]); - - const { data, isLoading } = useFetchCountWidgetData( - widgetKey, - filterQueryWithTimeRange, - groupedBy, - indexPattern?.title - ); - - const countValue = useMemo((): number => { - return data ? data?.pages[0] : 0; - }, [data]); - - const formattedNumber = useMemo((): string => { - return numberFormatter(countValue); - }, [countValue]); - - return ( -
-
{title}
- - - {isLoading ? ( - - ) : ( - formattedNumber - )} - - -
- ); -}; diff --git a/x-pack/solutions/security/plugins/kubernetes_security/public/components/count_widget/styles.ts b/x-pack/solutions/security/plugins/kubernetes_security/public/components/count_widget/styles.ts deleted file mode 100644 index c5d3adf43d838..0000000000000 --- a/x-pack/solutions/security/plugins/kubernetes_security/public/components/count_widget/styles.ts +++ /dev/null @@ -1,65 +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 { useMemo } from 'react'; -import { CSSObject } from '@emotion/react'; -import { useEuiTheme } from '../../hooks'; - -export const useStyles = () => { - const { euiTheme } = useEuiTheme(); - - const cached = useMemo(() => { - const { size, font, border } = euiTheme; - - const container: CSSObject = { - padding: size.base, - border: border.thin, - borderRadius: border.radius.medium, - overflow: 'auto', - position: 'relative', - height: '100%', - }; - - const title: CSSObject = { - marginBottom: size.s, - fontSize: size.m, - fontWeight: font.weight.bold, - whiteSpace: 'nowrap', - }; - - const dataInfo: CSSObject = { - fontSize: `calc(${size.l} - ${size.xxs})`, - lineHeight: size.l, - fontWeight: font.weight.bold, - }; - - const dataValue: CSSObject = { - fontWeight: font.weight.semiBold, - marginLeft: 'auto', - }; - - const filters: CSSObject = { - marginLeft: size.s, - }; - - const loadingSpinner: CSSObject = { - alignItems: 'center', - margin: `${size.xs} auto ${size.xl} auto`, - }; - - return { - container, - title, - dataInfo, - dataValue, - filters, - loadingSpinner, - }; - }, [euiTheme]); - - return cached; -}; diff --git a/x-pack/solutions/security/plugins/kubernetes_security/public/components/kubernetes_security_routes/index.test.tsx b/x-pack/solutions/security/plugins/kubernetes_security/public/components/kubernetes_security_routes/index.test.tsx deleted file mode 100644 index 2846cf828c961..0000000000000 --- a/x-pack/solutions/security/plugins/kubernetes_security/public/components/kubernetes_security_routes/index.test.tsx +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React from 'react'; -// eslint-disable-next-line @kbn/eslint/module_migration -import { MemoryRouterProps } from 'react-router'; -import { screen } from '@testing-library/react'; -import { MemoryRouter } from 'react-router-dom'; -import { KubernetesSecurityRoutes } from '.'; -import { createAppRootMockRenderer } from '../../test'; - -jest.mock('../percent_widget', () => ({ - PercentWidget: () =>
{'Mock percent widget'}
, -})); - -jest.mock('../../hooks/use_last_updated', () => ({ - useLastUpdated: () =>
{'Mock updated now'}
, -})); - -jest.mock('../count_widget', () => ({ - CountWidget: () =>
{'Mock count widget'}
, -})); - -jest.mock('../container_name_widget', () => ({ - ContainerNameWidget: () =>
{'Mock Container Name widget'}
, -})); - -const dataViewId = 'dataViewId'; - -const renderWithRouter = ( - initialEntries: MemoryRouterProps['initialEntries'] = ['/kubernetes'] -) => { - const useGlobalFullScreen = jest.fn(); - useGlobalFullScreen.mockImplementation(() => { - return { globalFullScreen: false }; - }); - const useSourcererDataView = jest.fn(); - useSourcererDataView.mockImplementation(() => { - return { - indexPattern: { - fields: [ - { - aggregatable: false, - esTypes: [], - name: '_id', - searchable: true, - type: 'string', - }, - ], - title: '.mock-index-pattern', - }, - }; - }); - const mockedContext = createAppRootMockRenderer(); - return mockedContext.render( - - {'Mock filters'}
} - globalFilter={{ - filterQuery: '{"bool":{"must":[],"filter":[],"should":[],"must_not":[]}}', - startDate: '2022-03-08T18:52:15.532Z', - endDate: '2022-06-09T17:52:15.532Z', - }} - renderSessionsView={jest.fn()} - dataViewId={dataViewId} - /> - - ); -}; - -describe('Kubernetes security routes', () => { - it('navigates to the kubernetes page', () => { - renderWithRouter(); - expect(screen.getAllByText('Mock count widget')).toHaveLength(5); - expect(screen.getAllByText('Mock percent widget')).toHaveLength(2); - expect(screen.getAllByText('Mock updated now')).toHaveLength(1); - }); -}); diff --git a/x-pack/solutions/security/plugins/kubernetes_security/public/components/kubernetes_security_routes/index.tsx b/x-pack/solutions/security/plugins/kubernetes_security/public/components/kubernetes_security_routes/index.tsx deleted file mode 100644 index 2cbffe489fd7d..0000000000000 --- a/x-pack/solutions/security/plugins/kubernetes_security/public/components/kubernetes_security_routes/index.tsx +++ /dev/null @@ -1,288 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React, { useCallback } from 'react'; -import { Routes, Route } from '@kbn/shared-ux-router'; -import useLocalStorage from 'react-use/lib/useLocalStorage'; -import { EuiFlexGroup, EuiFlexItem, EuiIconTip, EuiText, EuiTitle } from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; -import { FormattedMessage } from '@kbn/i18n-react'; -import { euiThemeVars } from '@kbn/ui-theme'; -import { - KUBERNETES_PATH, - KUBERNETES_TITLE, - LOCAL_STORAGE_HIDE_WIDGETS_KEY, - ENTRY_LEADER_INTERACTIVE, - ENTRY_LEADER_USER_ID, - ENTRY_LEADER_ENTITY_ID, - ORCHESTRATOR_CLUSTER_ID, - ORCHESTRATOR_NAMESPACE, - ORCHESTRATOR_RESOURCE_ID, - CONTAINER_IMAGE_NAME, - CLOUD_INSTANCE_NAME, - COUNT_WIDGET_KEY_CLUSTERS, - COUNT_WIDGET_KEY_NAMESPACE, - COUNT_WIDGET_KEY_NODES, - COUNT_WIDGET_KEY_CONTAINER_IMAGES, -} from '../../../common/constants'; -import { PercentWidget } from '../percent_widget'; -import { CountWidget } from '../count_widget'; -import { KubernetesSecurityDeps } from '../../types'; -import { AggregateResult } from '../../../common/types'; -import { useLastUpdated } from '../../hooks'; -import { useStyles } from './styles'; -import { TreeViewContainer } from '../tree_view_container'; -import { ChartsToggle } from '../charts_toggle'; -import { - COUNT_WIDGET_CLUSTERS, - COUNT_WIDGET_NAMESPACE, - COUNT_WIDGET_NODES, - COUNT_WIDGET_PODS, - COUNT_WIDGET_CONTAINER_IMAGES, -} from '../../../common/translations'; -import { ContainerNameWidget } from '../container_name_widget'; - -const KubernetesSecurityRoutesComponent = ({ - dataViewId, - filter, - indexPattern, - globalFilter, - renderSessionsView, -}: KubernetesSecurityDeps) => { - const [shouldHideCharts, setShouldHideCharts] = useLocalStorage( - LOCAL_STORAGE_HIDE_WIDGETS_KEY, - false - ); - const styles = useStyles(); - const lastUpdated = useLastUpdated(globalFilter); - const onReduceInteractiveAggs = useCallback( - (result: AggregateResult): Record => - result.buckets.reduce((groupedByKeyValue, aggregate) => { - groupedByKeyValue[aggregate.key_as_string || (aggregate.key.toString() as string)] = - aggregate.count_by_aggs?.value ?? 0; - return groupedByKeyValue; - }, {} as Record), - [] - ); - - const onReduceRootAggs = useCallback( - (result: AggregateResult): Record => - result.buckets.reduce((groupedByKeyValue, aggregate) => { - if (aggregate.key.toString() === '0') { - groupedByKeyValue[aggregate.key] = aggregate.count_by_aggs?.value ?? 0; - } else { - groupedByKeyValue.nonRoot = - (groupedByKeyValue.nonRoot || 0) + (aggregate.count_by_aggs?.value ?? 0); - } - return groupedByKeyValue; - }, {} as Record), - [] - ); - - const handleToggleHideCharts = useCallback(() => { - setShouldHideCharts(!shouldHideCharts); - }, [setShouldHideCharts, shouldHideCharts]); - - return ( - - - {filter} - - - -

{KUBERNETES_TITLE}

-
-
- -
{lastUpdated}
- -
-
- {!shouldHideCharts && ( - <> - - - - - - - - - - - - - - - - - - - - - - - - - - - } - /> - - } - widgetKey="sessionsPercentage" - indexPattern={indexPattern} - globalFilter={globalFilter} - dataValueMap={{ - true: { - name: i18n.translate( - 'xpack.kubernetesSecurity.sessionChart.interactive', - { - defaultMessage: 'Interactive', - } - ), - fieldName: ENTRY_LEADER_INTERACTIVE, - color: euiThemeVars.euiColorVis0, - }, - false: { - name: i18n.translate( - 'xpack.kubernetesSecurity.sessionChart.nonInteractive', - { - defaultMessage: 'Non-interactive', - } - ), - fieldName: ENTRY_LEADER_INTERACTIVE, - color: euiThemeVars.euiColorVis1, - shouldHideFilter: true, - }, - }} - groupedBy={ENTRY_LEADER_INTERACTIVE} - countBy={ENTRY_LEADER_ENTITY_ID} - onReduce={onReduceInteractiveAggs} - /> - - - - - - - - } - /> - - } - widgetKey="rootLoginPercentage" - indexPattern={indexPattern} - globalFilter={globalFilter} - dataValueMap={{ - '0': { - name: i18n.translate('xpack.kubernetesSecurity.entryUserChart.root', { - defaultMessage: 'Root', - }), - fieldName: ENTRY_LEADER_USER_ID, - color: euiThemeVars.euiColorVis2, - }, - nonRoot: { - name: i18n.translate('xpack.kubernetesSecurity.entryUserChart.nonRoot', { - defaultMessage: 'Non-root', - }), - fieldName: ENTRY_LEADER_USER_ID, - color: euiThemeVars.euiColorVis3, - shouldHideFilter: true, - }, - }} - dataViewId={dataViewId} - groupedBy={ENTRY_LEADER_USER_ID} - countBy={ENTRY_LEADER_ENTITY_ID} - onReduce={onReduceRootAggs} - /> - - - - - - - - - )} - -
-
- ); -}; - -export const KubernetesSecurityRoutes = React.memo(KubernetesSecurityRoutesComponent); -// eslint-disable-next-line import/no-default-export -export { KubernetesSecurityRoutes as default }; diff --git a/x-pack/solutions/security/plugins/kubernetes_security/public/components/kubernetes_security_routes/styles.ts b/x-pack/solutions/security/plugins/kubernetes_security/public/components/kubernetes_security_routes/styles.ts deleted file mode 100644 index 948f680312b69..0000000000000 --- a/x-pack/solutions/security/plugins/kubernetes_security/public/components/kubernetes_security_routes/styles.ts +++ /dev/null @@ -1,111 +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 { useMemo } from 'react'; -import type { CSSObject } from '@emotion/react'; -import { useEuiTheme } from '../../hooks'; - -export const useStyles = () => { - const { euiTheme } = useEuiTheme(); - - const cached = useMemo(() => { - const { size, font } = euiTheme; - - const titleSection: CSSObject = { - marginBottom: size.l, - }; - - const titleText: CSSObject = { - display: 'flex', - alignItems: 'center', - }; - - const titleActions: CSSObject = { - marginLeft: 'auto', - flexDirection: 'row', - alignItems: 'center', - }; - - const updatedAt: CSSObject = { - marginRight: size.m, - }; - - const widgetBadge: CSSObject = { - position: 'absolute', - bottom: size.base, - left: size.base, - width: `calc(100% - ${size.xl})`, - fontSize: size.m, - lineHeight: '18px', - padding: `${size.xs} ${size.s}`, - display: 'flex', - }; - - const treeViewContainer: CSSObject = { - position: 'relative', - border: euiTheme.border.thin, - borderRadius: euiTheme.border.radius.medium, - padding: size.base, - height: '500px', - }; - - const widgetsBottomSpacing: CSSObject = { - marginBottom: size.m, - }; - - const countWidgetsGroup: CSSObject = { - ...widgetsBottomSpacing, - flexWrap: 'wrap', - [`@media (max-width:${euiTheme.breakpoint.xl}px)`]: { - flexDirection: 'column', - }, - }; - - const leftWidgetsGroup: CSSObject = { - [`@media (max-width:${euiTheme.breakpoint.xl}px)`]: { - marginBottom: '0 !important', - }, - minWidth: `calc(70% - ${size.xxxl})`, - }; - - const rightWidgetsGroup: CSSObject = { - [`@media (max-width:${euiTheme.breakpoint.xl}px)`]: { - marginTop: '0 !important', - }, - minWidth: '30%', - }; - - const percentageChartTitle: CSSObject = { - marginRight: size.xs, - display: 'inline', - fontWeight: font.weight.bold, - }; - - const widgetsGroup: CSSObject = { - [`@media (max-width:${euiTheme.breakpoint.xl}px)`]: { - flexDirection: 'column', - }, - }; - - return { - titleSection, - titleText, - titleActions, - updatedAt, - widgetBadge, - treeViewContainer, - countWidgetsGroup, - leftWidgetsGroup, - rightWidgetsGroup, - widgetsBottomSpacing, - percentageChartTitle, - widgetsGroup, - }; - }, [euiTheme]); - - return cached; -}; diff --git a/x-pack/solutions/security/plugins/kubernetes_security/public/components/percent_widget/hooks.ts b/x-pack/solutions/security/plugins/kubernetes_security/public/components/percent_widget/hooks.ts deleted file mode 100644 index dfbba393ffcb4..0000000000000 --- a/x-pack/solutions/security/plugins/kubernetes_security/public/components/percent_widget/hooks.ts +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ -import { useQuery } from '@tanstack/react-query'; -import { CoreStart } from '@kbn/core/public'; -import { useKibana } from '@kbn/kibana-react-plugin/public'; -import { - QUERY_KEY_PERCENT_WIDGET, - AGGREGATE_ROUTE, - CURRENT_API_VERSION, -} from '../../../common/constants'; -import { AggregateResult } from '../../../common/types'; - -export const useFetchPercentWidgetData = ( - onReduce: (result: AggregateResult) => Record, - filterQuery: string, - widgetKey: string, - groupBy: string, - countBy?: string, - index?: string -) => { - const { http } = useKibana().services; - const cachingKeys = [QUERY_KEY_PERCENT_WIDGET, widgetKey, filterQuery, groupBy, countBy, index]; - const query = useQuery(cachingKeys, async (): Promise> => { - const res = await http.get(AGGREGATE_ROUTE, { - version: CURRENT_API_VERSION, - query: { - query: filterQuery, - groupBy, - countBy, - page: 0, - index, - }, - }); - - return onReduce(res); - }); - - return query; -}; diff --git a/x-pack/solutions/security/plugins/kubernetes_security/public/components/percent_widget/index.test.tsx b/x-pack/solutions/security/plugins/kubernetes_security/public/components/percent_widget/index.test.tsx deleted file mode 100644 index bb74896b2d53a..0000000000000 --- a/x-pack/solutions/security/plugins/kubernetes_security/public/components/percent_widget/index.test.tsx +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React from 'react'; -import { ENTRY_LEADER_INTERACTIVE } from '../../../common/constants'; -import { AppContextTestRender, createAppRootMockRenderer } from '../../test'; -import { GlobalFilter } from '../../types'; -import { PercentWidget, LOADING_TEST_ID, PERCENT_DATA_TEST_ID } from '.'; -import { useFetchPercentWidgetData } from './hooks'; - -const MOCK_DATA: Record = { - false: 47, - true: 1, -}; -const TITLE = 'Percent Widget Title'; -const GLOBAL_FILTER: GlobalFilter = { - endDate: '2022-06-15T14:15:25.777Z', - filterQuery: '{"bool":{"must":[],"filter":[],"should":[],"must_not":[]}}', - startDate: '2022-05-15T14:15:25.777Z', -}; -const DATA_VALUE_MAP = { - true: { - name: 'Interactive', - fieldName: ENTRY_LEADER_INTERACTIVE, - color: 'red', - }, - false: { - name: 'Non-interactive', - fieldName: ENTRY_LEADER_INTERACTIVE, - color: 'blue', - }, -}; - -const MOCK_DATA_VIEW_ID = 'dataViewId'; - -jest.mock('../../hooks/use_filter', () => ({ - useSetFilter: () => ({ - getFilterForValueButton: jest.fn(), - getFilterOutValueButton: jest.fn(), - filterManager: {}, - }), -})); - -jest.mock('./hooks'); -const mockUseFetchData = useFetchPercentWidgetData as jest.Mock; - -describe('PercentWidget component', () => { - let renderResult: ReturnType; - const mockedContext = createAppRootMockRenderer(); - const render: () => ReturnType = () => - (renderResult = mockedContext.render( - - )); - - describe('When PercentWidget is mounted', () => { - describe('with data', () => { - beforeEach(() => { - mockUseFetchData.mockImplementation(() => ({ - data: MOCK_DATA, - isLoading: false, - })); - }); - - it('should show title', async () => { - render(); - - expect(renderResult.getByText(TITLE)).toBeVisible(); - }); - it('should show data value names and value', async () => { - render(); - - expect(renderResult.getByText('Interactive')).toBeVisible(); - expect(renderResult.getByText('Non-interactive')).toBeVisible(); - expect(renderResult.queryByTestId(LOADING_TEST_ID)).toBeNull(); - expect(renderResult.getByText(47)).toBeVisible(); - expect(renderResult.getByText(1)).toBeVisible(); - }); - it('should show same number of data items as the number of records provided in dataValueMap', async () => { - render(); - - expect(renderResult.getAllByTestId(PERCENT_DATA_TEST_ID)).toHaveLength(2); - }); - }); - - describe('without data ', () => { - it('should show data value names and zeros as values when loading', async () => { - mockUseFetchData.mockImplementation(() => ({ - data: undefined, - isLoading: true, - })); - render(); - - expect(renderResult.getByText('Interactive')).toBeVisible(); - expect(renderResult.getByText('Non-interactive')).toBeVisible(); - expect(renderResult.getByTestId(LOADING_TEST_ID)).toBeVisible(); - expect(renderResult.getAllByText(0)).toHaveLength(2); - }); - it('should show zeros as values if no data returned', async () => { - mockUseFetchData.mockImplementation(() => ({ - data: undefined, - isLoading: false, - })); - render(); - - expect(renderResult.getByText('Interactive')).toBeVisible(); - expect(renderResult.getByText('Non-interactive')).toBeVisible(); - expect(renderResult.getAllByText(0)).toHaveLength(2); - }); - }); - }); -}); diff --git a/x-pack/solutions/security/plugins/kubernetes_security/public/components/percent_widget/index.tsx b/x-pack/solutions/security/plugins/kubernetes_security/public/components/percent_widget/index.tsx deleted file mode 100644 index eb09bf7f65954..0000000000000 --- a/x-pack/solutions/security/plugins/kubernetes_security/public/components/percent_widget/index.tsx +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React, { ReactNode, useMemo, useState } from 'react'; -import { EuiFlexGroup, EuiFlexItem, EuiProgress, EuiText } from '@elastic/eui'; -import { useStyles } from './styles'; -import type { IndexPattern, GlobalFilter } from '../../types'; -import { useSetFilter } from '../../hooks'; -import { addTimerangeAndDefaultFilterToQuery } from '../../utils/add_timerange_and_default_filter_to_query'; -import { AggregateResult } from '../../../common/types'; -import { useFetchPercentWidgetData } from './hooks'; - -export const LOADING_TEST_ID = 'kubernetesSecurity:percentWidgetLoading'; -export const PERCENT_DATA_TEST_ID = 'kubernetesSecurity:percentWidgetData'; - -export interface PercenWidgetDataValueMap { - name: string; - fieldName: string; - color: string; - shouldHideFilter?: boolean; -} - -export interface PercentWidgetDeps { - title: ReactNode; - dataValueMap: Record; - widgetKey: string; - indexPattern?: IndexPattern; - globalFilter: GlobalFilter; - groupedBy: string; - countBy?: string; - onReduce: (result: AggregateResult) => Record; - dataViewId?: string; -} - -interface FilterButtons { - filterForButtons: ReactNode[]; - filterOutButtons: ReactNode[]; -} - -export const PercentWidget = ({ - title, - dataValueMap, - widgetKey, - indexPattern, - globalFilter, - groupedBy, - countBy, - onReduce, - dataViewId, -}: PercentWidgetDeps) => { - const [hoveredFilter, setHoveredFilter] = useState(null); - const styles = useStyles(); - - const filterQueryWithTimeRange = useMemo(() => { - return addTimerangeAndDefaultFilterToQuery( - globalFilter.filterQuery, - globalFilter.startDate, - globalFilter.endDate - ); - }, [globalFilter.filterQuery, globalFilter.startDate, globalFilter.endDate]); - - const { data, isLoading } = useFetchPercentWidgetData( - onReduce, - filterQueryWithTimeRange, - widgetKey, - groupedBy, - countBy, - indexPattern?.title - ); - - const { getFilterForValueButton, getFilterOutValueButton, filterManager } = useSetFilter(); - const dataValueSum = useMemo( - () => (data ? Object.keys(data).reduce((sumSoFar, current) => sumSoFar + data[current], 0) : 0), - [data] - ); - const filterButtons = useMemo(() => { - const result: FilterButtons = { - filterForButtons: [], - filterOutButtons: [], - }; - Object.keys(dataValueMap).forEach((groupedByValue) => { - if (!dataValueMap[groupedByValue].shouldHideFilter) { - result.filterForButtons.push( - getFilterForValueButton({ - field: dataValueMap[groupedByValue].fieldName, - filterManager, - size: 'xs', - onClick: () => {}, - onFilterAdded: () => {}, - ownFocus: false, - showTooltip: true, - value: [groupedByValue], - dataViewId, - }) - ); - result.filterOutButtons.push( - getFilterOutValueButton({ - field: dataValueMap[groupedByValue].fieldName, - filterManager, - size: 'xs', - onClick: () => {}, - onFilterAdded: () => {}, - ownFocus: false, - showTooltip: true, - value: [groupedByValue], - dataViewId, - }) - ); - } - }); - - return result; - }, [dataValueMap, dataViewId, filterManager, getFilterForValueButton, getFilterOutValueButton]); - - return ( -
- {isLoading && ( - - )} -
{title}
- - {Object.keys(dataValueMap).map((groupedByValue, idx) => { - const value = data?.[groupedByValue] || 0; - return ( - setHoveredFilter(idx)} - onMouseLeave={() => setHoveredFilter(null)} - data-test-subj={PERCENT_DATA_TEST_ID} - > - - {dataValueMap[groupedByValue].name} - {hoveredFilter === idx && ( -
- {filterButtons.filterForButtons[idx]} - {filterButtons.filterOutButtons[idx]} -
- )} - {value} -
-
-
-
- - ); - })} - -
- ); -}; diff --git a/x-pack/solutions/security/plugins/kubernetes_security/public/components/percent_widget/styles.ts b/x-pack/solutions/security/plugins/kubernetes_security/public/components/percent_widget/styles.ts deleted file mode 100644 index e0725a1d84b4a..0000000000000 --- a/x-pack/solutions/security/plugins/kubernetes_security/public/components/percent_widget/styles.ts +++ /dev/null @@ -1,77 +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 { useMemo } from 'react'; -import type { CSSObject } from '@emotion/react'; -import { useEuiTheme } from '../../hooks'; - -export const useStyles = () => { - const { euiTheme } = useEuiTheme(); - - const cached = useMemo(() => { - const { size, colors, font, border } = euiTheme; - - const container: CSSObject = { - padding: size.base, - border: border.thin, - borderRadius: border.radius.medium, - overflow: 'auto', - position: 'relative', - }; - - const title: CSSObject = { - marginBottom: size.m, - }; - - const dataInfo: CSSObject = { - marginBottom: size.xs, - display: 'flex', - alignItems: 'center', - height: '18px', - }; - - const dataValue: CSSObject = { - fontWeight: font.weight.semiBold, - marginLeft: 'auto', - }; - - const filters: CSSObject = { - marginLeft: size.s, - }; - - const percentageBackground: CSSObject = { - position: 'relative', - backgroundColor: colors.lightShade, - height: size.xs, - borderRadius: border.radius.small, - }; - - const percentageBar: CSSObject = { - position: 'absolute', - height: size.xs, - borderRadius: border.radius.small, - }; - - const loadingSpinner: CSSObject = { - alignItems: 'center', - margin: `${size.xs} auto ${size.xl} auto`, - }; - - return { - container, - title, - dataInfo, - dataValue, - filters, - percentageBackground, - percentageBar, - loadingSpinner, - }; - }, [euiTheme]); - - return cached; -}; diff --git a/x-pack/solutions/security/plugins/kubernetes_security/public/components/tree_view_container/assets/illustration_product_no_results_magnifying_glass.svg b/x-pack/solutions/security/plugins/kubernetes_security/public/components/tree_view_container/assets/illustration_product_no_results_magnifying_glass.svg deleted file mode 100644 index b9a0df1630b20..0000000000000 --- a/x-pack/solutions/security/plugins/kubernetes_security/public/components/tree_view_container/assets/illustration_product_no_results_magnifying_glass.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/x-pack/solutions/security/plugins/kubernetes_security/public/components/tree_view_container/breadcrumb/__snapshots__/index.test.tsx.snap b/x-pack/solutions/security/plugins/kubernetes_security/public/components/tree_view_container/breadcrumb/__snapshots__/index.test.tsx.snap deleted file mode 100644 index 00c776a2a132a..0000000000000 --- a/x-pack/solutions/security/plugins/kubernetes_security/public/components/tree_view_container/breadcrumb/__snapshots__/index.test.tsx.snap +++ /dev/null @@ -1,461 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Tree view Breadcrumb component When Breadcrumb is mounted renders Breadcrumb button content correctly 1`] = ` -
-
-
-
- - - - - - - - - - - - - - - - - - -
-
-
-
-`; - -exports[`Tree view Breadcrumb component When Breadcrumb is mounted should display cluster icon button when no cluster name is provided 1`] = ` -
-
-
-
- - - - - - - - - - - - - - - - - - -
-
-
-
-`; - -exports[`Tree view Breadcrumb component When Breadcrumb is mounted should render breadcrumb icons 1`] = ` -
-
-
-
- - - - - - - - - - - - - - - - - - - - - - -
-
-
-
-`; - -exports[`Tree view Breadcrumb component When Breadcrumb is mounted should render last breadcrumb content only 1`] = ` -
-
-
-
- - - - - - - - - - - - - - -
-
-
-
-`; diff --git a/x-pack/solutions/security/plugins/kubernetes_security/public/components/tree_view_container/breadcrumb/helper.test.tsx b/x-pack/solutions/security/plugins/kubernetes_security/public/components/tree_view_container/breadcrumb/helper.test.tsx deleted file mode 100644 index ccce32a2dce0e..0000000000000 --- a/x-pack/solutions/security/plugins/kubernetes_security/public/components/tree_view_container/breadcrumb/helper.test.tsx +++ /dev/null @@ -1,70 +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 { KubernetesCollectionMap, KubernetesTreeViewLevels } from '../../../types'; -import { showBreadcrumbDisplayText } from './helper'; - -describe('showBreadcrumbDisplayText()', () => { - it('should return true when last breadcrumb is clusterId or clusterName', () => { - const MOCK_TREE_SELECTION: Partial = { - clusterId: 'selected cluster id', - clusterName: 'selected cluster name', - }; - - expect(showBreadcrumbDisplayText(MOCK_TREE_SELECTION, KubernetesTreeViewLevels.clusterId)).toBe( - true - ); - }); - - it('should return false when collectionType is not the last breadcrumb ', () => { - const MOCK_TREE_SELECTION: Partial = { - clusterId: 'selected cluster id', - clusterName: 'selected cluster name', - node: 'selected node name', - }; - - expect(showBreadcrumbDisplayText(MOCK_TREE_SELECTION, KubernetesTreeViewLevels.clusterId)).toBe( - false - ); - }); - - it('should true when node is the last breadcrumb ', () => { - const MOCK_TREE_SELECTION: Partial = { - clusterId: 'selected cluster id', - clusterName: 'selected cluster name', - node: 'selected node name', - }; - - expect(showBreadcrumbDisplayText(MOCK_TREE_SELECTION, KubernetesTreeViewLevels.node)).toBe( - true - ); - }); - - it('should true when pod is the last breadcrumb ', () => { - const MOCK_TREE_SELECTION: Partial = { - clusterId: 'selected cluster id', - clusterName: 'selected cluster name', - node: 'selected node name', - pod: 'selected pod name', - }; - - expect(showBreadcrumbDisplayText(MOCK_TREE_SELECTION, KubernetesTreeViewLevels.pod)).toBe(true); - }); - it('should true when container image is the last breadcrumb ', () => { - const MOCK_TREE_SELECTION: Partial = { - clusterId: 'selected cluster id', - clusterName: 'selected cluster name', - node: 'selected node name', - pod: 'selected pod name', - containerImage: 'selected container image', - }; - - expect( - showBreadcrumbDisplayText(MOCK_TREE_SELECTION, KubernetesTreeViewLevels.containerImage) - ).toBe(true); - }); -}); diff --git a/x-pack/solutions/security/plugins/kubernetes_security/public/components/tree_view_container/breadcrumb/helper.tsx b/x-pack/solutions/security/plugins/kubernetes_security/public/components/tree_view_container/breadcrumb/helper.tsx deleted file mode 100644 index 6af85b7783a43..0000000000000 --- a/x-pack/solutions/security/plugins/kubernetes_security/public/components/tree_view_container/breadcrumb/helper.tsx +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { KubernetesCollectionMap, KubernetesTreeViewLevels } from '../../../types'; - -export const showBreadcrumbDisplayText = ( - treeNavSelection: Partial>, - collectionType: string -): boolean => { - const resourceNames = Object.keys(treeNavSelection); - const lastSelectedResourceName = resourceNames[resourceNames.length - 1]; - - const isClusterNameSelected = - lastSelectedResourceName === KubernetesTreeViewLevels.clusterName && - collectionType === KubernetesTreeViewLevels.clusterId; - - const isLastSelectedCollectionType = collectionType === lastSelectedResourceName; - return isClusterNameSelected || isLastSelectedCollectionType; -}; diff --git a/x-pack/solutions/security/plugins/kubernetes_security/public/components/tree_view_container/breadcrumb/index.test.tsx b/x-pack/solutions/security/plugins/kubernetes_security/public/components/tree_view_container/breadcrumb/index.test.tsx deleted file mode 100644 index c377f21080ed1..0000000000000 --- a/x-pack/solutions/security/plugins/kubernetes_security/public/components/tree_view_container/breadcrumb/index.test.tsx +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React from 'react'; -import { AppContextTestRender, createAppRootMockRenderer } from '../../../test'; -import { KubernetesCollectionMap } from '../../../types'; -import { Breadcrumb } from '.'; - -const MOCK_TREE_SELECTION: KubernetesCollectionMap = { - clusterId: 'selected cluster id', - clusterName: 'selected cluster name', - namespace: 'selected namespace', - node: 'selected node', - pod: 'selected pod', - containerImage: 'selected image', -}; - -describe('Tree view Breadcrumb component', () => { - let render: () => ReturnType; - let renderResult: ReturnType; - let mockedContext: AppContextTestRender; - let onSelect: jest.Mock; - - beforeEach(() => { - mockedContext = createAppRootMockRenderer(); - onSelect = jest.fn(); - }); - - describe('When Breadcrumb is mounted', () => { - it('renders Breadcrumb button content correctly', async () => { - renderResult = mockedContext.render( - - ); - - expect(renderResult.queryByText(MOCK_TREE_SELECTION.clusterName!)).toBeNull(); - expect(renderResult.queryByText(MOCK_TREE_SELECTION.namespace!)).toBeNull(); - expect(renderResult.queryByText(MOCK_TREE_SELECTION.node!)).toBeFalsy(); - expect(renderResult.queryByText(MOCK_TREE_SELECTION.pod!)).toBeNull(); - expect(renderResult.queryByText(MOCK_TREE_SELECTION.containerImage!)).toBeVisible(); - expect(renderResult.container).toMatchSnapshot(); - }); - - it('should render breadcrumb icons', async () => { - renderResult = mockedContext.render( - - ); - - expect( - renderResult.queryByTestId('kubernetesSecurityBreadcrumbIcon-clusterId') - ).toBeVisible(); - expect(renderResult.queryByTestId('kubernetesSecurityBreadcrumbIcon-node')).toBeVisible(); - expect(renderResult.queryByTestId('kubernetesSecurityBreadcrumbIcon-pod')).toBeVisible(); - expect( - renderResult.queryByTestId('kubernetesSecurityBreadcrumbIcon-containerImage') - ).toBeVisible(); - expect(renderResult.container).toMatchSnapshot(); - }); - it('returns null when no selected collection', async () => { - renderResult = mockedContext.render(); - expect(renderResult.container).toBeEmptyDOMElement(); - }); - - it('should display cluster icon button when no cluster name is provided', async () => { - renderResult = mockedContext.render( - - ); - - expect( - renderResult.queryByTestId('kubernetesSecurityBreadcrumbIcon-clusterId') - ).toBeVisible(); - expect(renderResult.queryByText(MOCK_TREE_SELECTION.clusterId!)).toBeNull(); - expect(renderResult.queryByText(MOCK_TREE_SELECTION.containerImage!)).toBeVisible(); - expect(renderResult.container).toMatchSnapshot(); - }); - - it('should return null when no cluster in selection', async () => { - renderResult = mockedContext.render( - - ); - - expect(renderResult.container).toBeEmptyDOMElement(); - }); - - it('clicking on breadcrumb item triggers onSelect', async () => { - const mockPodNavSelection = { - clusterId: 'selected cluster id', - clusterName: 'selected cluster name', - namespace: 'selected namespace', - node: 'selected node', - pod: 'selected pod', - }; - renderResult = mockedContext.render( - - ); - expect(renderResult.queryByText(mockPodNavSelection.pod)).toBeVisible(); - renderResult.getByText(mockPodNavSelection.pod).click(); - expect(onSelect).toHaveBeenCalledTimes(1); - }); - - it('should render last breadcrumb content only', async () => { - renderResult = mockedContext.render( - - ); - - expect(renderResult.queryByText(MOCK_TREE_SELECTION.clusterName!)).toBeNull(); - expect(renderResult.queryByText(MOCK_TREE_SELECTION.namespace!)).toBeNull(); - expect(renderResult.queryByText(MOCK_TREE_SELECTION.node!)).toBeNull(); - expect(renderResult.queryByText(MOCK_TREE_SELECTION.pod!)).toBeNull(); - expect(renderResult.queryByText(MOCK_TREE_SELECTION.containerImage!)).toBeVisible(); - expect(renderResult.container).toMatchSnapshot(); - }); - }); -}); diff --git a/x-pack/solutions/security/plugins/kubernetes_security/public/components/tree_view_container/breadcrumb/index.tsx b/x-pack/solutions/security/plugins/kubernetes_security/public/components/tree_view_container/breadcrumb/index.tsx deleted file mode 100644 index 43ee4126c1488..0000000000000 --- a/x-pack/solutions/security/plugins/kubernetes_security/public/components/tree_view_container/breadcrumb/index.tsx +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React, { useCallback } from 'react'; -import { - EuiButtonEmpty, - EuiButtonIcon, - EuiFlexGroup, - EuiFlexItem, - EuiIcon, - EuiToolTip, -} from '@elastic/eui'; -import { useEuiTheme } from '../../../hooks'; -import { - KubernetesCollectionMap, - KubernetesCollection, - TreeViewIconProps, - KubernetesTreeViewLevels, -} from '../../../types'; -import { useStyles } from './styles'; -import { KUBERNETES_COLLECTION_ICONS_PROPS } from '../helpers'; -import { showBreadcrumbDisplayText } from './helper'; -import { BREADCRUMBS_CLUSTER_TREE_VIEW_LEVELS } from '../translations'; -interface BreadcrumbDeps { - treeNavSelection: Partial; - onSelect: (selection: Partial) => void; -} - -export const Breadcrumb = ({ treeNavSelection, onSelect }: BreadcrumbDeps) => { - const styles = useStyles(); - const { euiVars } = useEuiTheme(); - const onBreadCrumbClick = useCallback( - (collectionType: string) => { - return async () => { - const selectionCopy = { ...treeNavSelection }; - switch (collectionType) { - case KubernetesTreeViewLevels.clusterId: { - onSelect({ - clusterId: treeNavSelection.clusterId, - clusterName: treeNavSelection.clusterName, - }); - break; - } - case KubernetesTreeViewLevels.namespace: - case KubernetesTreeViewLevels.node: { - delete selectionCopy.pod; - delete selectionCopy.containerImage; - onSelect(selectionCopy); - break; - } - case KubernetesTreeViewLevels.pod: { - delete selectionCopy.containerImage; - onSelect(selectionCopy); - break; - } - } - }; - }, - [onSelect, treeNavSelection] - ); - - const renderBreadcrumbLink = useCallback( - ( - collectionType: KubernetesCollection, - treeViewIconProps: TreeViewIconProps, - isBolded: boolean, - hasRightArrow: boolean = true - ) => { - const clusterLevel = BREADCRUMBS_CLUSTER_TREE_VIEW_LEVELS[collectionType]; - const resourceName = - collectionType === KubernetesTreeViewLevels.clusterId - ? treeNavSelection.clusterName || treeNavSelection.clusterId - : treeNavSelection[collectionType]; - - const tooltip = `${clusterLevel}: ${resourceName}`; - const showBreadcrumbText = showBreadcrumbDisplayText(treeNavSelection, collectionType); - const { type: iconType, euiVarColor } = treeViewIconProps; - - return ( - <> - {hasRightArrow && } - - - - {showBreadcrumbText && ( - - - {resourceName} - - - )} - - ); - }, - [onBreadCrumbClick, styles, treeNavSelection, euiVars] - ); - - if (!treeNavSelection.clusterId) { - return null; - } - - return ( -
- - - {renderBreadcrumbLink( - KubernetesTreeViewLevels.clusterId, - KUBERNETES_COLLECTION_ICONS_PROPS.clusterId, - !(treeNavSelection.namespace || treeNavSelection.node), - false - )} - {treeNavSelection.namespace && - renderBreadcrumbLink( - KubernetesTreeViewLevels.namespace, - KUBERNETES_COLLECTION_ICONS_PROPS.namespace, - !treeNavSelection.pod - )} - {treeNavSelection.node && - renderBreadcrumbLink( - KubernetesTreeViewLevels.node, - KUBERNETES_COLLECTION_ICONS_PROPS.node, - !treeNavSelection.pod - )} - {treeNavSelection.pod && - renderBreadcrumbLink( - KubernetesTreeViewLevels.pod, - KUBERNETES_COLLECTION_ICONS_PROPS.pod, - !treeNavSelection.containerImage - )} - {treeNavSelection.containerImage && - renderBreadcrumbLink( - KubernetesTreeViewLevels.containerImage, - KUBERNETES_COLLECTION_ICONS_PROPS.containerImage, - true - )} - - -
- ); -}; diff --git a/x-pack/solutions/security/plugins/kubernetes_security/public/components/tree_view_container/breadcrumb/styles.ts b/x-pack/solutions/security/plugins/kubernetes_security/public/components/tree_view_container/breadcrumb/styles.ts deleted file mode 100644 index 82f98750879bb..0000000000000 --- a/x-pack/solutions/security/plugins/kubernetes_security/public/components/tree_view_container/breadcrumb/styles.ts +++ /dev/null @@ -1,61 +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 { useMemo } from 'react'; -import { CSSObject } from '@emotion/react'; -import { useEuiTheme } from '../../../hooks'; - -export const useStyles = () => { - const { euiTheme } = useEuiTheme(); - - const cached = useMemo(() => { - const { colors, size, font, border } = euiTheme; - - const breadcrumb: CSSObject = { - borderBottom: border.thin, - borderColor: colors.lightShade, - paddingBottom: size.s, - marginBottom: size.m, - }; - - const breadcrumbButton: CSSObject = { - height: 'fit-content', - maxWidth: '248px', - fontSize: size.m, - fontWeight: font.weight.regular, - '.euiButtonEmpty': { - paddingInline: size.xs, - }, - }; - - const breadcrumbButtonBold: CSSObject = { - ...breadcrumbButton, - fontWeight: font.weight.semiBold, - }; - - const breadcrumbRightIcon: CSSObject = { - marginRight: size.xs, - }; - - const breadcrumbsWrapper: CSSObject = { flexDirection: 'row', alignItems: 'center' }; - - const breadcrumbIconColor = (color: string): CSSObject => ({ - color, - }); - - return { - breadcrumb, - breadcrumbButton, - breadcrumbButtonBold, - breadcrumbRightIcon, - breadcrumbsWrapper, - breadcrumbIconColor, - }; - }, [euiTheme]); - - return cached; -}; diff --git a/x-pack/solutions/security/plugins/kubernetes_security/public/components/tree_view_container/contexts.tsx b/x-pack/solutions/security/plugins/kubernetes_security/public/components/tree_view_container/contexts.tsx deleted file mode 100644 index 89543d2d5fee7..0000000000000 --- a/x-pack/solutions/security/plugins/kubernetes_security/public/components/tree_view_container/contexts.tsx +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React, { createContext, useContext } from 'react'; - -import { useTreeView, UseTreeViewProps } from './hooks'; - -type TreeViewContextType = ReturnType; - -const TreeViewContext = createContext(null); - -export const useTreeViewContext = () => { - const context = useContext(TreeViewContext); - if (!context) { - throw new Error('useTreeViewContext must be called within an TreeViewContextProvider'); - } - return context; -}; - -type TreeViewContextProviderProps = { - children: JSX.Element; -}; - -export const TreeViewContextProvider = ({ - children, - ...useTreeViewProps -}: TreeViewContextProviderProps & UseTreeViewProps) => { - return ( - - {children} - - ); -}; diff --git a/x-pack/solutions/security/plugins/kubernetes_security/public/components/tree_view_container/dynamic_tree_view/helpers.test.tsx b/x-pack/solutions/security/plugins/kubernetes_security/public/components/tree_view_container/dynamic_tree_view/helpers.test.tsx deleted file mode 100644 index b623ddb773741..0000000000000 --- a/x-pack/solutions/security/plugins/kubernetes_security/public/components/tree_view_container/dynamic_tree_view/helpers.test.tsx +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ -import React, { FC } from 'react'; -import { render } from '@testing-library/react'; -import userEvent from '@testing-library/user-event'; -import { focusNextElement } from './helpers'; - -// dummy component for testing -const TestButtonList: FC = (props: any) => ( - <> - {[...Array(100)].map((_, idx) => ( - - ))} - -); - -describe('DynamicTreeView component', () => { - it('Should focus the next element', async () => { - const onKeyDown = (e: any) => { - focusNextElement(e, 'button', 'next'); - }; - const wrapper = render(); - wrapper.getByText('Button 40').focus(); - - await userEvent.keyboard('{ArrowRight}'); - expect(wrapper.getByText('Button 41')).toHaveFocus(); - await userEvent.keyboard('{ArrowRight}'); - expect(wrapper.getByText('Button 42')).toHaveFocus(); - }); - it('Should focus the previous element', async () => { - const onKeyDown = (e: any) => { - focusNextElement(e, 'button', 'prev'); - }; - const wrapper = render(); - wrapper.getByText('Button 40').focus(); - - await userEvent.keyboard('{ArrowLeft}'); - expect(wrapper.getByText('Button 39')).toHaveFocus(); - await userEvent.keyboard('{ArrowLeft}'); - expect(wrapper.getByText('Button 38')).toHaveFocus(); - }); -}); diff --git a/x-pack/solutions/security/plugins/kubernetes_security/public/components/tree_view_container/dynamic_tree_view/helpers.ts b/x-pack/solutions/security/plugins/kubernetes_security/public/components/tree_view_container/dynamic_tree_view/helpers.ts deleted file mode 100644 index 774ea3eb10ee5..0000000000000 --- a/x-pack/solutions/security/plugins/kubernetes_security/public/components/tree_view_container/dynamic_tree_view/helpers.ts +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { KeyboardEvent, MouseEvent } from 'react'; - -export const disableEventDefaults = (event: KeyboardEvent | MouseEvent) => { - event.preventDefault(); - event.stopPropagation(); -}; - -export const focusNextElement = ( - event: KeyboardEvent, - selector: string, - direction: 'prev' | 'next' -) => { - const list = Array.from(document.querySelectorAll(selector)); - const currentIndex = list.indexOf(event.currentTarget); - if (currentIndex > -1) { - const nextButton = list[currentIndex + (direction === 'next' ? +1 : -1)] as HTMLElement; - if (nextButton) { - disableEventDefaults(event); - nextButton.focus(); - } - } -}; diff --git a/x-pack/solutions/security/plugins/kubernetes_security/public/components/tree_view_container/dynamic_tree_view/hooks.ts b/x-pack/solutions/security/plugins/kubernetes_security/public/components/tree_view_container/dynamic_tree_view/hooks.ts deleted file mode 100644 index 1821229121ceb..0000000000000 --- a/x-pack/solutions/security/plugins/kubernetes_security/public/components/tree_view_container/dynamic_tree_view/hooks.ts +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ -import { useInfiniteQuery } from '@tanstack/react-query'; -import { CoreStart } from '@kbn/core/public'; -import { useKibana } from '@kbn/kibana-react-plugin/public'; -import { QueryDslQueryContainerBool } from '../../../types'; -import { - QUERY_KEY_PROCESS_EVENTS, - AGGREGATE_ROUTE, - MULTI_TERMS_AGGREGATE_ROUTE, - ORCHESTRATOR_CLUSTER_NAME, - CURRENT_API_VERSION, -} from '../../../../common/constants'; -import { AggregateBucketPaginationResult, MultiTermsBucket } from '../../../../common/types'; -import { KUBERNETES_COLLECTION_FIELDS } from '../helpers'; - -export const useFetchDynamicTreeView = ( - query: QueryDslQueryContainerBool, - groupBy: string, - index?: string, - enabled?: boolean -) => { - const { http } = useKibana().services; - const cachingKeys = [QUERY_KEY_PROCESS_EVENTS, query, groupBy, index]; - - return useInfiniteQuery( - cachingKeys, - async ({ pageParam = 0 }) => { - if (groupBy === KUBERNETES_COLLECTION_FIELDS.clusterId) { - const { buckets } = await http.get(MULTI_TERMS_AGGREGATE_ROUTE, { - version: '1', - query: { - query: JSON.stringify(query), - groupBys: JSON.stringify([ - { - field: groupBy, - }, - { - field: ORCHESTRATOR_CLUSTER_NAME, - missing: '', - }, - ]), - page: pageParam, - perPage: 50, - index, - }, - }); - - return { - buckets: buckets.map((bucket: MultiTermsBucket) => ({ - ...bucket, - key_as_string: bucket.key[1], - key: bucket.key[0], - })), - }; - } - - return await http.get(AGGREGATE_ROUTE, { - version: CURRENT_API_VERSION, - query: { - query: JSON.stringify(query), - groupBy, - page: pageParam, - perPage: 50, - index, - }, - }); - }, - { - enabled, - getNextPageParam: (lastPage, pages) => (lastPage.hasNextPage ? pages.length : undefined), - } - ); -}; diff --git a/x-pack/solutions/security/plugins/kubernetes_security/public/components/tree_view_container/dynamic_tree_view/index.test.tsx b/x-pack/solutions/security/plugins/kubernetes_security/public/components/tree_view_container/dynamic_tree_view/index.test.tsx deleted file mode 100644 index 7752ba8d96e51..0000000000000 --- a/x-pack/solutions/security/plugins/kubernetes_security/public/components/tree_view_container/dynamic_tree_view/index.test.tsx +++ /dev/null @@ -1,203 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React from 'react'; -import { waitFor } from '@testing-library/react'; -import { AppContextTestRender, createAppRootMockRenderer } from '../../../test'; -import { DynamicTreeView } from '.'; -import { clusterResponseMock, nodeResponseMock } from '../mocks'; -import { TreeViewContextProvider } from '../contexts'; - -describe('DynamicTreeView component', () => { - let render: (props?: any) => ReturnType; - let renderResult: ReturnType; - let mockedContext: AppContextTestRender; - let mockedApi: AppContextTestRender['coreStart']['http']['get']; - - const defaultProps = { - globalFilter: { - startDate: Date.now().toString(), - endDate: (Date.now() + 1).toString(), - }, - indexPattern: { - title: '*-logs', - }, - } as any; - - beforeEach(() => { - jest.clearAllMocks(); - mockedContext = createAppRootMockRenderer(); - mockedApi = mockedContext.coreStart.http.get; - mockedApi.mockResolvedValue(clusterResponseMock); - render = (props) => - (renderResult = mockedContext.render( - - {}} - {...props} - /> - - )); - }); - - describe('When DynamicTreeView is mounted', () => { - it('should show loading state while retrieving empty data and hide it when settled', async () => { - render(); - expect(renderResult.queryByText(/loading/i)).toBeInTheDocument(); - await waitFor(() => { - expect(renderResult.queryByText(/loading/i)).not.toBeInTheDocument(); - }); - }); - }); - - describe('DynamicTreeView parent level', () => { - const key = 'orchestrator.cluster.id'; - const tree = [ - { - key, - name: 'cluster', - namePlural: 'clusters', - type: 'clusterId', - iconProps: { - type: 'cluster', - }, - }, - ]; - - it('should make a api call with group based on tree parameters', async () => { - render({ - tree, - }); - - await waitFor(() => { - expect(mockedApi).toHaveBeenCalledWith( - '/internal/kubernetes_security/multi_terms_aggregate', - { - query: { - groupBys: `[{"field":"${key}"},{"field":"orchestrator.cluster.name","missing":""}]`, - index: '*-logs', - page: 0, - perPage: 50, - query: '{"bool":{"filter":[],"must":[],"must_not":[],"should":[]}}', - }, - version: '1', - } - ); - }); - }); - - it('should render the parent level based on api response', async () => { - render({ - tree, - }); - - await waitFor(() => { - ['awp-demo-gke-main', 'awp-demo-gke-test'].forEach((cluster) => { - expect(renderResult.queryByText(cluster)).toBeInTheDocument(); - }); - }); - }); - - it('should trigger a callback when tree node is clicked', async () => { - const callback = jest.fn(); - render({ tree, onSelect: callback }); - - await waitFor(() => { - renderResult.getByRole('button', { name: 'awp-demo-gke-main' }).click(); - }); - - expect(callback).toHaveBeenCalled(); - }); - }); - - describe('DynamicTreeView children', () => { - const tree = [ - { - key: 'orchestrator.cluster.id', - name: 'clusterId', - namePlural: 'clusters', - type: 'clusterId', - iconProps: { - type: 'cluster', - }, - }, - { - key: 'node', - name: 'node', - namePlural: 'nodes', - type: 'node', - iconProps: { - type: 'node', - }, - }, - ]; - - const parent = 'awp-demo-gke-main'; - - it('should make a children api call with filter when parent is expanded', async () => { - render({ tree }); - await waitFor(() => { - renderResult.getByRole('button', { name: parent }).click(); - }); - - mockedApi.mockResolvedValueOnce(nodeResponseMock); - - await waitFor(() => { - expect(mockedApi).toHaveBeenCalledWith('/internal/kubernetes_security/aggregate', { - query: { - groupBy: 'node', - index: '*-logs', - page: 0, - perPage: 50, - query: `{"bool":{"filter":[{"term":{"orchestrator.cluster.id":"${parent}"}}],"must":[],"must_not":[],"should":[]}}`, - }, - version: '1', - }); - }); - }); - - it('should render children when parent is expanded based on api request', async () => { - render({ tree }); - - await waitFor(() => { - expect(renderResult.getByRole('button', { name: parent })).toBeTruthy(); - mockedApi.mockResolvedValueOnce(nodeResponseMock); - renderResult.getByRole('button', { name: parent }).click(); - }); - - // check if children has loading state - await waitFor(() => { - expect(renderResult.queryByText(/loading/i)).toBeInTheDocument(); - }); - - await waitFor(() => { - ['default', 'kube-system', 'production', 'qa', 'staging'].forEach((node) => { - expect(renderResult.queryByText(node)).toBeInTheDocument(); - }); - }); - }); - }); -}); diff --git a/x-pack/solutions/security/plugins/kubernetes_security/public/components/tree_view_container/dynamic_tree_view/index.tsx b/x-pack/solutions/security/plugins/kubernetes_security/public/components/tree_view_container/dynamic_tree_view/index.tsx deleted file mode 100644 index 6527e290c5903..0000000000000 --- a/x-pack/solutions/security/plugins/kubernetes_security/public/components/tree_view_container/dynamic_tree_view/index.tsx +++ /dev/null @@ -1,344 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React, { useEffect, useState, useRef, KeyboardEvent, useMemo } from 'react'; -import { - EuiTreeView, - EuiText, - EuiI18n, - EuiScreenReaderOnly, - EuiBadge, - keys, - EuiLoadingSpinner, - EuiToolTip, - useEuiTheme, -} from '@elastic/eui'; -// @ts-expect-error style types not defined, but they exist -import { euiTreeViewStyles } from '@elastic/eui/lib/components/tree_view/tree_view.styles'; - -import { - TREE_NAVIGATION_LOADING, - TREE_NAVIGATION_EMPTY, - TREE_NAVIGATION_SHOW_MORE, -} from '../../../../common/translations'; -import { useFetchDynamicTreeView } from './hooks'; -import { useStyles } from './styles'; -import { disableEventDefaults, focusNextElement } from './helpers'; -import { useTreeViewContext } from '../contexts'; -import { TreeViewIcon } from '../tree_view_icon'; -import type { DynamicTreeViewProps, DynamicTreeViewItemProps } from './types'; -import { BREADCRUMBS_CLUSTER_TREE_VIEW_LEVELS } from '../translations'; - -const BUTTON_TEST_ID = 'kubernetesSecurity:dynamicTreeViewButton'; - -const focusNextButton = (event: KeyboardEvent) => { - focusNextElement(event, `[data-test-subj="${BUTTON_TEST_ID}"]`, 'next'); -}; -const focusPreviousButton = (event: KeyboardEvent) => { - focusNextElement(event, `[data-test-subj="${BUTTON_TEST_ID}"]`, 'prev'); -}; - -const DynamicTreeViewExpander = ({ - defaultExpanded = false, - children, -}: { - defaultExpanded: boolean; - children: (childrenProps: { isExpanded: boolean; onToggleExpand: () => void }) => JSX.Element; -}) => { - const [isExpanded, setIsExpanded] = useState(defaultExpanded); - - const onToggleExpand = () => { - setIsExpanded((e) => !e); - }; - - return children({ - isExpanded, - onToggleExpand, - }); -}; - -export const DynamicTreeView = ({ - tree, - depth = 0, - selectionDepth = {}, - query, - onSelect, - selected = '', - expanded = true, - onKeyDown, -}: DynamicTreeViewProps) => { - const styles = useStyles(depth); - const euiStyles = euiTreeViewStyles(useEuiTheme()); - const euiTreeViewCss = [euiStyles.euiTreeView, euiStyles.default]; - - const { indexPattern, setNoResults, setTreeNavSelection } = useTreeViewContext(); - - const { data, fetchNextPage, isFetchingNextPage, hasNextPage, isLoading } = - useFetchDynamicTreeView(query, tree[depth].key, indexPattern, expanded); - - const onLoadMoreKeydown = (event: React.KeyboardEvent) => { - switch (event.key) { - case keys.ARROW_DOWN: { - focusNextButton(event); - break; - } - case keys.ARROW_UP: { - focusPreviousButton(event); - break; - } - case keys.ARROW_RIGHT: { - disableEventDefaults(event); - fetchNextPage(); - } - } - }; - - useEffect(() => { - if (depth === 0 && data) { - const noData = data.pages?.[0].buckets.length === 0; - setNoResults(noData); - - if (noData) { - setTreeNavSelection({}); - } - } - }, [data, depth, setNoResults, setTreeNavSelection]); - - useEffect(() => { - if (expanded) { - fetchNextPage(); - } - }, [fetchNextPage, expanded]); - - useEffect(() => { - if (!selected && !depth && data && data.pages?.[0].buckets?.[0]?.key) { - onSelect( - {}, - tree[depth].type, - data.pages[0].buckets[0].key, - data.pages[0].buckets[0].key_as_string - ); - } - }, [data, depth, selected, onSelect, tree]); - - const onClickNextPageHandler = () => { - fetchNextPage(); - }; - - const itemList = useMemo(() => { - return ( - data?.pages - ?.map((aggsData) => { - return aggsData?.buckets; - }) - .flat() || [] - ); - }, [data?.pages]); - - return ( - - ); -}; - -const DynamicTreeViewItem = ({ - depth, - tree, - onToggleExpand, - onSelect, - aggData, - selectionDepth, - isExpanded, - selected, - expanded, - query, -}: DynamicTreeViewItemProps) => { - const isLastNode = depth === tree.length - 1; - const buttonRef = useRef>({}); - - const handleSelect = () => { - if (tree[depth].type === 'clusterId') { - onSelect(selectionDepth, tree[depth].type, aggData.key, aggData.key_as_string); - } else { - onSelect(selectionDepth, tree[depth].type, aggData.key); - } - }; - - const onKeyboardToggle = () => { - if (!isLastNode) { - onToggleExpand(); - } - handleSelect(); - }; - - const onButtonToggle = () => { - if (!isLastNode) { - onToggleExpand(); - } - handleSelect(); - }; - - // Enable keyboard navigation - const onKeyDown = (event: React.KeyboardEvent) => { - switch (event.key) { - case keys.ARROW_DOWN: { - focusNextButton(event); - break; - } - case keys.ARROW_UP: { - focusPreviousButton(event); - break; - } - case keys.ARROW_RIGHT: { - if (!isExpanded && !isLastNode) { - disableEventDefaults(event); - onKeyboardToggle(); - } - break; - } - case keys.ARROW_LEFT: { - if (isExpanded) { - disableEventDefaults(event); - onKeyboardToggle(); - } - } - default: - break; - } - }; - - const onChildrenKeydown = (event: React.KeyboardEvent, key: string) => { - if (event.key === keys.ARROW_LEFT) { - disableEventDefaults(event); - buttonRef.current[key].focus(); - } - }; - - const clusterLevel = BREADCRUMBS_CLUSTER_TREE_VIEW_LEVELS[tree[depth].type]; - - return ( - } - label={ - - {aggData.key_as_string || aggData.key} - - } - buttonRef={(el: HTMLButtonElement) => (buttonRef.current[aggData.key] = el)} - data-test-subj={expanded ? BUTTON_TEST_ID : ''} - > - {!isLastNode && ( - - onChildrenKeydown(event, aggData.key.toString()) - } - /> - )} - - ); -}; diff --git a/x-pack/solutions/security/plugins/kubernetes_security/public/components/tree_view_container/dynamic_tree_view/styles.ts b/x-pack/solutions/security/plugins/kubernetes_security/public/components/tree_view_container/dynamic_tree_view/styles.ts deleted file mode 100644 index fc2a9c2a42bea..0000000000000 --- a/x-pack/solutions/security/plugins/kubernetes_security/public/components/tree_view_container/dynamic_tree_view/styles.ts +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { useMemo } from 'react'; -import { CSSObject } from '@emotion/react'; -import { useEuiTheme } from '../../../hooks'; - -export const useStyles = (depth: number) => { - const { euiTheme } = useEuiTheme(); - - const cached = useMemo(() => { - const { size, colors, border } = euiTheme; - - const loadMoreButton: CSSObject = { - position: 'relative', - textAlign: 'center', - width: `calc(100% + ${depth * 24}px)`, - marginLeft: `-${depth * 24}px`, - '&::after': { - content: `''`, - position: 'absolute', - top: '50%', - width: '100%', - border: `${border.width.thin} dashed ${colors.mediumShade}`, - left: 0, - }, - '&:hover, &:focus': { - backgroundColor: 'transparent', - }, - '.euiTreeView__nodeLabel': { - width: '100%', - }, - }; - const loadMoreBadge: CSSObject = { - position: 'relative', - cursor: 'pointer', - zIndex: 2, - '.euiBadge__content': { - gap: size.xs, - }, - }; - const nonInteractiveItem: CSSObject = { - pointerEvents: 'none', - '&:hover, &:focus': { - backgroundColor: 'transparent', - }, - }; - const euiTreeViewWrapper: CSSObject = { - ul: { - marginLeft: '0 !important', - fontSize: 'inherit', - }, - // Override default EUI max-height - `DynamicTreeView` has its own scrolling container - '.euiTreeView__node': { - maxBlockSize: 'none', - }, - }; - - return { - loadMoreButton, - loadMoreBadge, - nonInteractiveItem, - euiTreeViewWrapper, - }; - }, [euiTheme, depth]); - - return cached; -}; diff --git a/x-pack/solutions/security/plugins/kubernetes_security/public/components/tree_view_container/dynamic_tree_view/types.ts b/x-pack/solutions/security/plugins/kubernetes_security/public/components/tree_view_container/dynamic_tree_view/types.ts deleted file mode 100644 index 835aa397ebadb..0000000000000 --- a/x-pack/solutions/security/plugins/kubernetes_security/public/components/tree_view_container/dynamic_tree_view/types.ts +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { KeyboardEventHandler } from 'react'; -import { QueryDslQueryContainerBool, KubernetesCollectionMap, DynamicTree } from '../../../types'; - -export type DynamicTreeViewProps = { - tree: DynamicTree[]; - depth?: number; - selectionDepth?: Partial; - query: QueryDslQueryContainerBool; - onSelect: ( - selectionDepth: Partial, - type: string, - key: string | number, - clusterName?: string - ) => void; - hasSelection?: boolean; - selected?: string; - expanded?: boolean; - onKeyDown?: KeyboardEventHandler | undefined; -}; - -export type DynamicTreeViewItemProps = Required< - Omit -> & { - onToggleExpand: any; - aggData: any; - isExpanded: boolean; -}; diff --git a/x-pack/solutions/security/plugins/kubernetes_security/public/components/tree_view_container/empty_state.tsx b/x-pack/solutions/security/plugins/kubernetes_security/public/components/tree_view_container/empty_state.tsx deleted file mode 100644 index 84f918a2cd0b5..0000000000000 --- a/x-pack/solutions/security/plugins/kubernetes_security/public/components/tree_view_container/empty_state.tsx +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React from 'react'; -import { EuiPanel, EuiFlexGroup, EuiFlexItem, EuiImage, EuiText, EuiTitle } from '@elastic/eui'; -import { FormattedMessage } from '@kbn/i18n-react'; -import { CSSObject } from '@emotion/serialize'; -import icon from './assets/illustration_product_no_results_magnifying_glass.svg'; - -export const TREE_EMPTY_STATE = 'kubernetesSecurity:treeEmptyState'; - -const panelStyle: CSSObject = { - maxWidth: 500, -}; - -const wrapperStyle: CSSObject = { - height: 262, -}; - -export const EmptyState: React.FC = () => { - return ( - - - - - - - - -

- -

-
-

- -

-
-
- - - -
-
-
-
-
- ); -}; diff --git a/x-pack/solutions/security/plugins/kubernetes_security/public/components/tree_view_container/helpers.ts b/x-pack/solutions/security/plugins/kubernetes_security/public/components/tree_view_container/helpers.ts deleted file mode 100644 index afb143f7f3840..0000000000000 --- a/x-pack/solutions/security/plugins/kubernetes_security/public/components/tree_view_container/helpers.ts +++ /dev/null @@ -1,80 +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 { - CLOUD_INSTANCE_NAME, - CONTAINER_IMAGE_NAME, - DEFAULT_FILTER_QUERY, - ORCHESTRATOR_CLUSTER_ID, - ORCHESTRATOR_CLUSTER_NAME, - ORCHESTRATOR_NAMESPACE, - ORCHESTRATOR_RESOURCE_ID, -} from '../../../common/constants'; -import type { - QueryDslQueryContainerBool, - KubernetesCollectionMap, - KubernetesCollection, - TreeViewIconProps, -} from '../../types'; - -export const KUBERNETES_COLLECTION_FIELDS: KubernetesCollectionMap = { - clusterId: ORCHESTRATOR_CLUSTER_ID, - clusterName: ORCHESTRATOR_CLUSTER_NAME, - namespace: ORCHESTRATOR_NAMESPACE, - node: CLOUD_INSTANCE_NAME, - pod: ORCHESTRATOR_RESOURCE_ID, - containerImage: CONTAINER_IMAGE_NAME, -}; - -export const KUBERNETES_COLLECTION_ICONS_PROPS: KubernetesCollectionMap = { - clusterId: { type: 'cluster', euiVarColor: 'euiColorVis0' }, - clusterName: { type: 'cluster', euiVarColor: 'euiColorVis0' }, - namespace: { type: 'namespace', euiVarColor: 'euiColorVis1' }, - node: { type: 'kubernetesNode', euiVarColor: 'euiColorVis3' }, - pod: { type: 'kubernetesPod', euiVarColor: 'euiColorVis9' }, - containerImage: { type: 'container', euiVarColor: 'euiColorVis8' }, -}; - -export const addTreeNavSelectionToFilterQuery = ( - filterQuery: string | undefined, - treeNavSelection: Partial -) => { - let validFilterQuery = DEFAULT_FILTER_QUERY; - - try { - const parsedFilterQuery: QueryDslQueryContainerBool = JSON.parse(filterQuery || '{}'); - if (!(parsedFilterQuery?.bool?.filter && Array.isArray(parsedFilterQuery.bool.filter))) { - throw new Error('Invalid filter query'); - } - - parsedFilterQuery.bool.filter.push( - ...Object.entries(treeNavSelection) - .filter(([key]) => (key as KubernetesCollection) !== 'clusterName') - .map((obj) => { - const [key, value] = obj as [KubernetesCollection, string]; - - return { - bool: { - should: [ - { - match: { - [KUBERNETES_COLLECTION_FIELDS[key]]: value, - }, - }, - ], - }, - }; - }) - ); - - validFilterQuery = JSON.stringify(parsedFilterQuery); - } catch { - // no-op since validFilterQuery is initialized to be DEFAULT_FILTER_QUERY - } - - return validFilterQuery; -}; diff --git a/x-pack/solutions/security/plugins/kubernetes_security/public/components/tree_view_container/hooks.tsx b/x-pack/solutions/security/plugins/kubernetes_security/public/components/tree_view_container/hooks.tsx deleted file mode 100644 index a86b03f866b81..0000000000000 --- a/x-pack/solutions/security/plugins/kubernetes_security/public/components/tree_view_container/hooks.tsx +++ /dev/null @@ -1,57 +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 { useCallback, useMemo, useState } from 'react'; -import useLocalStorage from 'react-use/lib/useLocalStorage'; -import type { KubernetesCollectionMap } from '../../types'; -import { LOCAL_STORAGE_TREE_NAV_KEY } from '../../../common/constants'; -import { addTimerangeAndDefaultFilterToQuery } from '../../utils/add_timerange_and_default_filter_to_query'; -import { addTreeNavSelectionToFilterQuery } from './helpers'; -import { IndexPattern, GlobalFilter } from '../../types'; - -export type UseTreeViewProps = { - globalFilter: GlobalFilter; - indexPattern?: IndexPattern; -}; - -export const useTreeView = ({ globalFilter, indexPattern }: UseTreeViewProps) => { - const [noResults, setNoResults] = useState(false); - const [treeNavSelection = {}, setTreeNavSelection] = useLocalStorage< - Partial - >(LOCAL_STORAGE_TREE_NAV_KEY, {}); - const filterQueryWithTimeRange = useMemo(() => { - return JSON.parse( - addTimerangeAndDefaultFilterToQuery( - globalFilter.filterQuery, - globalFilter.startDate, - globalFilter.endDate - ) - ); - }, [globalFilter.filterQuery, globalFilter.startDate, globalFilter.endDate]); - - const onTreeNavSelect = useCallback( - (selection: Partial) => { - setTreeNavSelection(selection); - }, - [setTreeNavSelection] - ); - - const sessionViewFilter = useMemo( - () => addTreeNavSelectionToFilterQuery(globalFilter.filterQuery, treeNavSelection), - [globalFilter.filterQuery, treeNavSelection] - ); - - return { - noResults, - setNoResults, - filterQueryWithTimeRange, - indexPattern: indexPattern?.title || '', - onTreeNavSelect, - treeNavSelection, - setTreeNavSelection, - sessionViewFilter, - }; -}; diff --git a/x-pack/solutions/security/plugins/kubernetes_security/public/components/tree_view_container/index.test.tsx b/x-pack/solutions/security/plugins/kubernetes_security/public/components/tree_view_container/index.test.tsx deleted file mode 100644 index be1aa764c4833..0000000000000 --- a/x-pack/solutions/security/plugins/kubernetes_security/public/components/tree_view_container/index.test.tsx +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React from 'react'; -import { TreeViewContainer } from '.'; -import { DEFAULT_FILTER_QUERY } from '../../../common/constants'; -import { AppContextTestRender, createAppRootMockRenderer } from '../../test'; -import * as context from './contexts'; - -describe('TreeNav component', () => { - let render: () => ReturnType; - let renderResult: ReturnType; - let mockedContext: AppContextTestRender; - const spy = jest.spyOn(context, 'useTreeViewContext'); - - const defaultProps = { - globalFilter: { - filterQuery: DEFAULT_FILTER_QUERY, - startDate: Date.now().toString(), - endDate: (Date.now() + 1).toString(), - }, - renderSessionsView: () =>
Session View
, - } as any; - - beforeEach(() => { - mockedContext = createAppRootMockRenderer(); - }); - afterEach(() => { - spy.mockRestore(); - }); - - it('shows empty message when there is no results', () => { - spy.mockImplementation(() => ({ - ...jest.requireActual('./contexts').useTreeViewContext, - noResults: true, - treeNavSelection: {}, - })); - - renderResult = mockedContext.render(); - expect(renderResult.getByText(/no results/i)).toBeInTheDocument(); - }); -}); diff --git a/x-pack/solutions/security/plugins/kubernetes_security/public/components/tree_view_container/index.tsx b/x-pack/solutions/security/plugins/kubernetes_security/public/components/tree_view_container/index.tsx deleted file mode 100644 index c3033394385ab..0000000000000 --- a/x-pack/solutions/security/plugins/kubernetes_security/public/components/tree_view_container/index.tsx +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React from 'react'; -import { EuiSplitPanel, EuiText } from '@elastic/eui'; -import { useStyles } from './styles'; -import { IndexPattern, GlobalFilter } from '../../types'; -import { TreeNav } from './tree_nav'; -import { Breadcrumb } from './breadcrumb'; -import { TreeViewContextProvider, useTreeViewContext } from './contexts'; -import { EmptyState } from './empty_state'; - -export interface TreeViewContainerComponentDeps { - renderSessionsView: (sessionsFilterQuery: string | undefined) => JSX.Element; -} -export interface TreeViewContainerDeps extends TreeViewContainerComponentDeps { - globalFilter: GlobalFilter; - indexPattern?: IndexPattern; -} - -export const TreeViewContainer = ({ - globalFilter, - renderSessionsView, - indexPattern, -}: TreeViewContainerDeps) => { - return ( - - - - ); -}; - -const TreeViewContainerComponent = ({ renderSessionsView }: TreeViewContainerComponentDeps) => { - const styles = useStyles(); - - const { treeNavSelection, sessionViewFilter, onTreeNavSelect, noResults } = useTreeViewContext(); - - return ( - - {noResults && } - - - - ); -}; diff --git a/x-pack/solutions/security/plugins/kubernetes_security/public/components/tree_view_container/mocks.ts b/x-pack/solutions/security/plugins/kubernetes_security/public/components/tree_view_container/mocks.ts deleted file mode 100644 index 7b1e098151e5e..0000000000000 --- a/x-pack/solutions/security/plugins/kubernetes_security/public/components/tree_view_container/mocks.ts +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -export const clusterResponseMock = { - buckets: [ - { - key: ['awp-demo-gke-main', 'awp-demo-gke-main'], - key_as_string: 'awp-demo-gke-main|awp-demo-gke-main', - doc_count: 22279, - }, - { - key: ['awp-demo-gke-test', ''], - key_as_string: 'awp-demo-gke-test|', - doc_count: 1, - }, - ], - hasNextPage: false, -}; - -export const nodeResponseMock = { - buckets: [ - { key: 'default', doc_count: 236 }, - { key: 'kube-system', doc_count: 30360 }, - { key: 'production', doc_count: 30713 }, - { key: 'qa', doc_count: 412 }, - { key: 'staging', doc_count: 220 }, - ], - hasNextPage: false, -}; diff --git a/x-pack/solutions/security/plugins/kubernetes_security/public/components/tree_view_container/styles.ts b/x-pack/solutions/security/plugins/kubernetes_security/public/components/tree_view_container/styles.ts deleted file mode 100644 index 61d69b32fad7b..0000000000000 --- a/x-pack/solutions/security/plugins/kubernetes_security/public/components/tree_view_container/styles.ts +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { useMemo } from 'react'; -import { CSSObject } from '@emotion/react'; -import { useEuiTheme } from '../../hooks'; - -export const useStyles = () => { - const { euiTheme } = useEuiTheme(); - - const cached = useMemo(() => { - const { border } = euiTheme; - - const outerPanel: CSSObject = { - minHeight: '262px', - }; - - const navPanel: CSSObject = { - borderRight: border.thin, - }; - - const sessionsPanel: CSSObject = { - overflowX: 'auto', - }; - - return { - outerPanel, - navPanel, - sessionsPanel, - }; - }, [euiTheme]); - - return cached; -}; diff --git a/x-pack/solutions/security/plugins/kubernetes_security/public/components/tree_view_container/translations.ts b/x-pack/solutions/security/plugins/kubernetes_security/public/components/tree_view_container/translations.ts deleted file mode 100644 index 71da8e78a23ba..0000000000000 --- a/x-pack/solutions/security/plugins/kubernetes_security/public/components/tree_view_container/translations.ts +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { i18n } from '@kbn/i18n'; - -export const BREADCRUMBS_CLUSTER_TREE_VIEW_LEVELS = { - clusterId: i18n.translate('xpack.kubernetesSecurity.treeView.breadcrumb.clusterId', { - defaultMessage: 'Cluster', - }), - clusterName: i18n.translate('xpack.kubernetesSecurity.treeView.breadcrumb.clusterName', { - defaultMessage: 'Cluster', - }), - namespace: i18n.translate('xpack.kubernetesSecurity.treeView.breadcrumb.namespace', { - defaultMessage: 'Namespace', - }), - node: i18n.translate('xpack.kubernetesSecurity.treeView.breadcrumb.node', { - defaultMessage: 'Node', - }), - pod: i18n.translate('xpack.kubernetesSecurity.treeView.breadcrumb.pod', { - defaultMessage: 'Pod', - }), - containerImage: i18n.translate('xpack.kubernetesSecurity.treeView.breadcrumb.containerImage', { - defaultMessage: 'Container Image', - }), -}; diff --git a/x-pack/solutions/security/plugins/kubernetes_security/public/components/tree_view_container/tree_nav/constants.ts b/x-pack/solutions/security/plugins/kubernetes_security/public/components/tree_view_container/tree_nav/constants.ts deleted file mode 100644 index c1b43bed1fd49..0000000000000 --- a/x-pack/solutions/security/plugins/kubernetes_security/public/components/tree_view_container/tree_nav/constants.ts +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import type { DynamicTree } from '../../../types'; -import { KUBERNETES_COLLECTION_FIELDS, KUBERNETES_COLLECTION_ICONS_PROPS } from '../helpers'; -import { translations } from './translations'; - -const LOGICAL_TREE_VIEW: DynamicTree[] = [ - { - key: KUBERNETES_COLLECTION_FIELDS.clusterId, - iconProps: KUBERNETES_COLLECTION_ICONS_PROPS.clusterId, - type: 'clusterId', - name: translations.cluster(), - namePlural: translations.cluster(true), - }, - { - key: KUBERNETES_COLLECTION_FIELDS.namespace, - iconProps: KUBERNETES_COLLECTION_ICONS_PROPS.namespace, - type: 'namespace', - name: translations.namespace(), - namePlural: translations.namespace(true), - }, - { - key: KUBERNETES_COLLECTION_FIELDS.pod, - iconProps: KUBERNETES_COLLECTION_ICONS_PROPS.pod, - type: 'pod', - name: translations.pod(), - namePlural: translations.pod(true), - }, - { - key: KUBERNETES_COLLECTION_FIELDS.containerImage, - iconProps: KUBERNETES_COLLECTION_ICONS_PROPS.containerImage, - type: 'containerImage', - name: translations.containerImage(), - namePlural: translations.containerImage(true), - }, -]; - -const INFRASTRUCTURE_TREE_VIEW: DynamicTree[] = LOGICAL_TREE_VIEW.map((tree, index) => { - if (index === 1) { - return { - key: KUBERNETES_COLLECTION_FIELDS.node, - iconProps: KUBERNETES_COLLECTION_ICONS_PROPS.node, - type: 'node', - name: translations.node(), - namePlural: translations.node(true), - }; - } - return tree; -}); - -export const TREE_VIEW = { - logical: LOGICAL_TREE_VIEW, - infrastructure: INFRASTRUCTURE_TREE_VIEW, -}; - -export const INFRASTRUCTURE = 'infrastructure'; -export const LOGICAL = 'logical'; diff --git a/x-pack/solutions/security/plugins/kubernetes_security/public/components/tree_view_container/tree_nav/index.test.tsx b/x-pack/solutions/security/plugins/kubernetes_security/public/components/tree_view_container/tree_nav/index.test.tsx deleted file mode 100644 index 155f4236f8107..0000000000000 --- a/x-pack/solutions/security/plugins/kubernetes_security/public/components/tree_view_container/tree_nav/index.test.tsx +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React from 'react'; -import { AppContextTestRender, createAppRootMockRenderer } from '../../../test'; -import { clusterResponseMock } from '../mocks'; -import { TreeNav } from '.'; -import { TreeViewContextProvider } from '../contexts'; - -describe('TreeNav component', () => { - let render: () => ReturnType; - let renderResult: ReturnType; - let mockedContext: AppContextTestRender; - let mockedApi: AppContextTestRender['coreStart']['http']['get']; - - const defaultProps = { - globalFilter: { - startDate: Date.now().toString(), - endDate: (Date.now() + 1).toString(), - }, - onSelect: () => {}, - hasSelection: false, - }; - - const TreeNavContainer = () => ( - - - - ); - - beforeEach(() => { - mockedContext = createAppRootMockRenderer(); - mockedApi = mockedContext.coreStart.http.get; - mockedApi.mockResolvedValue(clusterResponseMock); - }); - - it('mount with Logical View selected by default', async () => { - renderResult = mockedContext.render(); - const elemLabel = await renderResult.getByTestId('treeNavType_generated-idlogical'); - expect(elemLabel).toHaveAttribute('aria-pressed', 'true'); - }); - - it('shows the tree path according with the selected view type', async () => { - renderResult = mockedContext.render(); - - const logicalViewPath = 'cluster / namespace / pod / container image'; - const logicViewButton = renderResult.getByTestId('treeNavType_generated-idlogical'); - expect(logicViewButton).toHaveAttribute('aria-pressed', 'true'); - expect(renderResult.getByText(logicalViewPath)).toBeInTheDocument(); - - const infraStructureViewRadio = renderResult.getByTestId( - 'treeNavType_generated-idinfrastructure' - ); - infraStructureViewRadio.click(); - - expect(renderResult.getByText('cluster / node / pod / container image')).toBeInTheDocument(); - - logicViewButton.click(); - expect(renderResult.getByText(logicalViewPath)).toBeInTheDocument(); - }); - - it('collapses / expands the tree nav when clicking on collapse button', async () => { - renderResult = mockedContext.render(); - - expect(renderResult.getByText(/cluster/i)).toBeVisible(); - - const collapseButton = await renderResult.getByLabelText(/collapse/i); - collapseButton.click(); - expect(renderResult.getByText(/cluster/i)).not.toBeVisible(); - - const expandButton = await renderResult.getByLabelText(/expand/i); - expandButton.click(); - expect(renderResult.getByText(/cluster/i)).toBeVisible(); - }); -}); diff --git a/x-pack/solutions/security/plugins/kubernetes_security/public/components/tree_view_container/tree_nav/index.tsx b/x-pack/solutions/security/plugins/kubernetes_security/public/components/tree_view_container/tree_nav/index.tsx deleted file mode 100644 index 9060cb8e46b87..0000000000000 --- a/x-pack/solutions/security/plugins/kubernetes_security/public/components/tree_view_container/tree_nav/index.tsx +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ -import React, { useState, useMemo, useCallback } from 'react'; -import { - EuiButtonGroup, - useGeneratedHtmlId, - EuiText, - EuiSpacer, - EuiButtonIcon, - EuiFlexGroup, - EuiFlexItem, - EuiToolTip, -} from '@elastic/eui'; -import { - TREE_VIEW_INFRASTRUCTURE_VIEW, - TREE_VIEW_LOGICAL_VIEW, - TREE_VIEW_SWITCHER_LEGEND, - TREE_NAVIGATION_COLLAPSE, - TREE_NAVIGATION_EXPAND, -} from '../../../../common/translations'; -import { useStyles } from './styles'; -import { DynamicTreeView } from '../dynamic_tree_view'; -import { INFRASTRUCTURE, LOGICAL, TREE_VIEW } from './constants'; -import { TreeViewKind, TreeViewOptionsGroup } from './types'; -import { useTreeViewContext } from '../contexts'; - -export const TreeNav = () => { - const styles = useStyles(); - const [tree, setTree] = useState(TREE_VIEW.logical); - const { filterQueryWithTimeRange, onTreeNavSelect, treeNavSelection, setTreeNavSelection } = - useTreeViewContext(); - const [isCollapsed, setIsCollapsed] = useState(false); - const treeNavTypePrefix = useGeneratedHtmlId({ - prefix: 'treeNavType', - }); - const logicalTreeViewPrefix = `${treeNavTypePrefix}${LOGICAL}`; - const [toggleIdSelected, setToggleIdSelected] = useState(logicalTreeViewPrefix); - - const selected = useMemo(() => { - return Object.entries(treeNavSelection) - .map(([k, v]) => `${k}.${v}`) - .join(); - }, [treeNavSelection]); - - const handleToggleCollapse = () => { - setIsCollapsed(!isCollapsed); - }; - - const options: TreeViewOptionsGroup[] = useMemo( - () => [ - { - id: logicalTreeViewPrefix, - label: TREE_VIEW_LOGICAL_VIEW, - value: LOGICAL, - }, - { - id: `${treeNavTypePrefix}${INFRASTRUCTURE}`, - label: TREE_VIEW_INFRASTRUCTURE_VIEW, - value: INFRASTRUCTURE, - }, - ], - [logicalTreeViewPrefix, treeNavTypePrefix] - ); - - const handleTreeViewSwitch = useCallback( - (id: string, value: TreeViewKind) => { - setToggleIdSelected(id); - setTree(TREE_VIEW[value]); - setTreeNavSelection({}); - }, - [setTreeNavSelection] - ); - - return ( - <> - {isCollapsed && ( - - - - )} -
- - - - - - - - - - - - - {tree.map((t) => t.name).join(' / ')} - - -
- { - const newSelectionDepth = { - ...selectionDepth, - [type]: key, - ...(clusterName && { clusterName }), - }; - onTreeNavSelect(newSelectionDepth); - }} - /> -
-
- - ); -}; diff --git a/x-pack/solutions/security/plugins/kubernetes_security/public/components/tree_view_container/tree_nav/styles.ts b/x-pack/solutions/security/plugins/kubernetes_security/public/components/tree_view_container/tree_nav/styles.ts deleted file mode 100644 index d915e73ed21d1..0000000000000 --- a/x-pack/solutions/security/plugins/kubernetes_security/public/components/tree_view_container/tree_nav/styles.ts +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { useMemo } from 'react'; -import { CSSObject } from '@emotion/react'; -import { useEuiTheme } from '../../../hooks'; - -export const useStyles = () => { - const { euiTheme } = useEuiTheme(); - - const cached = useMemo(() => { - const { size } = euiTheme; - - const treeViewSwitcher: CSSObject = { - '.euiButton__text': { - fontSize: size.m, - }, - }; - - const treeViewContainer: CSSObject = { - height: '600px', - width: '288px', - overflowY: 'auto', - }; - - const treeViewLegend: CSSObject = { - textTransform: 'capitalize', - }; - - return { - treeViewSwitcher, - treeViewContainer, - treeViewLegend, - }; - }, [euiTheme]); - - return cached; -}; diff --git a/x-pack/solutions/security/plugins/kubernetes_security/public/components/tree_view_container/tree_nav/translations.ts b/x-pack/solutions/security/plugins/kubernetes_security/public/components/tree_view_container/tree_nav/translations.ts deleted file mode 100644 index 2de70a8b42eaa..0000000000000 --- a/x-pack/solutions/security/plugins/kubernetes_security/public/components/tree_view_container/tree_nav/translations.ts +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { i18n } from '@kbn/i18n'; - -const TREE_NAV_CLUSTER = (isPlural = false) => - i18n.translate('xpack.kubernetesSecurity.treeNav.cluster', { - defaultMessage: '{isPlural, select, true {clusters} other {cluster}}', - values: { isPlural }, - }); -const TREE_NAV_NAMESPACE = (isPlural = false) => - i18n.translate('xpack.kubernetesSecurity.treeNav.namespace', { - defaultMessage: '{isPlural, select, true {namespaces} other {namespace}}', - values: { isPlural }, - }); -const TREE_NAV_POD = (isPlural = false) => - i18n.translate('xpack.kubernetesSecurity.treeNav.pod', { - defaultMessage: '{isPlural, select, true {pods} other {pod}}', - values: { isPlural }, - }); -const TREE_NAV_CONTAINER_IMAGE = (isPlural = false) => - i18n.translate('xpack.kubernetesSecurity.treeNav.containerImage', { - defaultMessage: '{isPlural, select, true {container images} other { container image}}', - values: { isPlural }, - }); -const TREE_NAV_NODE = (isPlural = false) => - i18n.translate('xpack.kubernetesSecurity.treeNav.node', { - defaultMessage: '{isPlural, select, true {nodes} other {node}}', - values: { isPlural }, - }); - -export const translations = { - cluster: TREE_NAV_CLUSTER, - namespace: TREE_NAV_NAMESPACE, - pod: TREE_NAV_POD, - containerImage: TREE_NAV_CONTAINER_IMAGE, - node: TREE_NAV_NODE, -}; diff --git a/x-pack/solutions/security/plugins/kubernetes_security/public/components/tree_view_container/tree_view_icon.tsx b/x-pack/solutions/security/plugins/kubernetes_security/public/components/tree_view_container/tree_view_icon.tsx deleted file mode 100644 index 8434caadf817d..0000000000000 --- a/x-pack/solutions/security/plugins/kubernetes_security/public/components/tree_view_container/tree_view_icon.tsx +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ -import React from 'react'; -import { EuiIcon } from '@elastic/eui'; -import { useEuiTheme } from '../../hooks'; -import { TreeViewIconProps } from '../../types'; - -export const TreeViewIcon = ({ euiVarColor, ...props }: TreeViewIconProps) => { - const { euiVars } = useEuiTheme(); - - const colorStyle = euiVars[euiVarColor] ? { style: { color: euiVars[euiVarColor] } } : {}; - - return ; -}; diff --git a/x-pack/solutions/security/plugins/kubernetes_security/public/hooks/index.ts b/x-pack/solutions/security/plugins/kubernetes_security/public/hooks/index.ts deleted file mode 100644 index 2e330dfb1b159..0000000000000 --- a/x-pack/solutions/security/plugins/kubernetes_security/public/hooks/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -export { useEuiTheme } from './use_eui_theme'; -export { useSetFilter } from './use_filter'; -export { useLastUpdated } from './use_last_updated'; -export { useScroll } from './use_scroll'; diff --git a/x-pack/solutions/security/plugins/kubernetes_security/public/hooks/use_eui_theme.ts b/x-pack/solutions/security/plugins/kubernetes_security/public/hooks/use_eui_theme.ts deleted file mode 100644 index 67167f0c0edbc..0000000000000 --- a/x-pack/solutions/security/plugins/kubernetes_security/public/hooks/use_eui_theme.ts +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { shade, useEuiTheme as useEuiThemeHook } from '@elastic/eui'; -import { euiLightVars, euiDarkVars } from '@kbn/ui-theme'; -import { useMemo } from 'react'; - -type EuiThemeProps = Parameters; -type ExtraEuiVars = { - // eslint-disable-next-line @typescript-eslint/naming-convention - euiColorVis6_asText: string; - buttonsBackgroundNormalDefaultPrimary: string; -}; -type EuiVars = typeof euiLightVars & ExtraEuiVars; -type EuiThemeReturn = ReturnType & { euiVars: EuiVars }; - -export type EuiVarsColors = Pick< - ReturnType['euiVars'], - 'euiColorVis0' | 'euiColorVis1' | 'euiColorVis3' | 'euiColorVis8' | 'euiColorVis9' ->; -// Not all Eui Tokens were fully migrated to @elastic/eui/useEuiTheme yet, so -// this hook overrides the default useEuiTheme hook to provide a custom hook that -// allows the use the euiVars tokens from the euiLightVars and euiDarkVars -export const useEuiTheme = (...props: EuiThemeProps): EuiThemeReturn => { - const euiThemeHook = useEuiThemeHook(...props); - - const euiVars = useMemo(() => { - const themeVars = euiThemeHook.colorMode === 'DARK' ? euiDarkVars : euiLightVars; - - const extraEuiVars: ExtraEuiVars = { - // eslint-disable-next-line @typescript-eslint/naming-convention - euiColorVis6_asText: shade(themeVars.euiColorVis6, 0.335), - buttonsBackgroundNormalDefaultPrimary: '#006DE4', - }; - - return { - ...themeVars, - ...extraEuiVars, - }; - }, [euiThemeHook.colorMode]); - - return { - ...euiThemeHook, - euiVars, - }; -}; diff --git a/x-pack/solutions/security/plugins/kubernetes_security/public/hooks/use_filter.ts b/x-pack/solutions/security/plugins/kubernetes_security/public/hooks/use_filter.ts deleted file mode 100644 index 382b66214a189..0000000000000 --- a/x-pack/solutions/security/plugins/kubernetes_security/public/hooks/use_filter.ts +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { useMemo } from 'react'; -import { useKibana } from '@kbn/kibana-react-plugin/public'; -import type { CoreStart } from '@kbn/core/public'; -import type { StartPlugins } from '../types'; - -export const useSetFilter = () => { - const { data, timelines } = useKibana().services; - const { getFilterForValueButton, getFilterOutValueButton, getCopyButton } = - timelines.getHoverActions(); - - const filterManager = useMemo(() => data.query.filterManager, [data.query.filterManager]); - - return { - getFilterForValueButton, - getFilterOutValueButton, - getCopyButton, - filterManager, - }; -}; diff --git a/x-pack/solutions/security/plugins/kubernetes_security/public/hooks/use_last_updated.ts b/x-pack/solutions/security/plugins/kubernetes_security/public/hooks/use_last_updated.ts deleted file mode 100644 index 7879b5a0a1a4a..0000000000000 --- a/x-pack/solutions/security/plugins/kubernetes_security/public/hooks/use_last_updated.ts +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { useMemo } from 'react'; -import { useKibana } from '@kbn/kibana-react-plugin/public'; -import type { CoreStart } from '@kbn/core/public'; -import type { GlobalFilter, StartPlugins } from '../types'; - -export const useLastUpdated = (globalFilter: GlobalFilter) => { - const { timelines: timelinesUi } = useKibana().services; - - // Only reset updated at on refresh or after globalFilter gets updated - // eslint-disable-next-line react-hooks/exhaustive-deps - const updatedAt = useMemo(() => Date.now(), [globalFilter]); - - return timelinesUi.getLastUpdated({ - updatedAt: updatedAt || Date.now(), - }); -}; diff --git a/x-pack/solutions/security/plugins/kubernetes_security/public/hooks/use_scroll.ts b/x-pack/solutions/security/plugins/kubernetes_security/public/hooks/use_scroll.ts deleted file mode 100644 index 716e35dbb0987..0000000000000 --- a/x-pack/solutions/security/plugins/kubernetes_security/public/hooks/use_scroll.ts +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { useEffect } from 'react'; -import _ from 'lodash'; - -const SCROLL_END_BUFFER_HEIGHT = 20; -const DEBOUNCE_TIMEOUT = 500; - -function getScrollPosition(div: HTMLElement) { - if (div) { - return div.scrollTop; - } else { - return document.documentElement.scrollTop || document.body.scrollTop; - } -} - -interface IUseScrollDeps { - div: HTMLElement | null; - handler(pos: number, endReached: boolean): void; -} - -/** - * listens to scroll events on given div, if scroll reaches bottom, calls a callback - * @param {ref} ref to listen to scroll events on - * @param {function} handler function receives params (scrollTop, endReached) - */ -export function useScroll({ div, handler }: IUseScrollDeps) { - useEffect(() => { - if (div) { - const debounced = _.debounce(() => { - const pos = getScrollPosition(div); - const endReached = pos + div.offsetHeight > div.scrollHeight - SCROLL_END_BUFFER_HEIGHT; - - handler(pos, endReached); - }, DEBOUNCE_TIMEOUT); - - div.onscroll = debounced; - - return () => { - debounced.cancel(); - - div.onscroll = null; - }; - } - }, [div, handler]); -} diff --git a/x-pack/solutions/security/plugins/kubernetes_security/public/index.ts b/x-pack/solutions/security/plugins/kubernetes_security/public/index.ts deleted file mode 100644 index 38af73f710dbb..0000000000000 --- a/x-pack/solutions/security/plugins/kubernetes_security/public/index.ts +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { KubernetesSecurityPlugin } from './plugin'; - -export type { KubernetesSecurityStart } from './types'; -export { KUBERNETES_TITLE, KUBERNETES_PATH } from '../common/constants'; - -export function plugin() { - return new KubernetesSecurityPlugin(); -} diff --git a/x-pack/solutions/security/plugins/kubernetes_security/public/methods/index.tsx b/x-pack/solutions/security/plugins/kubernetes_security/public/methods/index.tsx deleted file mode 100644 index 362560c3b1ddf..0000000000000 --- a/x-pack/solutions/security/plugins/kubernetes_security/public/methods/index.tsx +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React, { lazy, Suspense } from 'react'; -import { EuiLoadingSpinner } from '@elastic/eui'; -import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; -import { KubernetesSecurityDeps } from '../types'; - -// Initializing react-query -const queryClient = new QueryClient({ - defaultOptions: { - queries: { - refetchOnWindowFocus: false, - refetchOnMount: false, - refetchOnReconnect: false, - }, - }, -}); - -const KubernetesSecurityLazy = lazy(() => import('../components/kubernetes_security_routes')); - -export const getKubernetesSecurityLazy = (props: KubernetesSecurityDeps) => { - return ( - - }> - - - - ); -}; diff --git a/x-pack/solutions/security/plugins/kubernetes_security/public/plugin.ts b/x-pack/solutions/security/plugins/kubernetes_security/public/plugin.ts deleted file mode 100644 index d80c858abf784..0000000000000 --- a/x-pack/solutions/security/plugins/kubernetes_security/public/plugin.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 { CoreSetup, CoreStart, Plugin } from '@kbn/core/public'; -import { KubernetesSecurityDeps, KubernetesSecurityServices } from './types'; -import { getKubernetesSecurityLazy } from './methods'; - -export type { KubernetesSecurityStart } from './types'; - -export class KubernetesSecurityPlugin implements Plugin { - public setup(core: CoreSetup) {} - - public start(core: CoreStart) { - return { - getKubernetesPage: (kubernetesSecurityDeps: KubernetesSecurityDeps) => - getKubernetesSecurityLazy(kubernetesSecurityDeps), - }; - } - - public stop() {} -} diff --git a/x-pack/solutions/security/plugins/kubernetes_security/public/test/index.tsx b/x-pack/solutions/security/plugins/kubernetes_security/public/test/index.tsx deleted file mode 100644 index 4aeaf93f746cc..0000000000000 --- a/x-pack/solutions/security/plugins/kubernetes_security/public/test/index.tsx +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React, { memo, ReactNode, useMemo } from 'react'; -import { createMemoryHistory, MemoryHistory } from 'history'; -import { render as reactRender, RenderOptions, RenderResult } from '@testing-library/react'; -import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; -import { Router } from '@kbn/shared-ux-router'; -import { History } from 'history'; -import { I18nProvider } from '@kbn/i18n-react'; -import { CoreStart } from '@kbn/core/public'; -import { coreMock } from '@kbn/core/public/mocks'; -import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public'; -import { EuiThemeProvider } from '@kbn/kibana-react-plugin/common'; - -type UiRender = (ui: React.ReactNode, options?: RenderOptions) => RenderResult; - -/** - * Mocked app root context renderer - */ -export interface AppContextTestRender { - history: ReturnType; - coreStart: ReturnType; - /** - * A wrapper around `AppRootContext` component. Uses the mocked modules as input to the - * `AppRootContext` - */ - AppWrapper: React.FC; - /** - * Renders the given UI within the created `AppWrapper` providing the given UI a mocked - * endpoint runtime context environment - */ - render: UiRender; -} - -const createCoreStartMock = ( - history: MemoryHistory -): ReturnType => { - const coreStart = coreMock.createStart({ basePath: '/mock' }); - - // Mock the certain APP Ids returned by `application.getUrlForApp()` - coreStart.application.getUrlForApp.mockImplementation((appId) => { - switch (appId) { - case 'sessionView': - return '/app/sessionView'; - default: - return `${appId} not mocked!`; - } - }); - - coreStart.application.navigateToUrl.mockImplementation((url) => { - history.push(url.replace('/app/sessionView', '')); - return Promise.resolve(); - }); - - return coreStart; -}; - -const AppRootProvider = memo<{ - history: History; - coreStart: CoreStart; - children: ReactNode | ReactNode[]; -}>(({ history, coreStart: { http, notifications, theme, application }, children }) => { - const isDarkMode = useMemo(() => theme.getTheme().darkMode, [theme]); - const services = useMemo( - () => ({ http, notifications, application }), - [application, http, notifications] - ); - return ( - - - - {children} - - - - ); -}); - -AppRootProvider.displayName = 'AppRootProvider'; - -/** - * Creates a mocked app context custom renderer that can be used to render - * component that depend upon the application's surrounding context providers. - * Factory also returns the content that was used to create the custom renderer, allowing - * for further customization. - */ - -export const createAppRootMockRenderer = (): AppContextTestRender => { - const history = createMemoryHistory(); - const coreStart = createCoreStartMock(history); - - const queryClient = new QueryClient({ - defaultOptions: { - queries: { - // turns retries off - retry: false, - // prevent jest did not exit errors - cacheTime: Infinity, - }, - }, - // hide react-query output in console - logger: { - error: () => {}, - // eslint-disable-next-line no-console - log: console.log, - // eslint-disable-next-line no-console - warn: console.warn, - }, - }); - - const AppWrapper: React.FC<{ children: React.ReactNode }> = ({ children }) => ( - - {children} - - ); - - const render: UiRender = (ui, options = {}) => { - return reactRender(ui, { - wrapper: AppWrapper, - ...options, - }); - }; - - return { - history, - coreStart, - AppWrapper, - render, - }; -}; diff --git a/x-pack/solutions/security/plugins/kubernetes_security/public/types.ts b/x-pack/solutions/security/plugins/kubernetes_security/public/types.ts deleted file mode 100644 index 4abd98a4ca937..0000000000000 --- a/x-pack/solutions/security/plugins/kubernetes_security/public/types.ts +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ -import React from 'react'; -import { CoreStart } from '@kbn/core/public'; -import type { DataPublicPluginStart } from '@kbn/data-plugin/public'; -import type { FieldSpec } from '@kbn/data-plugin/common'; -import type { TimelinesUIStart } from '@kbn/timelines-plugin/public'; -import type { SessionViewStart } from '@kbn/session-view-plugin/public'; -import { EuiIconProps } from '@elastic/eui'; -import { BoolQuery } from '@kbn/es-query'; -import { EuiVarsColors } from './hooks/use_eui_theme'; - -export interface StartPlugins { - data: DataPublicPluginStart; - timelines: TimelinesUIStart; - sessionView: SessionViewStart; -} - -export type KubernetesSecurityServices = CoreStart & StartPlugins; - -export interface IndexPattern { - fields: FieldSpec[]; - title: string; -} - -export interface GlobalFilter { - filterQuery?: string; - startDate: string; - endDate: string; -} - -export interface KubernetesSecurityDeps { - filter: React.ReactNode; - renderSessionsView: (sessionsFilterQuery: string | undefined) => JSX.Element; - indexPattern?: IndexPattern; - globalFilter: GlobalFilter; - dataViewId?: string; -} - -export interface KubernetesSecurityStart { - getKubernetesPage: (kubernetesSecurityDeps: KubernetesSecurityDeps) => JSX.Element; -} - -export type QueryDslQueryContainerBool = { - bool: BoolQuery; -}; - -export type KubernetesCollection = - | 'clusterId' - | 'clusterName' - | 'namespace' - | 'node' - | 'pod' - | 'containerImage'; - -export enum KubernetesTreeViewLevels { - clusterId = 'clusterId', - clusterName = 'clusterName', - namespace = 'namespace', - node = 'node', - pod = 'pod', - containerImage = 'containerImage', -} -export type KubernetesCollectionMap = Record; - -export type TreeViewIconProps = { - euiVarColor: keyof EuiVarsColors; -} & EuiIconProps; - -export type DynamicTree = { - key: string; - type: KubernetesCollection; - iconProps: TreeViewIconProps; - name: string; - namePlural: string; -}; diff --git a/x-pack/solutions/security/plugins/kubernetes_security/public/utils/add_commas_to_number.test.ts b/x-pack/solutions/security/plugins/kubernetes_security/public/utils/add_commas_to_number.test.ts deleted file mode 100644 index 03faf16921c1b..0000000000000 --- a/x-pack/solutions/security/plugins/kubernetes_security/public/utils/add_commas_to_number.test.ts +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { addCommasToNumber } from './add_commas_to_number'; - -describe('addCommasToNumber(num)', () => { - it('works for a number without needing a comma', () => { - expect(addCommasToNumber(123)).toEqual('123'); - }); - it('works for a number that needs a comma', () => { - expect(addCommasToNumber(1234)).toEqual('1,234'); - }); - it('works for a number that needs multiple commas', () => { - expect(addCommasToNumber(123456789)).toEqual('123,456,789'); - }); - it('works for negative number', () => { - expect(addCommasToNumber(-10)).toEqual('-10'); - }); - it('works for negative number with commas', () => { - expect(addCommasToNumber(-10000)).toEqual('-10,000'); - }); - it('works for NaN', () => { - expect(addCommasToNumber(NaN)).toEqual('NaN'); - }); - it('works for Infinity', () => { - expect(addCommasToNumber(Infinity)).toEqual('Infinity'); - }); - it('works for zero', () => { - expect(addCommasToNumber(0)).toEqual('0'); - }); -}); diff --git a/x-pack/solutions/security/plugins/kubernetes_security/public/utils/add_commas_to_number.ts b/x-pack/solutions/security/plugins/kubernetes_security/public/utils/add_commas_to_number.ts deleted file mode 100644 index 3e440ab8c9226..0000000000000 --- a/x-pack/solutions/security/plugins/kubernetes_security/public/utils/add_commas_to_number.ts +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -/** - * Add commas as thousands separators to a number. - * - * @param {Number} num - * @return {String} num in string with commas as thousands separaters - */ -export function addCommasToNumber(num: number) { - return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ','); -} diff --git a/x-pack/solutions/security/plugins/kubernetes_security/public/utils/add_timerange_and_default_filter_to_query.test.ts b/x-pack/solutions/security/plugins/kubernetes_security/public/utils/add_timerange_and_default_filter_to_query.test.ts deleted file mode 100644 index 0d58e0956f6df..0000000000000 --- a/x-pack/solutions/security/plugins/kubernetes_security/public/utils/add_timerange_and_default_filter_to_query.test.ts +++ /dev/null @@ -1,49 +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 { DEFAULT_FILTER_QUERY } from '../../common/constants'; -import { addTimerangeAndDefaultFilterToQuery } from './add_timerange_and_default_filter_to_query'; - -const TEST_QUERY = - '{"bool":{"must":[],"filter":[{"bool":{"should":[{"match":{"process.entry_leader.same_as_process":true}}],"minimum_should_match":1}}],"should":[],"must_not":[]}}'; -const TEST_INVALID_QUERY = '{"bool":{"must":['; -const TEST_EMPTY_STRING = ''; -const TEST_DATE = '2022-06-09T22:36:46.628Z'; -const VALID_RESULT = - '{"bool":{"must":[],"filter":[{"bool":{"should":[{"exists":{"field":"orchestrator.cluster.id"}}],"minimum_should_match":1}},{"bool":{"should":[{"match":{"process.entry_leader.same_as_process":true}}],"minimum_should_match":1}},{"range":{"@timestamp":{"gte":"2022-06-09T22:36:46.628Z","lte":"2022-06-09T22:36:46.628Z"}}}],"should":[],"must_not":[]}}'; - -describe('addTimerangeAndDefaultFilterToQuery(query, startDate, endDate)', () => { - it('works for valid query, startDate, and endDate', () => { - expect(addTimerangeAndDefaultFilterToQuery(TEST_QUERY, TEST_DATE, TEST_DATE)).toEqual( - VALID_RESULT - ); - }); - it('works with missing filter in bool', () => { - expect(addTimerangeAndDefaultFilterToQuery('{"bool":{}}', TEST_DATE, TEST_DATE)).toEqual( - '{"bool":{"filter":[{"range":{"@timestamp":{"gte":"2022-06-09T22:36:46.628Z","lte":"2022-06-09T22:36:46.628Z"}}}]}}' - ); - }); - it('returns default query with invalid JSON query', () => { - expect(addTimerangeAndDefaultFilterToQuery(TEST_INVALID_QUERY, TEST_DATE, TEST_DATE)).toEqual( - DEFAULT_FILTER_QUERY - ); - expect(addTimerangeAndDefaultFilterToQuery(TEST_EMPTY_STRING, TEST_DATE, TEST_DATE)).toEqual( - DEFAULT_FILTER_QUERY - ); - expect(addTimerangeAndDefaultFilterToQuery('{}', TEST_DATE, TEST_DATE)).toEqual( - DEFAULT_FILTER_QUERY - ); - }); - it('returns default query with invalid startDate or endDate', () => { - expect(addTimerangeAndDefaultFilterToQuery(TEST_QUERY, TEST_EMPTY_STRING, TEST_DATE)).toEqual( - DEFAULT_FILTER_QUERY - ); - expect(addTimerangeAndDefaultFilterToQuery(TEST_QUERY, TEST_DATE, TEST_EMPTY_STRING)).toEqual( - DEFAULT_FILTER_QUERY - ); - }); -}); diff --git a/x-pack/solutions/security/plugins/kubernetes_security/public/utils/add_timerange_and_default_filter_to_query.ts b/x-pack/solutions/security/plugins/kubernetes_security/public/utils/add_timerange_and_default_filter_to_query.ts deleted file mode 100644 index 5b5eca1b8a4d9..0000000000000 --- a/x-pack/solutions/security/plugins/kubernetes_security/public/utils/add_timerange_and_default_filter_to_query.ts +++ /dev/null @@ -1,56 +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 { DEFAULT_FILTER, DEFAULT_FILTER_QUERY } from '../../common/constants'; - -/** - * Add DEFAULT_FILTER and startDate and endDate filter for '@timestamp' field into query. - * - * Used by frontend components - * - * @param {String | undefined} query Example: '{"bool":{"must":[],"filter":[],"should":[],"must_not":[]}}' - * @param {String} startDate Example: '2022-06-08T18:52:15.532Z' - * @param {String} endDate Example: '2022-06-09T17:52:15.532Z' - * @return {String} Add startDate and endDate as a '@timestamp' range filter in query and return. - * If startDate or endDate is invalid Date string, or that query is not - * in the right format, return a default query. - */ - -export const addTimerangeAndDefaultFilterToQuery = ( - query: string | undefined, - startDate: string, - endDate: string -) => { - if (!(query && !isNaN(Date.parse(startDate)) && !isNaN(Date.parse(endDate)))) { - return DEFAULT_FILTER_QUERY; - } - - try { - const parsedQuery = JSON.parse(query); - if (!parsedQuery.bool) { - throw new Error("Field 'bool' does not exist in query."); - } - - const range = { - range: { - '@timestamp': { - gte: startDate, - lte: endDate, - }, - }, - }; - if (parsedQuery.bool.filter) { - parsedQuery.bool.filter = [DEFAULT_FILTER, ...parsedQuery.bool.filter, range]; - } else { - parsedQuery.bool.filter = [range]; - } - - return JSON.stringify(parsedQuery); - } catch { - return DEFAULT_FILTER_QUERY; - } -}; diff --git a/x-pack/solutions/security/plugins/kubernetes_security/server/index.ts b/x-pack/solutions/security/plugins/kubernetes_security/server/index.ts deleted file mode 100644 index b51098c136ad0..0000000000000 --- a/x-pack/solutions/security/plugins/kubernetes_security/server/index.ts +++ /dev/null @@ -1,13 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { PluginInitializerContext } from '@kbn/core/server'; - -export async function plugin(initializerContext: PluginInitializerContext) { - const { KubernetesSecurityPlugin } = await import('./plugin'); - return new KubernetesSecurityPlugin(initializerContext); -} diff --git a/x-pack/solutions/security/plugins/kubernetes_security/server/plugin.ts b/x-pack/solutions/security/plugins/kubernetes_security/server/plugin.ts deleted file mode 100644 index d257836a79498..0000000000000 --- a/x-pack/solutions/security/plugins/kubernetes_security/server/plugin.ts +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { - CoreSetup, - CoreStart, - Plugin, - Logger, - PluginInitializerContext, - IRouter, -} from '@kbn/core/server'; -import { KubernetesSecuritySetupPlugins, KubernetesSecurityStartPlugins } from './types'; -import { registerRoutes } from './routes'; - -export class KubernetesSecurityPlugin implements Plugin { - private logger: Logger; - private router: IRouter | undefined; - - /** - * Initialize KubernetesSecurityPlugin class properties (logger, etc) that is accessible - * through the initializerContext. - */ - constructor(initializerContext: PluginInitializerContext) { - this.logger = initializerContext.logger.get(); - } - - public setup(core: CoreSetup, plugins: KubernetesSecuritySetupPlugins) { - this.logger.debug('kubernetes security: Setup'); - this.router = core.http.createRouter(); - } - - public start(core: CoreStart, plugins: KubernetesSecurityStartPlugins) { - this.logger.debug('kubernetes security: Start'); - - // Register server routes - if (this.router) { - registerRoutes(this.router, this.logger, plugins.ruleRegistry); - } - } - - public stop() { - this.logger.debug('kubernetes security: Stop'); - } -} diff --git a/x-pack/solutions/security/plugins/kubernetes_security/server/routes/aggregate.ts b/x-pack/solutions/security/plugins/kubernetes_security/server/routes/aggregate.ts deleted file mode 100644 index 21bc8dada43e3..0000000000000 --- a/x-pack/solutions/security/plugins/kubernetes_security/server/routes/aggregate.ts +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ -import type { SortCombinations } from '@elastic/elasticsearch/lib/api/types'; -import { transformError } from '@kbn/securitysolution-es-utils'; -import { schema } from '@kbn/config-schema'; -import type { ElasticsearchClient } from '@kbn/core/server'; -import { IRouter, Logger } from '@kbn/core/server'; -import { - AGGREGATE_ROUTE, - AGGREGATE_PAGE_SIZE, - AGGREGATE_MAX_BUCKETS, - ORCHESTRATOR_CLUSTER_ID, - ORCHESTRATOR_RESOURCE_ID, - ORCHESTRATOR_NAMESPACE, - ORCHESTRATOR_CLUSTER_NAME, - CONTAINER_IMAGE_NAME, - CLOUD_INSTANCE_NAME, - ENTRY_LEADER_ENTITY_ID, - ENTRY_LEADER_USER_ID, - ENTRY_LEADER_INTERACTIVE, -} from '../../common/constants'; -import { AggregateBucketPaginationResult } from '../../common/types'; - -// sort by values -const ASC = 'asc'; -const DESC = 'desc'; - -export const registerAggregateRoute = (router: IRouter, logger: Logger) => { - router.versioned - .get({ - access: 'internal', - path: AGGREGATE_ROUTE, - }) - .addVersion( - { - version: '1', - security: { - authz: { - requiredPrivileges: ['securitySolution'], - }, - }, - validate: { - request: { - query: schema.object({ - index: schema.string(), - query: schema.string(), - countBy: schema.maybe( - schema.oneOf([ - schema.literal(ORCHESTRATOR_CLUSTER_ID), - schema.literal(ORCHESTRATOR_RESOURCE_ID), - schema.literal(ORCHESTRATOR_NAMESPACE), - schema.literal(ORCHESTRATOR_CLUSTER_NAME), - schema.literal(CLOUD_INSTANCE_NAME), - schema.literal(CONTAINER_IMAGE_NAME), - schema.literal(ENTRY_LEADER_ENTITY_ID), - ]) - ), - groupBy: schema.oneOf([ - schema.literal(ORCHESTRATOR_CLUSTER_ID), - schema.literal(ORCHESTRATOR_RESOURCE_ID), - schema.literal(ORCHESTRATOR_NAMESPACE), - schema.literal(ORCHESTRATOR_CLUSTER_NAME), - schema.literal(CLOUD_INSTANCE_NAME), - schema.literal(CONTAINER_IMAGE_NAME), - schema.literal(ENTRY_LEADER_USER_ID), - schema.literal(ENTRY_LEADER_INTERACTIVE), - ]), - page: schema.number({ defaultValue: 0, max: 10000, min: 0 }), - perPage: schema.maybe(schema.number({ defaultValue: 10, max: 100, min: 1 })), - sortByCount: schema.maybe(schema.oneOf([schema.literal(ASC), schema.literal(DESC)])), - }), - }, - }, - }, - async (context, request, response) => { - const client = (await context.core).elasticsearch.client.asCurrentUser; - const { query, countBy, sortByCount, groupBy, page, perPage, index } = request.query; - - try { - const body = await doSearch( - client, - index, - query, - groupBy, - page, - perPage, - countBy, - sortByCount - ); - - return response.ok({ body }); - } catch (err) { - const error = transformError(err); - logger.error(`Failed to fetch k8s aggregates: ${err}`); - - return response.customError({ - body: { message: error.message }, - statusCode: error.statusCode, - }); - } - } - ); -}; - -export const doSearch = async ( - client: ElasticsearchClient, - index: string, - query: string, - groupBy: string, - page: number, // zero based - perPage = AGGREGATE_PAGE_SIZE, - countBy?: string, - sortByCount?: string -): Promise => { - const queryDSL = JSON.parse(query); - - const countByAggs = countBy - ? { - count_by_aggs: { - cardinality: { - field: countBy, - }, - }, - } - : undefined; - - let sort: SortCombinations = { _key: { order: ASC } }; - if (sortByCount === ASC || sortByCount === DESC) { - sort = { 'count_by_aggs.value': { order: sortByCount } }; - } - - const search = await client.search({ - index: [index], - body: { - query: queryDSL, - size: 0, - aggs: { - custom_agg: { - terms: { - field: groupBy, - size: AGGREGATE_MAX_BUCKETS, - }, - aggs: { - ...countByAggs, - bucket_sort: { - bucket_sort: { - sort: [sort], // defaulting to alphabetic sort - size: perPage + 1, // check if there's a "next page" - from: perPage * page, - }, - }, - }, - }, - }, - }, - }); - - const agg: any = search.aggregations?.custom_agg; - const buckets = agg?.buckets || []; - - const hasNextPage = buckets.length > perPage; - - if (hasNextPage) { - buckets.pop(); - } - - return { - buckets, - hasNextPage, - }; -}; diff --git a/x-pack/solutions/security/plugins/kubernetes_security/server/routes/count.ts b/x-pack/solutions/security/plugins/kubernetes_security/server/routes/count.ts deleted file mode 100644 index b73452e8e45fc..0000000000000 --- a/x-pack/solutions/security/plugins/kubernetes_security/server/routes/count.ts +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ -import { schema } from '@kbn/config-schema'; -import { transformError } from '@kbn/securitysolution-es-utils'; -import type { ElasticsearchClient } from '@kbn/core/server'; -import { IRouter, Logger } from '@kbn/core/server'; -import { - COUNT_ROUTE, - ORCHESTRATOR_CLUSTER_ID, - ORCHESTRATOR_RESOURCE_ID, - ORCHESTRATOR_NAMESPACE, - ORCHESTRATOR_CLUSTER_NAME, - CONTAINER_IMAGE_NAME, - CLOUD_INSTANCE_NAME, - ENTRY_LEADER_ENTITY_ID, -} from '../../common/constants'; - -export const registerCountRoute = (router: IRouter, logger: Logger) => { - router.versioned - .get({ - access: 'internal', - path: COUNT_ROUTE, - }) - .addVersion( - { - version: '1', - security: { - authz: { - requiredPrivileges: ['securitySolution'], - }, - }, - validate: { - request: { - query: schema.object({ - index: schema.string(), - query: schema.string(), - field: schema.oneOf([ - schema.literal(ORCHESTRATOR_CLUSTER_ID), - schema.literal(ORCHESTRATOR_RESOURCE_ID), - schema.literal(ORCHESTRATOR_NAMESPACE), - schema.literal(ORCHESTRATOR_CLUSTER_NAME), - schema.literal(CLOUD_INSTANCE_NAME), - schema.literal(CONTAINER_IMAGE_NAME), - schema.literal(CONTAINER_IMAGE_NAME), - schema.literal(ENTRY_LEADER_ENTITY_ID), - ]), - }), - }, - }, - }, - async (context, request, response) => { - const client = (await context.core).elasticsearch.client.asCurrentUser; - const { query, field, index } = request.query; - - try { - const body = await doCount(client, index, query, field); - - return response.ok({ body }); - } catch (err) { - const error = transformError(err); - logger.error(`Failed to fetch k8s counts: ${err}`); - - return response.customError({ - body: { message: error.message }, - statusCode: error.statusCode, - }); - } - } - ); -}; - -export const doCount = async ( - client: ElasticsearchClient, - index: string, - query: string, - field: string -) => { - const queryDSL = JSON.parse(query); - - const search = await client.search({ - index: [index], - body: { - query: queryDSL, - size: 0, - aggs: { - custom_count: { - cardinality: { - field, - }, - }, - }, - }, - }); - - const agg: any = search.aggregations?.custom_count; - - return agg?.value || 0; -}; diff --git a/x-pack/solutions/security/plugins/kubernetes_security/server/routes/index.ts b/x-pack/solutions/security/plugins/kubernetes_security/server/routes/index.ts deleted file mode 100644 index 4cf2a53b6c0b0..0000000000000 --- a/x-pack/solutions/security/plugins/kubernetes_security/server/routes/index.ts +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ -import { IRouter, Logger } from '@kbn/core/server'; -import { RuleRegistryPluginStartContract } from '@kbn/rule-registry-plugin/server'; -import { registerAggregateRoute } from './aggregate'; -import { registerCountRoute } from './count'; -import { registerMultiTermsAggregateRoute } from './multi_terms_aggregate'; - -export const registerRoutes = ( - router: IRouter, - logger: Logger, - ruleRegistry: RuleRegistryPluginStartContract -) => { - registerAggregateRoute(router, logger); - registerCountRoute(router, logger); - registerMultiTermsAggregateRoute(router, logger); -}; diff --git a/x-pack/solutions/security/plugins/kubernetes_security/server/routes/multi_terms_aggregate.ts b/x-pack/solutions/security/plugins/kubernetes_security/server/routes/multi_terms_aggregate.ts deleted file mode 100644 index b4a0271b63edc..0000000000000 --- a/x-pack/solutions/security/plugins/kubernetes_security/server/routes/multi_terms_aggregate.ts +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ -import { schema } from '@kbn/config-schema'; -import { transformError } from '@kbn/securitysolution-es-utils'; -import type { ElasticsearchClient } from '@kbn/core/server'; -import { IRouter, Logger } from '@kbn/core/server'; -import { - MULTI_TERMS_AGGREGATE_ROUTE, - AGGREGATE_PAGE_SIZE, - ORCHESTRATOR_CLUSTER_ID, - ORCHESTRATOR_RESOURCE_ID, - ORCHESTRATOR_NAMESPACE, - ORCHESTRATOR_CLUSTER_NAME, - CONTAINER_IMAGE_NAME, - CLOUD_INSTANCE_NAME, - ENTRY_LEADER_ENTITY_ID, - ENTRY_LEADER_USER_ID, - ENTRY_LEADER_INTERACTIVE, -} from '../../common/constants'; -import { - MultiTermsAggregateGroupBy, - MultiTermsAggregateBucketPaginationResult, -} from '../../common/types'; - -export const registerMultiTermsAggregateRoute = (router: IRouter, logger: Logger) => { - router.versioned - .get({ - access: 'internal', - path: MULTI_TERMS_AGGREGATE_ROUTE, - }) - .addVersion( - { - version: '1', - security: { - authz: { - requiredPrivileges: ['securitySolution'], - }, - }, - validate: { - request: { - query: schema.object({ - index: schema.string(), - query: schema.string(), - countBy: schema.maybe( - schema.oneOf([ - schema.literal(ORCHESTRATOR_CLUSTER_ID), - schema.literal(ORCHESTRATOR_RESOURCE_ID), - schema.literal(ORCHESTRATOR_NAMESPACE), - schema.literal(ORCHESTRATOR_CLUSTER_NAME), - schema.literal(CLOUD_INSTANCE_NAME), - schema.literal(CONTAINER_IMAGE_NAME), - schema.literal(ENTRY_LEADER_ENTITY_ID), - ]) - ), - groupBys: schema.arrayOf( - schema.object({ - field: schema.oneOf([ - schema.literal(ORCHESTRATOR_CLUSTER_ID), - schema.literal(ORCHESTRATOR_RESOURCE_ID), - schema.literal(ORCHESTRATOR_NAMESPACE), - schema.literal(ORCHESTRATOR_CLUSTER_NAME), - schema.literal(CLOUD_INSTANCE_NAME), - schema.literal(CONTAINER_IMAGE_NAME), - schema.literal(ENTRY_LEADER_USER_ID), - schema.literal(ENTRY_LEADER_INTERACTIVE), - ]), - missing: schema.maybe(schema.string()), - }), - { defaultValue: [] } - ), - page: schema.number({ max: 10000, min: 0 }), - perPage: schema.maybe(schema.number({ max: 100, min: 1 })), - }), - }, - }, - }, - async (context, request, response) => { - const client = (await context.core).elasticsearch.client.asCurrentUser; - const { query, countBy, groupBys, page, perPage, index } = request.query; - - try { - const body = await doSearch(client, index, query, groupBys, page, perPage, countBy); - - return response.ok({ body }); - } catch (err) { - const error = transformError(err); - logger.error(`Failed to fetch k8s multi_terms_aggregate: ${err}`); - - return response.customError({ - body: { message: error.message }, - statusCode: error.statusCode, - }); - } - } - ); -}; - -export const doSearch = async ( - client: ElasticsearchClient, - index: string, - query: string, - groupBys: MultiTermsAggregateGroupBy[], - page: number, // zero based - perPage = AGGREGATE_PAGE_SIZE, - countBy?: string -): Promise => { - const queryDSL = JSON.parse(query); - - const countByAggs = countBy - ? { - count_by_aggs: { - cardinality: { - field: countBy, - }, - }, - count_alerts: { - cardinality: { - field: countBy, - }, - }, - } - : undefined; - - const search = await client.search({ - index: [index], - body: { - query: queryDSL, - size: 0, - aggs: { - custom_agg: { - multi_terms: { - terms: groupBys, - }, - aggs: { - ...countByAggs, - bucket_sort: { - bucket_sort: { - size: perPage + 1, // check if there's a "next page" - from: perPage * page, - }, - }, - }, - }, - }, - }, - }); - - const agg: any = search.aggregations?.custom_agg; - const buckets = agg?.buckets || []; - - const hasNextPage = buckets.length > perPage; - - if (hasNextPage) { - buckets.pop(); - } - - return { - buckets, - hasNextPage, - }; -}; diff --git a/x-pack/solutions/security/plugins/kubernetes_security/server/types.ts b/x-pack/solutions/security/plugins/kubernetes_security/server/types.ts deleted file mode 100644 index 3c10f35bc3239..0000000000000 --- a/x-pack/solutions/security/plugins/kubernetes_security/server/types.ts +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ -import { - RuleRegistryPluginSetupContract as RuleRegistryPluginSetup, - RuleRegistryPluginStartContract as RuleRegistryPluginStart, -} from '@kbn/rule-registry-plugin/server'; - -export interface KubernetesSecuritySetupPlugins { - ruleRegistry: RuleRegistryPluginSetup; -} - -export interface KubernetesSecurityStartPlugins { - ruleRegistry: RuleRegistryPluginStart; -} diff --git a/x-pack/solutions/security/plugins/kubernetes_security/tsconfig.json b/x-pack/solutions/security/plugins/kubernetes_security/tsconfig.json deleted file mode 100644 index 3acc6db4c9bd7..0000000000000 --- a/x-pack/solutions/security/plugins/kubernetes_security/tsconfig.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "extends": "../../../../../tsconfig.base.json", - "compilerOptions": { - "outDir": "target/types", - }, - "include": [ - // add all the folders containg files to be compiled - "common/**/*", - "public/**/*", - "server/**/*", - "server/**/*.json", - "scripts/**/*", - "package.json", - "storybook/**/*", - "../../../../../typings/**/*" - ], - "kbn_references": [ - "@kbn/core", - // add references to other TypeScript projects the plugin depends on - - // requiredPlugins from ./kibana.json - "@kbn/data-plugin", - - // optionalPlugins from ./kibana.json - - // requiredBundles from ./kibana.json - "@kbn/kibana-react-plugin", - "@kbn/rule-registry-plugin", - "@kbn/session-view-plugin", - "@kbn/i18n", - "@kbn/timelines-plugin", - "@kbn/es-query", - "@kbn/ui-theme", - "@kbn/i18n-react", - "@kbn/config-schema", - "@kbn/shared-ux-router", - "@kbn/securitysolution-es-utils", - ], - "exclude": [ - "target/**/*", - ] -} diff --git a/x-pack/solutions/security/plugins/security_solution/common/api/detection_engine/rule_monitoring/model/execution_metrics.gen.ts b/x-pack/solutions/security/plugins/security_solution/common/api/detection_engine/rule_monitoring/model/execution_metrics.gen.ts index 120272115dd2a..30891cb8f7927 100644 --- a/x-pack/solutions/security/plugins/security_solution/common/api/detection_engine/rule_monitoring/model/execution_metrics.gen.ts +++ b/x-pack/solutions/security/plugins/security_solution/common/api/detection_engine/rule_monitoring/model/execution_metrics.gen.ts @@ -34,4 +34,19 @@ export const RuleExecutionMetrics = z.object({ * Duration in seconds of execution gap */ execution_gap_duration_s: z.number().int().min(0).optional(), + /** + * Range of the execution gap + */ + gap_range: z + .object({ + /** + * Start date of the execution gap + */ + gte: z.string(), + /** + * End date of the execution gap + */ + lte: z.string(), + }) + .optional(), }); diff --git a/x-pack/solutions/security/plugins/security_solution/common/api/detection_engine/rule_monitoring/model/execution_metrics.schema.yaml b/x-pack/solutions/security/plugins/security_solution/common/api/detection_engine/rule_monitoring/model/execution_metrics.schema.yaml index 985da08e1df88..45ff14bae1542 100644 --- a/x-pack/solutions/security/plugins/security_solution/common/api/detection_engine/rule_monitoring/model/execution_metrics.schema.yaml +++ b/x-pack/solutions/security/plugins/security_solution/common/api/detection_engine/rule_monitoring/model/execution_metrics.schema.yaml @@ -25,3 +25,17 @@ components: description: Duration in seconds of execution gap type: integer minimum: 0 + gap_range: + description: Range of the execution gap + type: object + required: + - gte + - lte + properties: + gte: + description: Start date of the execution gap + type: string + lte: + description: End date of the execution gap + type: string + diff --git a/x-pack/solutions/security/plugins/security_solution/common/constants.ts b/x-pack/solutions/security/plugins/security_solution/common/constants.ts index 5cbb8b564a5e7..273e558e03ceb 100644 --- a/x-pack/solutions/security/plugins/security_solution/common/constants.ts +++ b/x-pack/solutions/security/plugins/security_solution/common/constants.ts @@ -425,6 +425,7 @@ export const NEW_FEATURES_TOUR_STORAGE_KEYS = { RULE_MANAGEMENT_PAGE: 'securitySolution.rulesManagementPage.newFeaturesTour.v8.13', TIMELINES: 'securitySolution.security.timelineFlyoutHeader.saveTimelineTour', SIEM_MAIN_LANDING_PAGE: 'securitySolution.siemMigrations.setupGuide.v8.18', + SIEM_RULE_TRANSLATION_PAGE: 'securitySolution.siemMigrations.ruleTranslationGuide.v8.18', }; export const RULE_DETAILS_EXECUTION_LOG_TABLE_SHOW_METRIC_COLUMNS_STORAGE_KEY = diff --git a/x-pack/solutions/security/plugins/security_solution/common/experimental_features.ts b/x-pack/solutions/security/plugins/security_solution/common/experimental_features.ts index a0417a1fd4c2a..13155bb1610c8 100644 --- a/x-pack/solutions/security/plugins/security_solution/common/experimental_features.ts +++ b/x-pack/solutions/security/plugins/security_solution/common/experimental_features.ts @@ -215,6 +215,15 @@ export const allowedExperimentalValues = Object.freeze({ */ valueListItemsModalEnabled: true, + /** + * Enables the storing of gaps in the event log + */ + manualRuleRunEnabled: false, + + /** + * Enables the storing of gaps in the event log + */ + storeGapsInEventLogEnabled: false, /** * Adds a new option to filter descendants of a process for Management / Event Filters */ @@ -273,6 +282,11 @@ export const allowedExperimentalValues = Object.freeze({ * Release: 8.18/9.0 */ responseActionsMSDefenderEndpointEnabled: true, + + /** + * Enables banner for informing users about changes in data collection. + */ + eventCollectionDataReductionBannerEnabled: false, }); type ExperimentalConfigKeys = Array; diff --git a/x-pack/solutions/security/plugins/security_solution/docs/openapi/ess/security_solution_detections_api_2023_10_31.bundled.schema.yaml b/x-pack/solutions/security/plugins/security_solution/docs/openapi/ess/security_solution_detections_api_2023_10_31.bundled.schema.yaml index 6c865ab356c1d..3cf7d14bedb8f 100644 --- a/x-pack/solutions/security/plugins/security_solution/docs/openapi/ess/security_solution_detections_api_2023_10_31.bundled.schema.yaml +++ b/x-pack/solutions/security/plugins/security_solution/docs/openapi/ess/security_solution_detections_api_2023_10_31.bundled.schema.yaml @@ -5133,6 +5133,19 @@ components: description: Duration in seconds of execution gap minimum: 0 type: integer + gap_range: + description: Range of the execution gap + type: object + properties: + gte: + description: Start date of the execution gap + type: string + lte: + description: End date of the execution gap + type: string + required: + - gte + - lte total_enrichment_duration_ms: description: >- Total time spent enriching documents during current rule execution diff --git a/x-pack/solutions/security/plugins/security_solution/docs/openapi/serverless/security_solution_detections_api_2023_10_31.bundled.schema.yaml b/x-pack/solutions/security/plugins/security_solution/docs/openapi/serverless/security_solution_detections_api_2023_10_31.bundled.schema.yaml index 583944c5b3435..fce6efba0afed 100644 --- a/x-pack/solutions/security/plugins/security_solution/docs/openapi/serverless/security_solution_detections_api_2023_10_31.bundled.schema.yaml +++ b/x-pack/solutions/security/plugins/security_solution/docs/openapi/serverless/security_solution_detections_api_2023_10_31.bundled.schema.yaml @@ -4282,6 +4282,19 @@ components: description: Duration in seconds of execution gap minimum: 0 type: integer + gap_range: + description: Range of the execution gap + type: object + properties: + gte: + description: Start date of the execution gap + type: string + lte: + description: End date of the execution gap + type: string + required: + - gte + - lte total_enrichment_duration_ms: description: >- Total time spent enriching documents during current rule execution diff --git a/x-pack/solutions/security/plugins/security_solution/kibana.jsonc b/x-pack/solutions/security/plugins/security_solution/kibana.jsonc index 10c24d0c979b5..2142601e1bd04 100644 --- a/x-pack/solutions/security/plugins/security_solution/kibana.jsonc +++ b/x-pack/solutions/security/plugins/security_solution/kibana.jsonc @@ -32,7 +32,6 @@ "features", "fieldFormats", "inspector", - "kubernetesSecurity", "lens", "licensing", "maps", diff --git a/x-pack/solutions/security/plugins/security_solution/public/asset_inventory/pages/all_assets.tsx b/x-pack/solutions/security/plugins/security_solution/public/asset_inventory/pages/all_assets.tsx index 345cc9a8b536f..251b86a91e27b 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/asset_inventory/pages/all_assets.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/asset_inventory/pages/all_assets.tsx @@ -374,7 +374,7 @@ const AllAssets = ({ loading={loadingState === DataLoadingState.loading} /> - +

({ key: capitalize(key), count, - color: getSeverityColor(key), + color: getSeverityColor(key, euiTheme), })); const totalAlertsCount = alertStats.reduce((total, item) => total + item.count, 0); diff --git a/x-pack/solutions/security/plugins/security_solution/public/cloud_security_posture/components/csp_details/alerts_findings_details_table.tsx b/x-pack/solutions/security/plugins/security_solution/public/cloud_security_posture/components/csp_details/alerts_findings_details_table.tsx index bf638a720d822..7a92bc8fdc268 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/cloud_security_posture/components/csp_details/alerts_findings_details_table.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/cloud_security_posture/components/csp_details/alerts_findings_details_table.tsx @@ -9,7 +9,15 @@ import React, { memo, useCallback, useEffect, useState } from 'react'; import { encode } from '@kbn/rison'; import { capitalize } from 'lodash'; import type { Criteria, EuiBasicTableColumn, EuiTableSortingType } from '@elastic/eui'; -import { EuiSpacer, EuiPanel, EuiText, EuiBasicTable, EuiIcon, EuiLink } from '@elastic/eui'; +import { + EuiSpacer, + EuiPanel, + EuiText, + EuiBasicTable, + EuiIcon, + EuiLink, + useEuiTheme, +} from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { DistributionBar } from '@kbn/security-solution-distribution-bar'; import { @@ -78,6 +86,8 @@ interface AlertsDetailsFields { export const AlertsDetailsTable = memo( ({ field, value }: { field: CloudPostureEntityIdentifier; value: string }) => { + const { euiTheme } = useEuiTheme(); + useEffect(() => { uiMetricService.trackUiMetric( METRIC_TYPE.COUNT, @@ -164,7 +174,7 @@ export const AlertsDetailsTable = memo( const alertStats = Array.from(severityMap, ([key, count]) => ({ key: capitalize(key), count, - color: getSeverityColor(key), + color: getSeverityColor(key, euiTheme), filter: () => { setCurrentFilter(key); setQuery( diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/charts/donutchart_empty.tsx b/x-pack/solutions/security/plugins/security_solution/public/common/components/charts/donutchart_empty.tsx index a24c487d7d924..b70460e81aa92 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/common/components/charts/donutchart_empty.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/common/components/charts/donutchart_empty.tsx @@ -4,7 +4,6 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import type { EuiThemeComputed } from '@elastic/eui'; import { useEuiTheme } from '@elastic/eui'; import { css } from '@emotion/react'; import React from 'react'; @@ -15,12 +14,10 @@ interface DonutChartEmptyProps { } /* - ** @deprecated use getEmptyDonutColor instead + ** @deprecated */ export const emptyDonutColor = '#FAFBFD'; -export const getEmptyDonutColor = (euiTheme: EuiThemeComputed) => euiTheme.colors.textSubdued; - const EmptyDonutChartComponent: React.FC = ({ size = 90, donutWidth = 20, diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/navigation/breadcrumbs/trailing_breadcrumbs.ts b/x-pack/solutions/security/plugins/security_solution/public/common/components/navigation/breadcrumbs/trailing_breadcrumbs.ts index 7da3500775e48..0a92bb5d890d8 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/common/components/navigation/breadcrumbs/trailing_breadcrumbs.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/common/components/navigation/breadcrumbs/trailing_breadcrumbs.ts @@ -14,7 +14,6 @@ import { getTrailingBreadcrumbs as getDetectionRulesBreadcrumbs } from '../../.. import { getTrailingBreadcrumbs as geExceptionsBreadcrumbs } from '../../../../exceptions/utils/breadcrumbs'; import { getTrailingBreadcrumbs as getCSPBreadcrumbs } from '../../../../cloud_security_posture/breadcrumbs'; import { getTrailingBreadcrumbs as getUsersBreadcrumbs } from '../../../../explore/users/pages/details/breadcrumbs'; -import { getTrailingBreadcrumbs as getKubernetesBreadcrumbs } from '../../../../kubernetes/pages/utils/breadcrumbs'; import { getTrailingBreadcrumbs as getDashboardBreadcrumbs } from '../../../../dashboards/pages/breadcrumbs'; export const getTrailingBreadcrumbs: GetTrailingBreadcrumbs = ( @@ -34,8 +33,6 @@ export const getTrailingBreadcrumbs: GetTrailingBreadcrumbs = ( return getDetectionRulesBreadcrumbs(spyState, getSecuritySolutionUrl); case SecurityPageName.exceptions: return geExceptionsBreadcrumbs(spyState, getSecuritySolutionUrl); - case SecurityPageName.kubernetes: - return getKubernetesBreadcrumbs(spyState, getSecuritySolutionUrl); case SecurityPageName.cloudSecurityPostureBenchmarks: return getCSPBreadcrumbs(spyState, getSecuritySolutionUrl); case SecurityPageName.dashboards: diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/severity_badge/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/common/components/severity_badge/index.tsx index 4c6312761666f..4651afb19ea0a 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/common/components/severity_badge/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/common/components/severity_badge/index.tsx @@ -7,18 +7,11 @@ import React from 'react'; import { upperFirst } from 'lodash/fp'; -import { euiLightVars } from '@kbn/ui-theme'; import type { Severity } from '@kbn/securitysolution-io-ts-alerting-types'; +import { useEuiTheme } from '@elastic/eui'; import { HealthTruncateText } from '../health_truncate_text'; - -const { euiColorVis0, euiColorVis5, euiColorVis7, euiColorVis9 } = euiLightVars; -const severityToColorMap: Record = { - low: euiColorVis0, - medium: euiColorVis5, - high: euiColorVis7, - critical: euiColorVis9, -}; +import { useRiskSeverityColors } from '../../utils/risk_color_palette'; interface Props { value: Severity; @@ -29,8 +22,10 @@ const SeverityBadgeComponent: React.FC = ({ value, 'data-test-subj': dataTestSubj = 'severity', }) => { + const { euiTheme } = useEuiTheme(); const displayValue = upperFirst(value); - const color = severityToColorMap[value] ?? 'subdued'; + const severityToColorMap = useRiskSeverityColors(); + const color = severityToColorMap[value] ?? euiTheme.colors.textSubdued; return ( + ({ + themeName: 'EUI_THEME_AMSTERDAM', + } as EuiThemeComputed); + +export const getMockEuiBorealisTheme = () => + ({ + themeName: 'EUI_THEME_BOREALIS', + } as EuiThemeComputed); diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/utils/risk_color_palette.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/common/utils/risk_color_palette.test.tsx new file mode 100644 index 0000000000000..136153d2a760c --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/public/common/utils/risk_color_palette.test.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 { renderHook } from '@testing-library/react'; +import { getRiskSeverityColors, useRiskSeverityColors } from './risk_color_palette'; +import { useEuiTheme } from '@elastic/eui'; +import { getMockEuiAmsterdamTheme, getMockEuiBorealisTheme } from './__mocks__/severity_colors'; + +jest.mock('@elastic/eui', () => ({ + useEuiTheme: jest.fn(), +})); + +const EXPECTED_SEVERITY_COLOR_AMSTERDAM = { + low: '#54b399', + medium: '#f1d86f', + high: '#ff7e62', + critical: '#bd271e', +}; + +const EXPECTED_SEVERITY_COLOR_BOREALIS = { + low: '#54B399', + medium: '#D6BF57', + high: '#DA8B45', + critical: '#E7664C', +} as const; + +describe('risk_color_palette', () => { + const scenarios = [ + { + mockEuiTheme: getMockEuiAmsterdamTheme(), + themeName: 'Amsterdam', + expected: EXPECTED_SEVERITY_COLOR_AMSTERDAM, + }, + { + mockEuiTheme: getMockEuiBorealisTheme(), + themeName: 'Borealis', + expected: EXPECTED_SEVERITY_COLOR_BOREALIS, + }, + ]; + + describe.each(scenarios)( + '$themeName: getRiskSeverityColors', + ({ mockEuiTheme, themeName, expected }) => { + it(`returns the correct colors for ${themeName} theme`, () => { + expect(getRiskSeverityColors(mockEuiTheme)).toEqual(expected); + }); + } + ); + + describe.each(scenarios)( + '$themeName: useRiskSeverityColors', + ({ mockEuiTheme, themeName, expected }) => { + const useEuiThemeMock = useEuiTheme as jest.Mock; + + it(`returns the correct colors for ${themeName} theme`, () => { + useEuiThemeMock.mockReturnValue({ + euiTheme: mockEuiTheme, + }); + const { result } = renderHook(() => useRiskSeverityColors()); + expect(result.current).toEqual(expected); + }); + } + ); +}); diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/utils/risk_color_palette.tsx b/x-pack/solutions/security/plugins/security_solution/public/common/utils/risk_color_palette.tsx new file mode 100644 index 0000000000000..e0eac26c7fe04 --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/public/common/utils/risk_color_palette.tsx @@ -0,0 +1,47 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { EuiThemeComputed } from '@elastic/eui'; +import { useEuiTheme } from '@elastic/eui'; +import type { Severity } from '@kbn/securitysolution-io-ts-alerting-types'; +import { useMemo } from 'react'; +import { + RISK_COLOR_CRITICAL, + RISK_COLOR_HIGH, + RISK_COLOR_LOW, + RISK_COLOR_MEDIUM, +} from '../constants'; + +// Temporary solution until we have a decision for color palette https://github.com/elastic/kibana/issues/203387 +export const SEVERITY_COLOR = { + low: '#54B399', + medium: '#D6BF57', + high: '#DA8B45', + critical: '#E7664C', +} as const; + +const isAmsterdam = (euiThemeName: string) => { + return euiThemeName?.toLowerCase().includes('amsterdam'); +}; + +export const getRiskSeverityColors = (euiTheme: EuiThemeComputed) => { + if (euiTheme && isAmsterdam(euiTheme.themeName)) { + return { + low: RISK_COLOR_LOW, + medium: RISK_COLOR_MEDIUM, + high: RISK_COLOR_HIGH, + critical: RISK_COLOR_CRITICAL, + }; + } + return SEVERITY_COLOR; +}; + +export const useRiskSeverityColors = (): Record => { + const { euiTheme } = useEuiTheme(); + + return useMemo(() => getRiskSeverityColors(euiTheme), [euiTheme]); +}; diff --git a/x-pack/solutions/security/plugins/security_solution/public/dashboards/links.ts b/x-pack/solutions/security/plugins/security_solution/public/dashboards/links.ts index a6914e76734a8..7feecbd1742c9 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/dashboards/links.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/dashboards/links.ts @@ -8,7 +8,6 @@ import { i18n } from '@kbn/i18n'; import { DASHBOARDS_PATH, SecurityPageName, SECURITY_FEATURE_ID } from '../../common/constants'; import { DASHBOARDS } from '../app/translations'; import type { LinkItem } from '../common/links/types'; -import { links as kubernetesLinks } from '../kubernetes/links'; import { cspDashboardLink, vulnerabilityDashboardLink } from '../cloud_security_posture/links'; import { ecsDataQualityDashboardLinks, @@ -21,7 +20,6 @@ import { IconDashboards } from '../common/icons/dashboards'; const subLinks: LinkItem[] = [ overviewLinks, detectionResponseLinks, - kubernetesLinks, cspDashboardLink, vulnerabilityDashboardLink, entityAnalyticsLinks, diff --git a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_creation_ui/components/severity_mapping/default_severity.tsx b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_creation_ui/components/severity_mapping/default_severity.tsx index 477b4bcd0f519..b33bd1c737a5a 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_creation_ui/components/severity_mapping/default_severity.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_creation_ui/components/severity_mapping/default_severity.tsx @@ -15,7 +15,7 @@ import { } from '@elastic/eui'; import React from 'react'; import type { Severity } from '../../../../../common/api/detection_engine/model/rule_schema/common_attributes.gen'; -import { severityOptions } from '../step_about_rule/data'; +import { useSeverityOptions } from '../step_about_rule/data'; import * as i18n from './translations'; const describedByIds = ['detectionEngineStepAboutRuleSeverity']; @@ -26,6 +26,7 @@ interface DefaultSeverityProps { } export function DefaultSeverity({ value, onChange }: DefaultSeverityProps) { + const severityOptions = useSeverityOptions(); return ( diff --git a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_creation_ui/components/step_about_rule/data.tsx b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_creation_ui/components/step_about_rule/data.tsx index 511f4109f9413..57e824d7d400d 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_creation_ui/components/step_about_rule/data.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_creation_ui/components/step_about_rule/data.tsx @@ -5,22 +5,20 @@ * 2.0. */ -import React from 'react'; +import React, { useMemo } from 'react'; import styled from 'styled-components'; -import { EuiHealth } from '@elastic/eui'; +import type { EuiThemeComputed } from '@elastic/eui'; +import { EuiHealth, useEuiTheme } from '@elastic/eui'; import type { Severity } from '@kbn/securitysolution-io-ts-alerting-types'; import * as I18n from './translations'; import { - RISK_COLOR_LOW, - RISK_COLOR_MEDIUM, - RISK_COLOR_HIGH, - RISK_COLOR_CRITICAL, RISK_SCORE_LOW, RISK_SCORE_MEDIUM, RISK_SCORE_HIGH, RISK_SCORE_CRITICAL, } from '../../../../common/constants'; +import { getRiskSeverityColors } from '../../../../common/utils/risk_color_palette'; export interface SeverityOptionItem { value: Severity; @@ -31,24 +29,41 @@ const StyledEuiHealth = styled(EuiHealth)` line-height: inherit; `; -export const severityOptions: SeverityOptionItem[] = [ - { - value: 'low', - inputDisplay: {I18n.LOW}, - }, - { - value: 'medium', - inputDisplay: {I18n.MEDIUM}, - }, - { - value: 'high', - inputDisplay: {I18n.HIGH}, - }, - { - value: 'critical', - inputDisplay: {I18n.CRITICAL}, - }, -]; +export enum SeverityLevel { + low = 'low', + medium = 'medium', + high = 'high', + critical = 'critical', +} + +const getSeverityOptions: (euiTheme: EuiThemeComputed) => SeverityOptionItem[] = (euiTheme) => { + const palette = getRiskSeverityColors(euiTheme); + return [ + { + value: SeverityLevel.low, + inputDisplay: {I18n.LOW}, + }, + { + value: SeverityLevel.medium, + inputDisplay: {I18n.MEDIUM}, + }, + { + value: SeverityLevel.high, + inputDisplay: {I18n.HIGH}, + }, + { + value: SeverityLevel.critical, + inputDisplay: {I18n.CRITICAL}, + }, + ]; +}; + +export const useSeverityOptions = () => { + const { euiTheme } = useEuiTheme(); + const severityOptions = useMemo(() => getSeverityOptions(euiTheme), [euiTheme]); + + return severityOptions; +}; export const defaultRiskScoreBySeverity: Record = { low: RISK_SCORE_LOW, diff --git a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_creation_ui/components/step_about_rule/default_value.ts b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_creation_ui/components/step_about_rule/default_value.ts index 9d1fff5b8a9ef..e397281b684bc 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_creation_ui/components/step_about_rule/default_value.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_creation_ui/components/step_about_rule/default_value.ts @@ -23,7 +23,11 @@ export const stepAboutDefaultValue: AboutStepRule = { description: '', isAssociatedToEndpointList: false, isBuildingBlock: false, - severity: { value: 'low', mapping: fillEmptySeverityMappings([]), isMappingChecked: false }, + severity: { + value: 'low', + mapping: fillEmptySeverityMappings([]), + isMappingChecked: false, + }, riskScore: { value: 21, mapping: [], isMappingChecked: false }, references: [''], falsePositives: [''], diff --git a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_creation_ui/components/step_about_rule/index.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_creation_ui/components/step_about_rule/index.test.tsx index 94e230c59569c..d101b771e9fe1 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_creation_ui/components/step_about_rule/index.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_creation_ui/components/step_about_rule/index.test.tsx @@ -103,9 +103,10 @@ describe('StepAboutRuleComponent', () => { defineStepDefaultOverride?: DefineStepRule; }) => { const defineStepDefault = defineStepDefaultOverride ?? stepDefineDefaultValue; + const aboutStepDefault = stepAboutDefaultValue; const { aboutStepForm } = useRuleForms({ defineStepDefault, - aboutStepDefault: stepAboutDefaultValue, + aboutStepDefault, scheduleStepDefault: defaultSchedule, actionsStepDefault: stepActionsDefaultValue, }); @@ -118,7 +119,7 @@ describe('StepAboutRuleComponent', () => { machineLearningJobId={defineStepDefault.machineLearningJobId} index={defineStepDefault.index} dataViewId={defineStepDefault.dataViewId} - timestampOverride={stepAboutDefaultValue.timestampOverride} + timestampOverride={aboutStepDefault.timestampOverride} isLoading={false} form={aboutStepForm} /> @@ -287,7 +288,11 @@ describe('StepAboutRuleComponent', () => { setup: '', references: [''], riskScore: { value: 21, mapping: [], isMappingChecked: false }, - severity: { value: 'low', mapping: fillEmptySeverityMappings([]), isMappingChecked: false }, + severity: { + value: 'low', + mapping: fillEmptySeverityMappings([]), + isMappingChecked: false, + }, tags: [], threat: [ { @@ -349,7 +354,11 @@ describe('StepAboutRuleComponent', () => { setup: '', references: [''], riskScore: { value: 80, mapping: [], isMappingChecked: false }, - severity: { value: 'low', mapping: fillEmptySeverityMappings([]), isMappingChecked: false }, + severity: { + value: 'low', + mapping: fillEmptySeverityMappings([]), + isMappingChecked: false, + }, tags: [], threat: [ { diff --git a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_gaps/components/manual_rule_run/translations.ts b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_gaps/components/manual_rule_run/translations.ts index d0800fd25b630..d811e2a20df63 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_gaps/components/manual_rule_run/translations.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_gaps/components/manual_rule_run/translations.ts @@ -72,6 +72,7 @@ export const MANUAL_RULE_RUN_START_DATE_OUT_OF_RANGE_ERROR = (maxDaysLookback: n export const MANUAL_RULE_RUN_NOTIFIACTIONS_LIMITATIONS = i18n.translate( 'xpack.securitySolution.manualRuleRun.notificationsLimitations', { - defaultMessage: 'Rule actions are not performed during manual rule runs.', + defaultMessage: + 'Alert summary rule actions that run at a custom frequency are not performed during manual rule runs.', } ); diff --git a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/__mocks__/mock.ts b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/__mocks__/mock.ts index 25b2d88c6dddd..9fc852882c792 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/__mocks__/mock.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/__mocks__/mock.ts @@ -205,7 +205,11 @@ export const mockAboutStepRule = (): AboutStepRule => ({ name: 'Query with rule-id', description: '24/7', riskScore: { value: 21, mapping: [], isMappingChecked: false }, - severity: { value: 'low', mapping: fillEmptySeverityMappings([]), isMappingChecked: false }, + severity: { + value: 'low', + mapping: fillEmptySeverityMappings([]), + isMappingChecked: false, + }, references: ['www.test.co'], falsePositives: ['test'], tags: ['tag1', 'tag2'], diff --git a/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_kpis/alerts_treemap_panel/alerts_treemap/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_kpis/alerts_treemap_panel/alerts_treemap/index.tsx index ef7000f5037b3..5cdf30f4a6e0d 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_kpis/alerts_treemap_panel/alerts_treemap/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_kpis/alerts_treemap_panel/alerts_treemap/index.tsx @@ -7,7 +7,7 @@ import type { Datum, ElementClickListener, PartialTheme } from '@elastic/charts'; import { Chart, Partition, PartitionLayout, Settings } from '@elastic/charts'; -import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; +import { EuiFlexGroup, EuiFlexItem, useEuiTheme } from '@elastic/eui'; import { isEmpty } from 'lodash/fp'; import React, { useCallback, useMemo } from 'react'; import styled from 'styled-components'; @@ -60,6 +60,7 @@ const AlertsTreemapComponent: React.FC = ({ stackByField0, stackByField1, }: Props) => { + const { euiTheme } = useEuiTheme(); const { theme, baseTheme } = useThemes(); const fillColor = useMemo( () => theme?.background?.color ?? baseTheme.background.color, @@ -101,7 +102,7 @@ const AlertsTreemapComponent: React.FC = ({ [buckets, maxRiskSubAggregations, stackByField0] ); - const colorPalette = useMemo(() => getRiskScorePalette(RISK_SCORE_STEPS), []); + const colorPalette = useMemo(() => getRiskScorePalette(RISK_SCORE_STEPS, euiTheme), [euiTheme]); const legendItems: LegendItem[] = useMemo( () => diff --git a/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_kpis/alerts_treemap_panel/alerts_treemap/lib/chart_palette/index.test.ts b/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_kpis/alerts_treemap_panel/alerts_treemap/lib/chart_palette/index.test.ts index 64bd8911ddcd6..d7974ac8f4a51 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_kpis/alerts_treemap_panel/alerts_treemap/lib/chart_palette/index.test.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_kpis/alerts_treemap_panel/alerts_treemap/lib/chart_palette/index.test.ts @@ -5,24 +5,26 @@ * 2.0. */ -import { euiPaletteWarm } from '@elastic/eui'; +import { euiPaletteWarm, useEuiTheme } from '@elastic/eui'; import { - RISK_COLOR_LOW, - RISK_COLOR_MEDIUM, - RISK_COLOR_HIGH, - RISK_COLOR_CRITICAL, RISK_SCORE_MEDIUM, RISK_SCORE_HIGH, RISK_SCORE_CRITICAL, } from '../../../../../../../common/constants'; import { getFillColor, getRiskScorePalette, RISK_SCORE_STEPS } from '.'; +import { renderHook } from '@testing-library/react'; +import { getRiskSeverityColors } from '../../../../../../../common/utils/risk_color_palette'; describe('getFillColor', () => { + const { result } = renderHook(() => useEuiTheme()); + const euiTheme = result.current.euiTheme; + describe('when using the Risk Score palette', () => { - const colorPalette = getRiskScorePalette(RISK_SCORE_STEPS); + const colorPalette = getRiskScorePalette(RISK_SCORE_STEPS, euiTheme); + const expectedColorPalette = getRiskSeverityColors(euiTheme); it('returns the expected fill color', () => { - expect(getFillColor({ riskScore: 50, colorPalette })).toEqual('#d6bf57'); + expect(getFillColor({ riskScore: 50, colorPalette })).toEqual('#f1d86f'); }); it('returns the expected fill color when risk score is zero', () => { @@ -34,50 +36,52 @@ describe('getFillColor', () => { }); it('returns the expected fill color when risk score is 100', () => { - expect(getFillColor({ riskScore: 100, colorPalette })).toEqual('#e7664c'); + expect(getFillColor({ riskScore: 100, colorPalette })).toEqual('#bd271e'); }); it('returns the expected fill color when risk score is greater than 100', () => { - expect(getFillColor({ riskScore: 101, colorPalette })).toEqual('#e7664c'); + expect(getFillColor({ riskScore: 101, colorPalette })).toEqual('#bd271e'); }); it('returns the expected fill color when risk score is greater than RISK_SCORE_CRITICAL', () => { expect(getFillColor({ riskScore: RISK_SCORE_CRITICAL + 1, colorPalette })).toEqual( - RISK_COLOR_CRITICAL + expectedColorPalette.critical ); }); it('returns the expected fill color when risk score is equal to RISK_SCORE_CRITICAL', () => { expect(getFillColor({ riskScore: RISK_SCORE_CRITICAL, colorPalette })).toEqual( - RISK_COLOR_CRITICAL + expectedColorPalette.critical ); }); it('returns the expected fill color when risk score is greater than RISK_SCORE_HIGH', () => { expect(getFillColor({ riskScore: RISK_SCORE_HIGH + 1, colorPalette })).toEqual( - RISK_COLOR_HIGH + expectedColorPalette.high ); }); it('returns the expected fill color when risk score is equal to RISK_SCORE_HIGH', () => { - expect(getFillColor({ riskScore: RISK_SCORE_HIGH, colorPalette })).toEqual(RISK_COLOR_HIGH); + expect(getFillColor({ riskScore: RISK_SCORE_HIGH, colorPalette })).toEqual( + expectedColorPalette.high + ); }); it('returns the expected fill color when risk score is greater than RISK_SCORE_MEDIUM', () => { expect(getFillColor({ riskScore: RISK_SCORE_MEDIUM + 1, colorPalette })).toEqual( - RISK_COLOR_MEDIUM + expectedColorPalette.medium ); }); it('returns the expected fill color when risk score is equal to RISK_SCORE_MEDIUM', () => { expect(getFillColor({ riskScore: RISK_SCORE_MEDIUM, colorPalette })).toEqual( - RISK_COLOR_MEDIUM + expectedColorPalette.medium ); }); it('returns the expected fill color when risk score is less than RISK_SCORE_MEDIUM', () => { expect(getFillColor({ riskScore: RISK_SCORE_MEDIUM - 1, colorPalette })).toEqual( - RISK_COLOR_LOW + expectedColorPalette.low ); }); }); diff --git a/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_kpis/alerts_treemap_panel/alerts_treemap/lib/chart_palette/index.ts b/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_kpis/alerts_treemap_panel/alerts_treemap/lib/chart_palette/index.ts index 7cc31c76b112e..fdbeb989632e3 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_kpis/alerts_treemap_panel/alerts_treemap/lib/chart_palette/index.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_kpis/alerts_treemap_panel/alerts_treemap/lib/chart_palette/index.ts @@ -7,15 +7,13 @@ import { clamp } from 'lodash/fp'; +import type { EuiThemeComputed } from '@elastic/eui'; import { - RISK_COLOR_LOW, - RISK_COLOR_MEDIUM, - RISK_COLOR_HIGH, - RISK_COLOR_CRITICAL, RISK_SCORE_MEDIUM, RISK_SCORE_HIGH, RISK_SCORE_CRITICAL, } from '../../../../../../../common/constants'; +import { getRiskSeverityColors } from '../../../../../../../common/utils/risk_color_palette'; /** * The detection engine creates risk scores in the range 1 - 100. @@ -34,20 +32,22 @@ export const RISK_SCORE_STEPS = 101; * This pallet has the same type as `EuiPalette`, which is not exported by * EUI at the time of this writing. */ -export const getRiskScorePalette = (steps: number): string[] => - Array(steps) +export const getRiskScorePalette = (steps: number, euiTheme: EuiThemeComputed): string[] => { + const palette = getRiskSeverityColors(euiTheme); + return Array(steps) .fill(0) .map((_, i) => { if (i >= RISK_SCORE_CRITICAL) { - return RISK_COLOR_CRITICAL; + return palette.critical; } else if (i >= RISK_SCORE_HIGH) { - return RISK_COLOR_HIGH; + return palette.high; } else if (i >= RISK_SCORE_MEDIUM) { - return RISK_COLOR_MEDIUM; + return palette.medium; } else { - return RISK_COLOR_LOW; + return palette.low; } }); +}; /** Returns a fill color based on the index of the risk score in the color palette */ export const getFillColor = ({ diff --git a/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_kpis/alerts_treemap_panel/alerts_treemap/lib/layers/index.test.ts b/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_kpis/alerts_treemap_panel/alerts_treemap/lib/layers/index.test.ts index f8404cc7d33ed..24f40ee94067f 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_kpis/alerts_treemap_panel/alerts_treemap/lib/layers/index.test.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_kpis/alerts_treemap_panel/alerts_treemap/lib/layers/index.test.ts @@ -9,9 +9,13 @@ import { getRiskScorePalette, RISK_SCORE_STEPS } from '../chart_palette'; import { maxRiskSubAggregations } from '../flatten/mocks/mock_buckets'; import { getGroupFromPath, getLayersOneDimension, getLayersMultiDimensional } from '.'; import type { Key, ArrayNode } from '@elastic/charts'; +import { useEuiTheme } from '@elastic/eui'; +import { renderHook } from '@testing-library/react'; describe('layers', () => { - const colorPalette = getRiskScorePalette(RISK_SCORE_STEPS); + const { result } = renderHook(() => useEuiTheme()); + const euiTheme = result.current.euiTheme; + const colorPalette = getRiskScorePalette(RISK_SCORE_STEPS, euiTheme); describe('getGroupFromPath', () => { it('returns the expected group from the path', () => { @@ -69,7 +73,7 @@ describe('layers', () => { const dataName = 'mimikatz process started'; expect( getLayersOneDimension({ colorPalette, maxRiskSubAggregations })[0].shape.fillColor(dataName) - ).toEqual('#e7664c'); + ).toEqual('#bd271e'); }); it('return the default fill color when dataName is not found in the maxRiskSubAggregations', () => { @@ -165,7 +169,7 @@ describe('layers', () => { { index: 0, value: 'Host-k8iyfzraq9' }, ], }) - ).toEqual('#e7664c'); + ).toEqual('#bd271e'); }); it('returns the default fillColor for layer 1 when the group from path is not found', () => { diff --git a/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_kpis/alerts_treemap_panel/alerts_treemap/lib/legend/get_flattened_legend_items.test.ts b/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_kpis/alerts_treemap_panel/alerts_treemap/lib/legend/get_flattened_legend_items.test.ts index c0fb3383a2556..0702b3b98b738 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_kpis/alerts_treemap_panel/alerts_treemap/lib/legend/get_flattened_legend_items.test.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_kpis/alerts_treemap_panel/alerts_treemap/lib/legend/get_flattened_legend_items.test.ts @@ -13,6 +13,8 @@ import { getFlattenedLegendItems } from './get_flattened_legend_items'; import { bucketsWithStackByField1, maxRiskSubAggregations } from '../flatten/mocks/mock_buckets'; import { flattenedBuckets } from '../flatten/mocks/mock_flattened_buckets'; import { TableId } from '@kbn/securitysolution-data-table'; +import { renderHook } from '@testing-library/react'; +import { useEuiTheme } from '@elastic/eui'; describe('getFlattenedLegendItems', () => { it('returns the expected legend items', () => { @@ -52,25 +54,25 @@ describe('getFlattenedLegendItems', () => { value: 'EQL process sequence', }, { - color: '#da8b45', + color: '#ff7e62', count: 10, field: 'host.name', value: 'Host-k8iyfzraq9', }, { - color: '#da8b45', + color: '#ff7e62', count: 7, field: 'host.name', value: 'Host-ao1a4wu7vn', }, { - color: '#da8b45', + color: '#ff7e62', count: 5, field: 'host.name', value: 'Host-3fbljiq8rj', }, { - color: '#da8b45', + color: '#ff7e62', count: 3, field: 'host.name', value: 'Host-r4y6xi92ob', @@ -81,25 +83,25 @@ describe('getFlattenedLegendItems', () => { value: 'Endpoint Security', }, { - color: '#d6bf57', + color: '#f1d86f', count: 11, field: 'host.name', value: 'Host-ao1a4wu7vn', }, { - color: '#d6bf57', + color: '#f1d86f', count: 6, field: 'host.name', value: 'Host-3fbljiq8rj', }, { - color: '#d6bf57', + color: '#f1d86f', count: 1, field: 'host.name', value: 'Host-k8iyfzraq9', }, { - color: '#d6bf57', + color: '#f1d86f', count: 1, field: 'host.name', value: 'Host-r4y6xi92ob', @@ -110,19 +112,19 @@ describe('getFlattenedLegendItems', () => { value: 'mimikatz process started', }, { - color: '#e7664c', + color: '#bd271e', count: 3, field: 'host.name', value: 'Host-k8iyfzraq9', }, { - color: '#e7664c', + color: '#bd271e', count: 1, field: 'host.name', value: 'Host-3fbljiq8rj', }, { - color: '#e7664c', + color: '#bd271e', count: 1, field: 'host.name', value: 'Host-r4y6xi92ob', @@ -133,16 +135,17 @@ describe('getFlattenedLegendItems', () => { value: 'Threshold rule', }, { - color: '#e7664c', + color: '#bd271e', count: 1, field: 'host.name', value: 'Host-r4y6xi92ob', }, ].map((legend) => ({ ...legend, scopeId: TableId.alertsOnAlertsPage })); - + const { result: euiThemeResult } = renderHook(() => useEuiTheme()); + const euiTheme = euiThemeResult.current.euiTheme; const legendItems = getFlattenedLegendItems({ buckets: bucketsWithStackByField1, - colorPalette: getRiskScorePalette(RISK_SCORE_STEPS), + colorPalette: getRiskScorePalette(RISK_SCORE_STEPS, euiTheme), flattenedBuckets, maxRiskSubAggregations, stackByField0: 'kibana.alert.rule.name', diff --git a/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_kpis/alerts_treemap_panel/alerts_treemap/lib/legend/index.test.ts b/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_kpis/alerts_treemap_panel/alerts_treemap/lib/legend/index.test.ts index fe136924576a8..deeff81b97d2a 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_kpis/alerts_treemap_panel/alerts_treemap/lib/legend/index.test.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_kpis/alerts_treemap_panel/alerts_treemap/lib/legend/index.test.ts @@ -18,9 +18,13 @@ import { } from '.'; import type { FlattenedBucket, RawBucket } from '../../types'; import { TableId } from '@kbn/securitysolution-data-table'; +import { renderHook } from '@testing-library/react'; +import { useEuiTheme } from '@elastic/eui'; describe('legend', () => { - const colorPalette = getRiskScorePalette(RISK_SCORE_STEPS); + const { result } = renderHook(() => useEuiTheme()); + const euiTheme = result.current.euiTheme; + const colorPalette = getRiskScorePalette(RISK_SCORE_STEPS, euiTheme); describe('getLegendItemFromRawBucket', () => { const bucket: RawBucket = { @@ -219,28 +223,28 @@ describe('legend', () => { scopeId: TableId.alertsOnAlertsPage, }, { - color: '#da8b45', + color: '#ff7e62', count: 28, field: 'kibana.alert.rule.name', value: 'EQL process sequence', scopeId: TableId.alertsOnAlertsPage, }, { - color: '#d6bf57', + color: '#f1d86f', count: 19, field: 'kibana.alert.rule.name', value: 'Endpoint Security', scopeId: TableId.alertsOnAlertsPage, }, { - color: '#e7664c', + color: '#bd271e', count: 5, field: 'kibana.alert.rule.name', value: 'mimikatz process started', scopeId: TableId.alertsOnAlertsPage, }, { - color: '#e7664c', + color: '#bd271e', count: 1, field: 'kibana.alert.rule.name', value: 'Threshold rule', diff --git a/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_kpis/chart_panels/chart_collapse/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_kpis/chart_panels/chart_collapse/index.tsx index 0539b7f7615d6..54853d6402e86 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_kpis/chart_panels/chart_collapse/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_kpis/chart_panels/chart_collapse/index.tsx @@ -4,7 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import { EuiFlexGroup, EuiFlexItem, EuiHealth, EuiText } from '@elastic/eui'; +import { EuiFlexGroup, EuiFlexItem, EuiHealth, EuiText, useEuiTheme } from '@elastic/eui'; import { ALERT_SEVERITY, ALERT_RULE_NAME } from '@kbn/rule-data-utils'; import type { MappingRuntimeFields } from '@elastic/elasticsearch/lib/api/types'; import type { Filter, Query } from '@kbn/es-query'; @@ -20,8 +20,7 @@ import { getSeverityColor } from '../../severity_level_panel/helpers'; import { FormattedCount } from '../../../../../common/components/formatted_number'; import { getIsChartCollapseData } from './helpers'; import * as i18n from './translations'; - -import { SEVERITY_COLOR } from '../../../../../overview/components/detection_response/utils'; +import { useRiskSeverityColors } from '../../../../../common/utils/risk_color_palette'; const DETECTIONS_ALERTS_COLLAPSED_CHART_ID = 'detectioin-alerts-collapsed-chart'; @@ -79,6 +78,7 @@ export const ChartCollapse: React.FC = ({ signalIndexName, runtimeMappings, }: Props) => { + const { euiTheme } = useEuiTheme(); const uniqueQueryId = useMemo(() => `${DETECTIONS_ALERTS_COLLAPSED_CHART_ID}-${uuid()}`, []); const aggregations = useMemo(() => combinedAggregations(groupBySelection), [groupBySelection]); @@ -94,9 +94,10 @@ export const ChartCollapse: React.FC = ({ const topRule = useMemo(() => data.at(0)?.rule ?? i18n.NO_RESULT_MESSAGE, [data]); const topGroup = useMemo(() => data.at(0)?.group ?? i18n.NO_RESULT_MESSAGE, [data]); + const severityColors = useRiskSeverityColors(); const severities = useMemo(() => { const severityData = data.at(0)?.severities ?? []; - return Object.keys(SEVERITY_COLOR).map((severity) => { + return Object.keys(severityColors).map((severity) => { const obj = severityData.find((s) => s.key === severity); if (obj) { return { key: obj.key, label: obj.label, value: obj.value }; @@ -104,7 +105,7 @@ export const ChartCollapse: React.FC = ({ return { key: severity, label: capitalize(severity), value: 0 }; } }); - }, [data]); + }, [data, severityColors]); const groupBy = useMemo(() => getGroupByLabel(groupBySelection), [groupBySelection]); return ( @@ -115,7 +116,7 @@ export const ChartCollapse: React.FC = ({ {severities.map((severity) => ( - + {`${severity.label}: `} diff --git a/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_kpis/severity_level_panel/columns.tsx b/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_kpis/severity_level_panel/columns.tsx index 2c79054a4a5e9..c4e1c52799607 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_kpis/severity_level_panel/columns.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_kpis/severity_level_panel/columns.tsx @@ -4,7 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import React from 'react'; +import React, { useMemo } from 'react'; import { EuiHealth, EuiText } from '@elastic/eui'; import { capitalize } from 'lodash'; import { ALERT_SEVERITY } from '@kbn/rule-data-utils'; @@ -13,41 +13,47 @@ import type { Severity } from '@kbn/securitysolution-io-ts-alerting-types'; import { TableId } from '@kbn/securitysolution-data-table'; import type { SeverityBuckets as SeverityData } from '../../../../overview/components/detection_response/alerts_by_status/types'; import { DefaultDraggable } from '../../../../common/components/draggables'; -import { SEVERITY_COLOR } from '../../../../overview/components/detection_response/utils'; import { FormattedCount } from '../../../../common/components/formatted_number'; import { COUNT_TABLE_TITLE } from '../alerts_count_panel/translations'; import * as i18n from './translations'; +import { useRiskSeverityColors } from '../../../../common/utils/risk_color_palette'; -export const getSeverityTableColumns = (): Array> => [ - { - field: 'key', - name: i18n.SEVERITY_LEVEL_COLUMN_TITLE, - 'data-test-subj': 'severityTable-severity', - render: (severity: Severity) => ( - - - - ), - }, - { - field: 'value', - name: COUNT_TABLE_TITLE, - dataType: 'number', - 'data-test-subj': 'severityTable-alertCount', - width: '45%', - render: (alertCount: number) => ( - - - - ), - }, -]; +export const useGetSeverityTableColumns = (): Array> => { + const severityColors = useRiskSeverityColors(); + return useMemo( + () => [ + { + field: 'key', + name: i18n.SEVERITY_LEVEL_COLUMN_TITLE, + 'data-test-subj': 'severityTable-severity', + render: (severity: Severity) => ( + + + + ), + }, + { + field: 'value', + name: COUNT_TABLE_TITLE, + dataType: 'number', + 'data-test-subj': 'severityTable-alertCount', + width: '45%', + render: (alertCount: number) => ( + + + + ), + }, + ], + [severityColors] + ); +}; diff --git a/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_kpis/severity_level_panel/helpers.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_kpis/severity_level_panel/helpers.test.tsx index 9e493ba8fe48f..f0ed436159ec0 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_kpis/severity_level_panel/helpers.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_kpis/severity_level_panel/helpers.test.tsx @@ -4,10 +4,14 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import { parseSeverityData } from './helpers'; +import { getSeverityColor, parseSeverityData } from './helpers'; import * as mock from './mock_data'; import type { AlertsBySeverityAgg } from './types'; import type { AlertSearchResponse } from '../../../containers/detection_engine/alerts/types'; +import { + getMockEuiAmsterdamTheme, + getMockEuiBorealisTheme, +} from '../../../../common/utils/__mocks__/severity_colors'; describe('parse severity data', () => { test('parse alerts with data', () => { @@ -24,3 +28,21 @@ describe('parse severity data', () => { expect(res).toEqual([]); }); }); + +describe.each([ + { severity: 'critical', colorToken: '#bd271e', themeName: 'Amsterdam' }, + { severity: 'high', colorToken: '#ff7e62', themeName: 'Amsterdam' }, + { severity: 'medium', colorToken: '#f1d86f', themeName: 'Amsterdam' }, + { severity: 'low', colorToken: '#54b399', themeName: 'Amsterdam' }, + { severity: 'critical', colorToken: '#E7664C', themeName: 'Borealis' }, + { severity: 'high', colorToken: '#DA8B45', themeName: 'Borealis' }, + { severity: 'medium', colorToken: '#D6BF57', themeName: 'Borealis' }, + { severity: 'low', colorToken: '#54B399', themeName: 'Borealis' }, +])('$themeName: getSeverityColor', ({ severity, colorToken, themeName }) => { + const mockEuiTheme = + themeName === 'Amsterdam' ? getMockEuiAmsterdamTheme() : getMockEuiBorealisTheme(); + + test(`returns color for given severity: ${severity}`, () => { + expect(getSeverityColor(severity, mockEuiTheme)).toEqual(colorToken); + }); +}); diff --git a/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_kpis/severity_level_panel/helpers.tsx b/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_kpis/severity_level_panel/helpers.tsx index 227fde8a9b8f2..7b76ff3bb94dc 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_kpis/severity_level_panel/helpers.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_kpis/severity_level_panel/helpers.tsx @@ -6,18 +6,19 @@ */ import type { Severity } from '@kbn/securitysolution-io-ts-alerting-types'; import { has } from 'lodash'; +import type { EuiThemeComputed } from '@elastic/eui'; import type { AlertsBySeverityAgg } from './types'; import type { AlertSearchResponse } from '../../../containers/detection_engine/alerts/types'; import type { SeverityBuckets as SeverityData } from '../../../../overview/components/detection_response/alerts_by_status/types'; import type { SummaryChartsData, SummaryChartsAgg } from '../alerts_summary_charts_panel/types'; import { severityLabels } from '../../../../overview/components/detection_response/alerts_by_status/use_alerts_by_status'; -import { emptyDonutColor } from '../../../../common/components/charts/donutchart_empty'; -import { SEVERITY_COLOR } from '../../../../overview/components/detection_response/utils'; +import { getRiskSeverityColors } from '../../../../common/utils/risk_color_palette'; const SEVERITY_ORDER: Severity[] = ['critical', 'high', 'medium', 'low']; -export const getSeverityColor = (severity: string) => { - return SEVERITY_COLOR[severity.toLocaleLowerCase() as Severity] ?? emptyDonutColor; +export const getSeverityColor = (severity: string, euiTheme: EuiThemeComputed) => { + const palette = getRiskSeverityColors(euiTheme); + return palette[severity.toLocaleLowerCase() as Severity] ?? euiTheme.colors.textSubdued; }; export const parseSeverityData = ( diff --git a/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_kpis/severity_level_panel/severity_level_chart.tsx b/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_kpis/severity_level_panel/severity_level_chart.tsx index 841586ebad2be..6d2337a78296f 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_kpis/severity_level_panel/severity_level_chart.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_kpis/severity_level_panel/severity_level_chart.tsx @@ -7,12 +7,18 @@ import React, { useCallback, useMemo } from 'react'; import { ALERT_SEVERITY } from '@kbn/rule-data-utils'; import styled from 'styled-components'; -import { EuiFlexGroup, EuiFlexItem, EuiInMemoryTable, EuiLoadingSpinner } from '@elastic/eui'; +import { + EuiFlexGroup, + EuiFlexItem, + EuiInMemoryTable, + EuiLoadingSpinner, + useEuiTheme, +} from '@elastic/eui'; import type { SeverityBuckets as SeverityData } from '../../../../overview/components/detection_response/alerts_by_status/types'; import type { FillColor } from '../../../../common/components/charts/donutchart'; import { DonutChart } from '../../../../common/components/charts/donutchart'; import { ChartLabel } from '../../../../overview/components/detection_response/alerts_by_status/chart_label'; -import { getSeverityTableColumns } from './columns'; +import { useGetSeverityTableColumns } from './columns'; import { getSeverityColor } from './helpers'; import { TOTAL_COUNT_OF_ALERTS } from '../../alerts_table/translations'; @@ -32,7 +38,8 @@ export const SeverityLevelChart: React.FC = ({ isLoading, addFilter, }) => { - const columns = useMemo(() => getSeverityTableColumns(), []); + const { euiTheme } = useEuiTheme(); + const columns = useGetSeverityTableColumns(); const count = useMemo(() => { return data @@ -42,9 +49,10 @@ export const SeverityLevelChart: React.FC = ({ : 0; }, [data]); - const fillColor: FillColor = useCallback((dataName: string) => { - return getSeverityColor(dataName); - }, []); + const fillColor: FillColor = useCallback( + (dataName: string) => getSeverityColor(dataName, euiTheme), + [euiTheme] + ); const onDonutPartitionClicked = useCallback( (level: string) => { diff --git a/x-pack/solutions/security/plugins/security_solution/public/detections/pages/detection_engine/rules/helpers.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/detections/pages/detection_engine/rules/helpers.test.tsx index 2152d10115b2d..39cf9bbd8a915 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detections/pages/detection_engine/rules/helpers.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/detections/pages/detection_engine/rules/helpers.test.tsx @@ -148,7 +148,11 @@ describe('rule helpers', () => { references: ['www.test.co'], riskScore: { value: 21, mapping: [], isMappingChecked: false }, ruleNameOverride: 'message', - severity: { value: 'low', mapping: fillEmptySeverityMappings([]), isMappingChecked: false }, + severity: { + value: 'low', + mapping: fillEmptySeverityMappings([]), + isMappingChecked: false, + }, tags: ['tag1', 'tag2'], threat: getThreatMock(), timestampOverride: 'event.ingested', diff --git a/x-pack/solutions/security/plugins/security_solution/public/detections/pages/detection_engine/rules/helpers.tsx b/x-pack/solutions/security/plugins/security_solution/public/detections/pages/detection_engine/rules/helpers.tsx index 1dff767667450..f9edd66e7fb20 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detections/pages/detection_engine/rules/helpers.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/detections/pages/detection_engine/rules/helpers.tsx @@ -43,7 +43,7 @@ import type { ActionsStepRule, } from './types'; import { DataSourceType, AlertSuppressionDurationType } from './types'; -import { severityOptions } from '../../../../detection_engine/rule_creation_ui/components/step_about_rule/data'; +import { SeverityLevel } from '../../../../detection_engine/rule_creation_ui/components/step_about_rule/data'; import { DEFAULT_SUPPRESSION_MISSING_FIELDS_STRATEGY } from '../../../../../common/detection_engine/constants'; import type { RuleAction, RuleResponse } from '../../../../../common/api/detection_engine'; import { normalizeMachineLearningJobId } from '../../../../common/utils/normalize_machine_learning_job_id'; @@ -272,11 +272,14 @@ const severitySortMapping = { }; export const fillEmptySeverityMappings = (mappings: SeverityMapping): SeverityMapping => { - const missingMappings: SeverityMapping = severityOptions.flatMap((so) => - mappings.find((mapping) => mapping.severity === so.value) == null - ? [{ field: '', value: '', operator: 'equals', severity: so.value }] - : [] - ); + const missingMappings: SeverityMapping = Object.values(SeverityLevel).flatMap((severityLevel) => { + const isSeverityLevelInMappings = mappings.some( + (mapping) => mapping.severity === severityLevel + ); + return isSeverityLevelInMappings + ? [] + : [{ field: '', value: '', operator: 'equals', severity: severityLevel }]; + }); return [...mappings, ...missingMappings].sort( (a, b) => severitySortMapping[a.severity] - severitySortMapping[b.severity] ); diff --git a/x-pack/solutions/security/plugins/security_solution/public/detections/pages/detection_engine/rules/utils.ts b/x-pack/solutions/security/plugins/security_solution/public/detections/pages/detection_engine/rules/utils.ts index f0529e22114a7..1a8bbeef18fc6 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detections/pages/detection_engine/rules/utils.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/detections/pages/detection_engine/rules/utils.ts @@ -85,7 +85,11 @@ export const stepAboutDefaultValue: AboutStepRule = { description: '', isAssociatedToEndpointList: false, isBuildingBlock: false, - severity: { value: 'low', mapping: fillEmptySeverityMappings([]), isMappingChecked: false }, + severity: { + value: 'low', + mapping: fillEmptySeverityMappings([]), + isMappingChecked: false, + }, riskScore: { value: 21, mapping: [], isMappingChecked: false }, investigationFields: [], references: [''], diff --git a/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/common/utils.ts b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/common/utils.ts index 4833f14ba55cb..8c8ee528a50e7 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/common/utils.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/common/utils.ts @@ -5,7 +5,6 @@ * 2.0. */ -import { euiLightVars } from '@kbn/ui-theme'; import { RiskSeverity } from '../../../common/search_strategy'; import { SEVERITY_COLOR } from '../../overview/components/detection_response/utils'; export { RISK_LEVEL_RANGES as RISK_SCORE_RANGES } from '../../../common/entity_analytics/risk_engine'; @@ -18,8 +17,12 @@ export const SEVERITY_UI_SORT_ORDER = [ RiskSeverity.Critical, ]; +// Migration to tokens from EUI during the Borealis theme migration is blocked until new severity palette is agreed upon. +// We keep using hardcoded colors until security severity palette is ready https://github.com/elastic/kibana/issues/203387 +// TODO: Borealis migration - move from hardcoded values to severity palette, which should instead use shared hook across security: +// https://github.com/elastic/security-team/issues/11516 hook - https://github.com/elastic/kibana/pull/206276 export const RISK_SEVERITY_COLOUR: { [k in RiskSeverity]: string } = { - [RiskSeverity.Unknown]: euiLightVars.euiColorMediumShade, + [RiskSeverity.Unknown]: '#aaa', // euiThemeVars no longer in use. Hard coded temporarily, see above. [RiskSeverity.Low]: SEVERITY_COLOR.low, [RiskSeverity.Moderate]: SEVERITY_COLOR.medium, [RiskSeverity.High]: SEVERITY_COLOR.high, diff --git a/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/asset_criticality/asset_criticality_badge.tsx b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/asset_criticality/asset_criticality_badge.tsx index a4c7344ca5607..4e8c7329bdd31 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/asset_criticality/asset_criticality_badge.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/asset_criticality/asset_criticality_badge.tsx @@ -10,6 +10,7 @@ import { euiLightVars } from '@kbn/ui-theme'; import { CRITICALITY_LEVEL_TITLE } from './translations'; import type { CriticalityLevelWithUnassigned } from '../../../../common/entity_analytics/asset_criticality/types'; +// below will be updated with new severity color palette & shared security wide severity colors hook creation export const CRITICALITY_LEVEL_COLOR: Record = { extreme_impact: '#E7664C', high_impact: '#DA8B45', diff --git a/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/asset_criticality_file_uploader/components/file_picker_step.tsx b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/asset_criticality_file_uploader/components/file_picker_step.tsx index 6dbd1d87b29a6..9663fc242be51 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/asset_criticality_file_uploader/components/file_picker_step.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/asset_criticality_file_uploader/components/file_picker_step.tsx @@ -13,15 +13,17 @@ import { EuiSpacer, EuiText, EuiTitle, + useEuiFontSize, useEuiTheme, } from '@elastic/eui'; + import { css } from '@emotion/css'; import React from 'react'; import { FormattedMessage, useI18n } from '@kbn/i18n-react'; -import { euiThemeVars } from '@kbn/ui-theme'; import { useAssetCriticalityEntityTypes } from '../../../hooks/use_enabled_entity_types'; import { EntityTypeToIdentifierField } from '../../../../../common/entity_analytics/types'; + import { CRITICALITY_CSV_MAX_SIZE_BYTES, ValidCriticalityLevels, @@ -37,19 +39,20 @@ interface AssetCriticalityFilePickerStepProps { const sampleCSVContent = `user,user-001,low_impact\nuser,user-002,medium_impact\nhost,host-001,extreme_impact`; -const listStyle = css` - list-style-type: disc; - margin-bottom: ${euiThemeVars.euiSizeL}; - margin-left: ${euiThemeVars.euiSizeL}; - line-height: ${euiThemeVars.euiLineHeight}; -`; - export const AssetCriticalityFilePickerStep: React.FC = React.memo(({ onFileChange, errorMessage, isLoading }) => { const i18n = useI18n(); const formatBytes = useFormatBytes(); const { euiTheme } = useEuiTheme(); + + const listStyle = css` + list-style-type: disc; + margin-bottom: ${euiTheme.size.l}; + margin-left: ${euiTheme.size.l}; + line-height: ${useEuiFontSize('s').lineHeight}; + `; + const entityTypes = useAssetCriticalityEntityTypes(); const i18nOrList = (items: string[]) => i18n diff --git a/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/asset_criticality_file_uploader/components/validation_step.tsx b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/asset_criticality_file_uploader/components/validation_step.tsx index c4dadc756c15b..f12db29f7fac3 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/asset_criticality_file_uploader/components/validation_step.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/asset_criticality_file_uploader/components/validation_step.tsx @@ -100,7 +100,7 @@ export const AssetCriticalityValidationStep: React.FC {validLines.text} diff --git a/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/entity_store/components/engines_status/components/engine_status_header.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/entity_store/components/engines_status/components/engine_status_header.test.tsx new file mode 100644 index 0000000000000..464b7491c5a83 --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/entity_store/components/engines_status/components/engine_status_header.test.tsx @@ -0,0 +1,33 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { render } from '@testing-library/react'; +import { EngineStatusHeader } from './engine_status_header'; +import { capitalize } from 'lodash/fp'; +import { EntityType } from '../../../../../../../common/entity_analytics/types'; +import { TestProviders } from '../../../../../../common/mock'; + +describe('EngineStatusHeader', () => { + it('renders the title with the capitalized entity type', () => { + const { getByText } = render(, { + wrapper: TestProviders, + }); + expect(getByText(`${capitalize(EntityType.host)} Store`)).toBeInTheDocument(); + }); + + it('renders the action button if provided', () => { + const actionButton = ; + const { getByText } = render( + , + { + wrapper: TestProviders, + } + ); + expect(getByText('Click me')).toBeInTheDocument(); + }); +}); diff --git a/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/entity_store/components/engines_status/components/engine_status_header.tsx b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/entity_store/components/engines_status/components/engine_status_header.tsx new file mode 100644 index 0000000000000..caadd3d598b30 --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/entity_store/components/engines_status/components/engine_status_header.tsx @@ -0,0 +1,39 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { EuiFlexItem, EuiTitle, EuiFlexGroup } from '@elastic/eui'; +import { capitalize } from 'lodash/fp'; +import { FormattedMessage } from '@kbn/i18n-react'; +import type { EntityType } from '../../../../../../../common/entity_analytics/types'; + +export const EngineStatusHeader = ({ + entityType, + actionButton, +}: { + entityType: EntityType; + actionButton?: React.ReactNode; +}) => ( + +

+ + + + + + {actionButton} + + +

+
+); diff --git a/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/entity_store/components/engines_status/components/engine_status_header_action.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/entity_store/components/engines_status/components/engine_status_header_action.test.tsx new file mode 100644 index 0000000000000..ca67becf64d8a --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/entity_store/components/engines_status/components/engine_status_header_action.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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { render, screen, fireEvent } from '@testing-library/react'; +import { EngineStatusHeaderAction } from './engine_status_header_action'; +import { useEnableEntityStoreMutation } from '../../../hooks/use_entity_store'; +import { isEngineLoading } from '../helpers'; +import type { GetEntityStoreStatusResponse } from '../../../../../../../common/api/entity_analytics/entity_store/status.gen'; +import { EntityType } from '../../../../../../../common/entity_analytics/types'; +import { TestProviders } from '../../../../../../common/mock'; +import type { EngineComponentStatus } from '../../../../../../../common/api/entity_analytics'; + +jest.mock('../../../hooks/use_entity_store'); +jest.mock('../helpers'); + +const mockUseEnableEntityStoreMutation = useEnableEntityStoreMutation as jest.Mock; +const mockIsEngineLoading = isEngineLoading as jest.Mock; + +const defaultComponent: EngineComponentStatus = { + id: 'component1', + resource: 'entity_engine', + installed: true, +}; + +const defaultEngineResponse: GetEntityStoreStatusResponse['engines'][0] = { + type: EntityType.user, + indexPattern: '', + status: 'started', + fieldHistoryLength: 0, + components: [defaultComponent], + lookbackPeriod: '', +}; + +describe('EngineStatusHeaderAction', () => { + beforeEach(() => { + mockUseEnableEntityStoreMutation.mockReturnValue({ + mutate: jest.fn(), + isLoading: false, + }); + mockIsEngineLoading.mockReturnValue(false); + }); + + it('renders loading spinner when loading', () => { + mockUseEnableEntityStoreMutation.mockReturnValue({ + mutate: jest.fn(), + isLoading: true, + }); + + render(, { + wrapper: TestProviders, + }); + expect(screen.getByRole('progressbar')).toBeInTheDocument(); + }); + + it('renders install button when engine is undefined', () => { + render(, { + wrapper: TestProviders, + }); + expect(screen.getByText('Install')).toBeInTheDocument(); + }); + + it('calls installEntityStore when install button is clicked', () => { + const mutate = jest.fn(); + mockUseEnableEntityStoreMutation.mockReturnValue({ + mutate, + isLoading: false, + }); + + render(, { + wrapper: TestProviders, + }); + fireEvent.click(screen.getByText('Install')); + expect(mutate).toHaveBeenCalledWith({ entityTypes: [EntityType.user] }); + }); + + it('calls installEntityStore when reinstall button is clicked', () => { + const engine: GetEntityStoreStatusResponse['engines'][0] = { + ...defaultEngineResponse, + components: [{ ...defaultComponent, installed: false }], + }; + const mutate = jest.fn(); + mockUseEnableEntityStoreMutation.mockReturnValue({ + mutate, + isLoading: false, + }); + + render(, { + wrapper: TestProviders, + }); + fireEvent.click(screen.getByText('Reinstall')); + expect(mutate).toHaveBeenCalledWith({ entityTypes: [EntityType.user] }); + }); + + it('renders reinstall button and tooltip when a component is not installed', () => { + const engine: GetEntityStoreStatusResponse['engines'][0] = { + ...defaultEngineResponse, + components: [{ ...defaultComponent, installed: false }], + }; + + render(, { + wrapper: TestProviders, + }); + expect(screen.getByText('Reinstall')).toBeInTheDocument(); + }); + + it('renders not action when engine is defined and no error', () => { + render(, { + wrapper: TestProviders, + }); + expect(screen.queryByText('Install')).not.toBeInTheDocument(); + expect(screen.queryByText('Reinstall')).not.toBeInTheDocument(); + }); +}); diff --git a/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/entity_store/components/engines_status/components/engine_status_header_action.tsx b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/entity_store/components/engines_status/components/engine_status_header_action.tsx new file mode 100644 index 0000000000000..5dce64cdbd6a7 --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/entity_store/components/engines_status/components/engine_status_header_action.tsx @@ -0,0 +1,70 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { EuiLoadingSpinner, EuiButtonEmpty, EuiIconTip } from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n-react'; +import { useEnableEntityStoreMutation } from '../../../hooks/use_entity_store'; +import type { GetEntityStoreStatusResponse } from '../../../../../../../common/api/entity_analytics/entity_store/status.gen'; +import type { EntityType } from '../../../../../../../common/entity_analytics/types'; +import { isEngineLoading } from '../helpers'; + +export function EngineStatusHeaderAction({ + engine, + type, +}: { + engine: GetEntityStoreStatusResponse['engines'][0] | undefined; + type: EntityType; +}) { + const enableEntityStore = useEnableEntityStoreMutation(); + const installEntityStore = () => { + enableEntityStore.mutate({ entityTypes: [type] }); + }; + const hasUninstalledComponent = engine?.components?.some(({ installed }) => !installed); + + if (enableEntityStore.isLoading || isEngineLoading(engine?.status)) { + return ; + } + + if (!engine) { + return ( + + + + ); + } + + if (hasUninstalledComponent) { + return ( +
+ + + + + + } + color="warning" + position="right" + type="iInCircle" + /> +
+ ); + } + + return null; +} diff --git a/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/entity_store/components/engines_status/helpers.ts b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/entity_store/components/engines_status/helpers.ts new file mode 100644 index 0000000000000..0bfe4c8229383 --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/entity_store/components/engines_status/helpers.ts @@ -0,0 +1,11 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { EngineStatus } from '../../../../../../common/api/entity_analytics/entity_store/common.gen'; + +export const isEngineLoading = (status: EngineStatus | undefined) => + status === 'updating' || status === 'installing'; diff --git a/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/entity_store/components/engines_status/index.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/entity_store/components/engines_status/index.test.tsx index 2f9e74df39d39..7ee47692d3715 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/entity_store/components/engines_status/index.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/entity_store/components/engines_status/index.test.tsx @@ -10,10 +10,16 @@ import { render, screen, fireEvent } from '@testing-library/react'; import { EngineStatus } from '.'; import { TestProviders } from '@kbn/timelines-plugin/public/mock'; +import { mockGlobalState } from '../../../../../common/mock'; +import { EntityType } from '../../../../../../common/entity_analytics/types'; const mockUseEntityStore = jest.fn(); jest.mock('../../hooks/use_entity_store', () => ({ useEntityStoreStatus: () => mockUseEntityStore(), + useEnableEntityStoreMutation: () => ({ + mutate: jest.fn(), + isLoading: false, + }), })); const mockDownloadBlob = jest.fn(); @@ -21,6 +27,11 @@ jest.mock('../../../../../common/utils/download_blob', () => ({ downloadBlob: () => mockDownloadBlob(), })); +const mockedExperimentalFeatures = mockGlobalState.app.enableExperimental; +jest.mock('../../../../../common/hooks/use_experimental_features', () => ({ + useEnableExperimental: () => mockedExperimentalFeatures, +})); + describe('EngineStatus', () => { beforeEach(() => { jest.clearAllMocks(); @@ -66,7 +77,7 @@ describe('EngineStatus', () => { const mockData = { engines: [ { - type: 'test', + type: EntityType.user, components: [{ id: 'entity_engine_id', installed: true, resource: 'entity_engine' }], }, ], @@ -75,7 +86,7 @@ describe('EngineStatus', () => { render(, { wrapper: TestProviders }); - expect(screen.getByText('Test Store')).toBeInTheDocument(); + expect(screen.getByText('User Store')).toBeInTheDocument(); expect(screen.getByText('Download status')).toBeInTheDocument(); }); @@ -83,7 +94,7 @@ describe('EngineStatus', () => { const mockData = { engines: [ { - type: 'test', + type: EntityType.user, components: [{ id: 'entity_engine_id', installed: true, resource: 'entity_engine' }], }, ], diff --git a/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/entity_store/components/engines_status/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/entity_store/components/engines_status/index.tsx index 692841334bd50..0385e789374e1 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/entity_store/components/engines_status/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/entity_store/components/engines_status/index.tsx @@ -12,41 +12,48 @@ import { EuiSpacer, EuiButtonEmpty, EuiFlexItem, - EuiTitle, EuiFlexGroup, EuiCallOut, } from '@elastic/eui'; -import { capitalize } from 'lodash/fp'; import { FormattedMessage } from '@kbn/i18n-react'; import { i18n } from '@kbn/i18n'; +import { useStoreEntityTypes } from '../../../../hooks/use_enabled_entity_types'; import { useErrorToast } from '../../../../../common/hooks/use_error_toast'; import { downloadBlob } from '../../../../../common/utils/download_blob'; import { EngineComponentsStatusTable } from './components/engine_components_status'; import { useEntityStoreStatus } from '../../hooks/use_entity_store'; +import { isEngineLoading } from './helpers'; +import { EngineStatusHeader } from './components/engine_status_header'; +import { EngineStatusHeaderAction } from './components/engine_status_header_action'; const FILE_NAME = 'engines_status.json'; +const errorMessage = i18n.translate( + 'xpack.securitySolution.entityAnalytics.entityStore.enginesStatus.queryError', + { + defaultMessage: 'There was an error loading the engine status', + } +); + export const EngineStatus: React.FC = () => { - const { data, isLoading, error } = useEntityStoreStatus({ withComponents: true }); + const { + data, + isLoading: isStatusAPILoading, + error, + } = useEntityStoreStatus({ withComponents: true }); + const enabledEntityTypes = useStoreEntityTypes(); const downloadJson = () => { downloadBlob(new Blob([JSON.stringify(data)]), FILE_NAME); }; - const errorMessage = i18n.translate( - 'xpack.securitySolution.entityAnalytics.entityStore.enginesStatus.queryError', - { - defaultMessage: 'There was an error loading the engine status', - } - ); - useErrorToast(errorMessage, error); if (error) { return ; } - if (!data || isLoading) return ; + if (!data || isStatusAPILoading) return ; if (data.engines.length === 0) { return ( @@ -57,6 +64,11 @@ export const EngineStatus: React.FC = () => { ); } + const enginesStatusData = enabledEntityTypes.map((type) => ({ + type, + engine: data.engines.find((e) => e.type === type), + })); + return ( {data?.engines?.length > 0 && ( @@ -74,29 +86,23 @@ export const EngineStatus: React.FC = () => {
)} - {(data?.engines ?? []).map((engine) => ( - - -

- -

-
- - - - - {engine.components && } - - - -
- ))} + {enginesStatusData.map(({ engine, type }) => { + return ( + + } + /> + + + {engine && !isEngineLoading(engine.status) && engine.components && ( + + )} + + + + ); + })}
); diff --git a/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/entity_store/hooks/use_entity_store.ts b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/entity_store/hooks/use_entity_store.ts index f6b7497d6564b..637a96fee392b 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/entity_store/hooks/use_entity_store.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/entity_store/hooks/use_entity_store.ts @@ -18,7 +18,6 @@ import { useKibana } from '../../../../common/lib/kibana/kibana_react'; import type { EntityType } from '../../../../../common/api/entity_analytics'; import { type DeleteEntityEngineResponse, - type InitEntityEngineResponse, type StopEntityEngineResponse, } from '../../../../../common/api/entity_analytics'; import { useEntityStoreRoutes } from '../../../api/entity_store'; @@ -82,23 +81,6 @@ export const useEnableEntityStoreMutation = ( }; export const INIT_ENTITY_ENGINE_STATUS_KEY = ['POST', 'INIT_ENTITY_ENGINE']; -/** - * @deprecated - * It will be deleted on a follow-up PR - */ -export const useInitEntityEngineMutation = (options?: UseMutationOptions<{}>) => { - const queryClient = useQueryClient(); - - const { initEntityEngine } = useEntityStoreRoutes(); - return useMutation( - () => Promise.all([initEntityEngine('user'), initEntityEngine('host')]), - { - mutationKey: INIT_ENTITY_ENGINE_STATUS_KEY, - onSuccess: () => queryClient.refetchQueries({ queryKey: ENTITY_STORE_STATUS }), - ...options, - } - ); -}; export const STOP_ENTITY_ENGINE_STATUS_KEY = ['POST', 'STOP_ENTITY_ENGINE']; export const useStopEntityEngineMutation = (entityTypes: EntityType[]) => { diff --git a/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/risk_information/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/risk_information/index.tsx index f5b407378bde4..35ab3b8c17ef7 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/risk_information/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/risk_information/index.tsx @@ -144,7 +144,7 @@ export const RiskInformationFlyout = ({ handleOnClose }: { handleOnClose: () => label={BETA} size="s" css={css` - color: ${euiTheme.colors.text}; + color: ${euiTheme.colors.textParagraph}; margin-top: ${euiTheme.size.xxs}; `} /> diff --git a/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/risk_score_donut_chart/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/risk_score_donut_chart/index.tsx index 92ae592368ba5..bc4a704b48655 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/risk_score_donut_chart/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/risk_score_donut_chart/index.tsx @@ -21,12 +21,6 @@ import type { RiskSeverity } from '../../../../common/search_strategy'; const DONUT_HEIGHT = 120; -const fillColor: FillColor = (dataName) => { - return Object.hasOwn(RISK_SEVERITY_COLOUR, dataName) - ? RISK_SEVERITY_COLOUR[dataName as RiskSeverity] - : emptyDonutColor; -}; - const DonutContainer = styled(EuiFlexItem)` padding-right: ${({ theme }) => theme.eui.euiSizeXXL}; padding-left: ${({ theme }) => theme.eui.euiSizeM}; @@ -42,7 +36,13 @@ interface RiskScoreDonutChartProps { export const RiskScoreDonutChart = ({ severityCount }: RiskScoreDonutChartProps) => { const [donutChartData, legendItems, total] = useRiskDonutChartData(severityCount); - + // TODO: Borealis theme migration, when severity palette agreed, update RISK_SEVERITY_COLOUR to use shared hook from security colors: + // https://github.com/elastic/security-team/issues/11516 hook - https://github.com/elastic/kibana/pull/206276 + const fillColorValue: FillColor = (dataName) => { + return Object.hasOwn(RISK_SEVERITY_COLOUR, dataName) + ? RISK_SEVERITY_COLOUR[dataName as RiskSeverity] + : emptyDonutColor; + }; return ( @@ -51,7 +51,7 @@ export const RiskScoreDonutChart = ({ severityCount }: RiskScoreDonutChartProps) { const [donutChartData, legendItems, total] = useMemo(() => { const severities = Object.keys(RISK_SEVERITY_COLOUR) as RiskSeverity[]; - + // TODO: Borealis theme migration, when severity palette agreed, update RISK_SEVERITY_COLOUR to use shared hook from security colors: + // https://github.com/elastic/security-team/issues/11516 hook - https://github.com/elastic/kibana/pull/206276 return [ severities.map((status) => ({ key: status, diff --git a/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/risk_summary_flyout/risk_summary.tsx b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/risk_summary_flyout/risk_summary.tsx index eb6dcdf049558..64ecb0dbd87e6 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/risk_summary_flyout/risk_summary.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/risk_summary_flyout/risk_summary.tsx @@ -19,7 +19,6 @@ import { } from '@elastic/eui'; import { css } from '@emotion/react'; import { FormattedMessage } from '@kbn/i18n-react'; -import { euiThemeVars } from '@kbn/ui-theme'; import dateMath from '@kbn/datemath'; import { i18n } from '@kbn/i18n'; import { capitalize } from 'lodash/fp'; @@ -71,7 +70,6 @@ const FlyoutRiskSummaryComponent = ({ const riskData = data && data.length > 0 ? data[0] : undefined; const entityData = getEntityData(entityType, riskData); const { euiTheme } = useEuiTheme(); - const lensAttributes = useMemo(() => { const entityName = entityData?.name ?? ''; const fieldName = EntityTypeToIdentifierField[entityType]; @@ -81,9 +79,10 @@ const FlyoutRiskSummaryComponent = ({ query: `${fieldName}: ${entityName}`, spaceId: 'default', riskEntity: entityType, + // TODO: add in riskColors when severity palette agreed on. + // https://github.com/elastic/security-team/issues/11516 hook - https://github.com/elastic/kibana/pull/206276 }); }, [entityData?.name, entityData?.risk?.calculated_level, entityType]); - const xsFontSize = useEuiFontSize('xxs').fontSize; const rows = useMemo(() => getItems(entityData), [entityData]); @@ -247,7 +246,7 @@ const FlyoutRiskSummaryComponent = ({ css={css` position: absolute; right: 0; - top: -${euiThemeVars.euiSize}; + top: -${euiTheme.size.base}; `} > { ); expect(container).toHaveTextContent(RiskSeverity.Critical); - expect(EuiHealth as jest.Mock).toHaveBeenLastCalledWith( expect.objectContaining({ color: SEVERITY_COLOR.critical }), - context + {} ); }); @@ -98,7 +96,8 @@ describe('RiskScore', () => { expect(container).toHaveTextContent(RiskSeverity.Unknown); expect(EuiHealth as jest.Mock).toHaveBeenLastCalledWith( - expect.objectContaining({ color: euiThemeVars.euiColorMediumShade }), + expect.objectContaining({ color: '#aaa' }), // TODO: update with new severity palette agreement. + // https://github.com/elastic/security-team/issues/11516 hook - https://github.com/elastic/kibana/pull/206276 context ); }); diff --git a/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/severity/common/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/severity/common/index.tsx index e010c3bd42169..123027fd81da9 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/severity/common/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/severity/common/index.tsx @@ -7,17 +7,19 @@ import React from 'react'; -import { EuiHealth, EuiTextColor, transparentize } from '@elastic/eui'; +import { EuiHealth, EuiTextColor, useEuiTheme } from '@elastic/eui'; import styled, { css } from 'styled-components'; -import { euiLightVars } from '@kbn/ui-theme'; import { RISK_SEVERITY_COLOUR } from '../../../common/utils'; import { HoverPopover } from '../../../../common/components/hover_popover'; import type { RiskSeverity } from '../../../../../common/search_strategy'; -const RiskBadge = styled.div<{ $severity: RiskSeverity; $hideBackgroundColor: boolean }>` - ${({ theme, $severity, $hideBackgroundColor }) => css` +const RiskBadge = styled.div<{ + $severity: RiskSeverity; + $hideBackgroundColor: boolean; +}>` + ${({ theme, color, $severity, $hideBackgroundColor }) => css` width: fit-content; padding-right: ${theme.eui.euiSizeS}; padding-left: ${theme.eui.euiSizeXS}; @@ -25,13 +27,13 @@ const RiskBadge = styled.div<{ $severity: RiskSeverity; $hideBackgroundColor: bo ${($severity === 'Critical' || $severity === 'High') && !$hideBackgroundColor && css` - background-color: ${transparentize(theme.eui.euiColorDanger, 0.2)}; + background-color: ${color}; border-radius: 999px; // pill shaped `}; `} `; const TooltipContainer = styled.div` - padding: ${({ theme }) => theme.eui.euiSizeS}; + padding: ${({ theme }) => theme.euiSizeS}; `; export const RiskScoreLevel: React.FC<{ @@ -68,18 +70,23 @@ const RiskScoreBadge: React.FC<{ severity: RiskSeverity; hideBackgroundColor?: boolean; ['data-test-subj']?: string; -}> = React.memo(({ severity, hideBackgroundColor = false, 'data-test-subj': dataTestSubj }) => ( - - - - {severity} - - - -)); +}> = React.memo(({ severity, hideBackgroundColor = false, 'data-test-subj': dataTestSubj }) => { + const { euiTheme } = useEuiTheme(); + // TODO: use riskSeverity hook when palette agreed. + // https://github.com/elastic/security-team/issues/11516 hook - https://github.com/elastic/kibana/pull/206276 + return ( + + + + {severity} + + + + ); +}); RiskScoreBadge.displayName = 'RiskScoreBadge'; diff --git a/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/severity/severity_badges.tsx b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/severity/severity_badges.tsx index 373a8dd5a5693..a1a83d8c4d40a 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/severity/severity_badges.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/severity/severity_badges.tsx @@ -14,24 +14,28 @@ import type { SeverityCount } from './types'; export const SeverityBadges: React.FC<{ severityCount: SeverityCount; -}> = React.memo(({ severityCount }) => ( - - - - - {(Object.keys(RISK_SEVERITY_COLOUR) as RiskSeverity[]).map((status) => ( - - - - ))} - - - -)); +}> = React.memo(({ severityCount }) => { + // TODO: use riskSeverity hook when palette agreed. + // https://github.com/elastic/security-team/issues/11516 hook - https://github.com/elastic/kibana/pull/206276 + return ( + + + + + {(Object.keys(RISK_SEVERITY_COLOUR) as RiskSeverity[]).map((status) => ( + + + + ))} + + + + ); +}); SeverityBadges.displayName = 'SeverityBadges'; diff --git a/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/severity/severity_bar.tsx b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/severity/severity_bar.tsx index 149d8f2cf74b9..e643407cde5f4 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/severity/severity_bar.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/severity/severity_bar.tsx @@ -31,6 +31,8 @@ type PalletteArray = PalletteObject[]; export const SeverityBar: React.FC<{ severityCount: SeverityCount; }> = ({ severityCount }) => { + // TODO: use riskSeverity hook when palette agreed. + // https://github.com/elastic/security-team/issues/11516 hook - https://github.com/elastic/kibana/pull/206276 const palette = useMemo( () => (Object.keys(RISK_SEVERITY_COLOUR) as RiskSeverity[]).reduce( diff --git a/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/lens_attributes/__snapshots__/risk_score_summary.test.ts.snap b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/lens_attributes/__snapshots__/risk_score_summary.test.ts.snap index 225ff3ef8c7a0..7f8b46a9f5bb4 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/lens_attributes/__snapshots__/risk_score_summary.test.ts.snap +++ b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/lens_attributes/__snapshots__/risk_score_summary.test.ts.snap @@ -113,7 +113,7 @@ Object { "params": Object { "colorStops": Array [ Object { - "color": "#98a2b3", + "color": "#aaa", "stop": 0, }, Object { @@ -144,7 +144,7 @@ Object { "steps": 3, "stops": Array [ Object { - "color": "#98a2b3", + "color": "#aaa", "stop": 20, }, Object { diff --git a/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/lens_attributes/risk_score_summary.test.ts b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/lens_attributes/risk_score_summary.test.ts index 994bfc3de4c55..943a62a6e689d 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/lens_attributes/risk_score_summary.test.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/lens_attributes/risk_score_summary.test.ts @@ -74,6 +74,7 @@ describe('getRiskScoreSummaryAttributes', () => { spaceId: 'default', riskEntity: EntityType.user, }), + applyGlobalQueriesAndFilters: false, }), { wrapper } diff --git a/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/lens_attributes/risk_score_summary.ts b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/lens_attributes/risk_score_summary.ts index bf6f6897f8bb9..44108c683c77a 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/lens_attributes/risk_score_summary.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/lens_attributes/risk_score_summary.ts @@ -8,7 +8,8 @@ import { v4 as uuidv4 } from 'uuid'; import type { LensAttributes } from '@kbn/lens-embeddable-utils'; import capitalize from 'lodash/capitalize'; -import { SEVERITY_UI_SORT_ORDER, RISK_SEVERITY_COLOUR, RISK_SCORE_RANGES } from '../common/utils'; + +import { SEVERITY_UI_SORT_ORDER, RISK_SCORE_RANGES, RISK_SEVERITY_COLOUR } from '../common/utils'; import type { EntityType } from '../../../common/entity_analytics/types'; import type { RiskSeverity } from '../../../common/search_strategy'; import { EntityTypeToScoreField, RiskScoreFields } from '../../../common/search_strategy'; @@ -17,17 +18,20 @@ interface GetRiskScoreSummaryAttributesProps { query?: string; spaceId?: string; severity?: RiskSeverity; + // TODO: add riskColors in when severityPalette available + // riskColors: { [k in RiskSeverity]: string }; riskEntity: EntityType; } export const getRiskScoreSummaryAttributes: ( props: GetRiskScoreSummaryAttributesProps + // TODO: may need to pass riskColors in props, here, when severity palette agreed and hook created + // https://github.com/elastic/security-team/issues/11516 hook - https://github.com/elastic/kibana/pull/206276 ) => LensAttributes = ({ spaceId, query, severity, riskEntity }) => { const layerIds = [uuidv4(), uuidv4()]; const internalReferenceId = uuidv4(); const columnIds = [uuidv4(), uuidv4(), uuidv4()]; const sourceField = EntityTypeToScoreField[riskEntity]; - return { title: 'Risk score summary', description: '', diff --git a/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/pages/entity_store_management_page.tsx b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/pages/entity_store_management_page.tsx index 9bdb73d814021..5884ebae100c7 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/pages/entity_store_management_page.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/entity_analytics/pages/entity_store_management_page.tsx @@ -57,7 +57,8 @@ enum TabId { Status = 'status', } -const isSwitchDisabled = (status?: StoreStatus) => status === 'error' || status === 'installing'; +const isSwitchLoading = (status?: StoreStatus) => status === 'installing'; +const isSwitchDisabled = (status?: StoreStatus) => status === 'error' || isSwitchLoading(status); const isEntityStoreEnabled = (status?: StoreStatus) => status === 'running'; const canDeleteEntityEngine = (status?: StoreStatus) => !['not_installed', 'installing'].includes(status || ''); @@ -164,7 +165,7 @@ export const EntityStoreManagementPage = () => { !isEntityStoreFeatureFlagDisabled && privileges?.has_all_required ? [ { }); describe('getFormattedAlertStats', () => { + const { result } = renderHook(() => useEuiTheme()); + const euiTheme = result.current.euiTheme; + it('should return alert stats', () => { - const alertStats = getFormattedAlertStats(mockAlertData); + const alertStats = getFormattedAlertStats(mockAlertData, euiTheme); expect(alertStats).toEqual([ - { key: 'High', count: 2, color: SEVERITY_COLOR.high }, - { key: 'Low', count: 2, color: SEVERITY_COLOR.low }, - { key: 'Medium', count: 2, color: SEVERITY_COLOR.medium }, - { key: 'Critical', count: 2, color: SEVERITY_COLOR.critical }, + { key: 'High', count: 2, color: '#ff7e62' }, + { key: 'Low', count: 2, color: '#54b399' }, + { key: 'Medium', count: 2, color: '#f1d86f' }, + { key: 'Critical', count: 2, color: '#bd271e' }, ]); }); it('should return empty array if no active alerts are available', () => { - const alertStats = getFormattedAlertStats({ - closed: { - total: 2, - severities: [ - { key: 'high', value: 1, label: 'High' }, - { key: 'low', value: 1, label: 'Low' }, - ], + const alertStats = getFormattedAlertStats( + { + closed: { + total: 2, + severities: [ + { key: 'high', value: 1, label: 'High' }, + { key: 'low', value: 1, label: 'Low' }, + ], + }, }, - }); + euiTheme + ); expect(alertStats).toEqual([]); }); }); diff --git a/x-pack/solutions/security/plugins/security_solution/public/flyout/document_details/shared/components/alert_count_insight.tsx b/x-pack/solutions/security/plugins/security_solution/public/flyout/document_details/shared/components/alert_count_insight.tsx index 77a06132e463c..58c6e78b74bda 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/flyout/document_details/shared/components/alert_count_insight.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/flyout/document_details/shared/components/alert_count_insight.tsx @@ -7,7 +7,14 @@ import React, { useMemo } from 'react'; import { capitalize } from 'lodash'; -import { EuiLoadingSpinner, EuiFlexItem, EuiText, type EuiFlexGroupProps } from '@elastic/eui'; +import type { EuiThemeComputed } from '@elastic/eui'; +import { + EuiLoadingSpinner, + EuiFlexItem, + EuiText, + type EuiFlexGroupProps, + useEuiTheme, +} from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; import { InsightDistributionBar } from './insight_distribution_bar'; import { getSeverityColor } from '../../../../detections/components/alerts_kpis/severity_level_panel/helpers'; @@ -54,7 +61,10 @@ interface AlertCountInsightProps { /** * Filters closed alerts and format the alert stats for the distribution bar */ -export const getFormattedAlertStats = (alertsData: ParsedAlertsData) => { +export const getFormattedAlertStats = ( + alertsData: ParsedAlertsData, + euiTheme: EuiThemeComputed +) => { const severityMap = new Map(); const filteredAlertsData: ParsedAlertsData = alertsData @@ -73,7 +83,7 @@ export const getFormattedAlertStats = (alertsData: ParsedAlertsData) => { const alertStats = Array.from(severityMap, ([key, count]) => ({ key: capitalize(key), count, - color: getSeverityColor(key), + color: getSeverityColor(key, euiTheme), })); return alertStats; }; @@ -87,6 +97,7 @@ export const AlertCountInsight: React.FC = ({ direction, 'data-test-subj': dataTestSubj, }) => { + const { euiTheme } = useEuiTheme(); const { timelinePrivileges: { read: canUseTimeline }, } = useUserPrivileges(); @@ -103,7 +114,7 @@ export const AlertCountInsight: React.FC = ({ from, }); - const alertStats = useMemo(() => getFormattedAlertStats(items), [items]); + const alertStats = useMemo(() => getFormattedAlertStats(items, euiTheme), [items, euiTheme]); const totalAlertCount = useMemo( () => alertStats.reduce((acc, item) => acc + item.count, 0), diff --git a/x-pack/solutions/security/plugins/security_solution/public/flyout/entity_details/user_right/utils/columns.tsx b/x-pack/solutions/security/plugins/security_solution/public/flyout/entity_details/user_right/utils/columns.tsx index 22387fadbaf06..ffc4c2ce8ee94 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/flyout/entity_details/user_right/utils/columns.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/flyout/entity_details/user_right/utils/columns.tsx @@ -7,26 +7,31 @@ import { css } from '@emotion/react'; import React from 'react'; -import { euiThemeVars } from '@kbn/ui-theme'; -import type { EuiBasicTableColumn } from '@elastic/eui'; +import { useEuiTheme, type EuiBasicTableColumn } from '@elastic/eui'; import { DefaultFieldRenderer } from '../../../../timelines/components/field_renderers/default_renderer'; import type { ManagedUsersTableColumns, ManagedUserTable } from '../types'; import * as i18n from '../translations'; import { defaultToEmptyTag } from '../../../../common/components/empty_value'; -const fieldColumn: EuiBasicTableColumn = { - name: i18n.FIELD_COLUMN_TITLE, - field: 'label', - render: (label: string, { field }) => ( +const FieldColumn: React.FC<{ label: string; field: string }> = ({ label, field }) => { + const { euiTheme } = useEuiTheme(); + + return ( {label ?? field} - ), + ); +}; + +const fieldColumn: EuiBasicTableColumn = { + name: i18n.FIELD_COLUMN_TITLE, + field: 'label', + render: (label: string, { field }) => , }; export const getManagedUserTableColumns = ( diff --git a/x-pack/solutions/security/plugins/security_solution/public/kubernetes/links.ts b/x-pack/solutions/security/plugins/security_solution/public/kubernetes/links.ts deleted file mode 100644 index d71e1a3fc9da7..0000000000000 --- a/x-pack/solutions/security/plugins/security_solution/public/kubernetes/links.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 { i18n } from '@kbn/i18n'; -import { KUBERNETES_PATH, SecurityPageName } from '../../common/constants'; -import { KUBERNETES } from '../app/translations'; -import type { LinkItem } from '../common/links/types'; -import kubernetesPageImg from '../common/images/kubernetes_page.png'; - -export const links: LinkItem = { - id: SecurityPageName.kubernetes, - title: KUBERNETES, - landingImage: kubernetesPageImg, - description: i18n.translate('xpack.securitySolution.appLinks.kubernetesDescription', { - defaultMessage: - 'Provides interactive visualizations of your Kubernetes workload and session data.', - }), - path: KUBERNETES_PATH, - experimentalKey: 'kubernetesEnabled', - globalSearchKeywords: ['Kubernetes'], -}; diff --git a/x-pack/solutions/security/plugins/security_solution/public/kubernetes/pages/constants.ts b/x-pack/solutions/security/plugins/security_solution/public/kubernetes/pages/constants.ts deleted file mode 100644 index 4acc5bf038e75..0000000000000 --- a/x-pack/solutions/security/plugins/security_solution/public/kubernetes/pages/constants.ts +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import type { ColumnHeaderOptions } from '../../../common/types/timeline'; -import { defaultColumnHeaderType } from '../../timelines/components/timeline/body/column_headers/default_headers'; -import { DEFAULT_DATE_COLUMN_MIN_WIDTH } from '../../timelines/components/timeline/body/constants'; -import { - COLUMN_SESSION_START, - COLUMN_EXECUTABLE, - COLUMN_ENTRY_USER, - COLUMN_INTERACTIVE, - COLUMN_NODE, - COLUMN_CONTAINER, - COLUMN_POD, -} from './translations'; - -export const kubernetesSessionsHeaders: ColumnHeaderOptions[] = [ - { - columnHeaderType: defaultColumnHeaderType, - id: 'process.entry_leader.start', - initialWidth: DEFAULT_DATE_COLUMN_MIN_WIDTH, - display: COLUMN_SESSION_START, - }, - { - columnHeaderType: defaultColumnHeaderType, - id: 'process.entry_leader.executable', - display: COLUMN_EXECUTABLE, - }, - { - columnHeaderType: defaultColumnHeaderType, - id: 'process.entry_leader.user.id', - display: COLUMN_ENTRY_USER, - }, - { - columnHeaderType: defaultColumnHeaderType, - id: 'process.entry_leader.interactive', - display: COLUMN_INTERACTIVE, - }, - { - columnHeaderType: defaultColumnHeaderType, - id: 'cloud.instance.name', - display: COLUMN_NODE, - }, - { - columnHeaderType: defaultColumnHeaderType, - id: 'orchestrator.resource.name', - display: COLUMN_POD, - }, - { - columnHeaderType: defaultColumnHeaderType, - id: 'container.name', - display: COLUMN_CONTAINER, - }, -]; diff --git a/x-pack/solutions/security/plugins/security_solution/public/kubernetes/pages/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/kubernetes/pages/index.tsx deleted file mode 100644 index 55c8a4472379b..0000000000000 --- a/x-pack/solutions/security/plugins/security_solution/public/kubernetes/pages/index.tsx +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React, { useCallback, useMemo } from 'react'; -import { getEsQueryConfig } from '@kbn/data-plugin/common'; -import { TableId } from '@kbn/securitysolution-data-table'; -import { InputsModelId } from '../../common/store/inputs/constants'; -import { SecuritySolutionPageWrapper } from '../../common/components/page_wrapper'; -import { useKibana } from '../../common/lib/kibana'; -import { SecurityPageName } from '../../../common/constants'; -import { SpyRoute } from '../../common/utils/route/spy_routes'; -import { FiltersGlobal } from '../../common/components/filters_global'; -import { SiemSearchBar } from '../../common/components/search_bar'; -import { showGlobalFilters } from '../../timelines/components/timeline/helpers'; -import { inputsSelectors } from '../../common/store'; -import { useGlobalFullScreen } from '../../common/containers/use_full_screen'; -import { useSourcererDataView } from '../../sourcerer/containers'; -import { useGlobalTime } from '../../common/containers/use_global_time'; -import { useDeepEqualSelector } from '../../common/hooks/use_selector'; -import { convertToBuildEsQuery } from '../../common/lib/kuery'; -import { useInvalidFilterQuery } from '../../common/hooks/use_invalid_filter_query'; -import { SessionsView } from '../../common/components/sessions_viewer'; -import { kubernetesSessionsHeaders } from './constants'; -import { dataViewSpecToIndexPattern } from './utils/data_view_spec_to_index_pattern'; - -export const KubernetesContainer = React.memo(() => { - const { kubernetesSecurity, uiSettings } = useKibana().services; - - const { globalFullScreen } = useGlobalFullScreen(); - const { sourcererDataView, dataViewId } = useSourcererDataView(); - const { from, to } = useGlobalTime(); - - const getGlobalFiltersQuerySelector = useMemo( - () => inputsSelectors.globalFiltersQuerySelector(), - [] - ); - const getGlobalQuerySelector = useMemo(() => inputsSelectors.globalQuerySelector(), []); - const query = useDeepEqualSelector(getGlobalQuerySelector); - const filters = useDeepEqualSelector(getGlobalFiltersQuerySelector); - - const [filterQuery, kqlError] = useMemo( - () => - convertToBuildEsQuery({ - config: getEsQueryConfig(uiSettings), - dataViewSpec: sourcererDataView, - queries: [query], - filters, - }), - [filters, sourcererDataView, uiSettings, query] - ); - - useInvalidFilterQuery({ - id: 'kubernetesQuery', - filterQuery, - kqlError, - query, - startDate: from, - endDate: to, - }); - - const renderSessionsView = useCallback( - (sessionsFilterQuery: string | undefined) => ( - - ), - [from, to] - ); - - return ( - - {kubernetesSecurity.getKubernetesPage({ - filter: ( - - - - ), - indexPattern: dataViewSpecToIndexPattern(sourcererDataView), - globalFilter: { - filterQuery, - startDate: from, - endDate: to, - }, - renderSessionsView, - dataViewId: dataViewId ?? undefined, - })} - - - ); -}); - -KubernetesContainer.displayName = 'KubernetesContainer'; diff --git a/x-pack/solutions/security/plugins/security_solution/public/kubernetes/pages/translations.ts b/x-pack/solutions/security/plugins/security_solution/public/kubernetes/pages/translations.ts deleted file mode 100644 index 0a190e0a93d05..0000000000000 --- a/x-pack/solutions/security/plugins/security_solution/public/kubernetes/pages/translations.ts +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { i18n } from '@kbn/i18n'; - -export const COLUMN_SESSION_START = i18n.translate( - 'xpack.securitySolution.kubernetes.columnSessionStart', - { - defaultMessage: 'Date started', - } -); - -export const COLUMN_EXECUTABLE = i18n.translate( - 'xpack.securitySolution.kubernetes.columnExecutable', - { - defaultMessage: 'Executable', - } -); - -export const COLUMN_NODE = i18n.translate('xpack.securitySolution.kubernetes.columnNode', { - defaultMessage: 'Node', -}); - -export const COLUMN_ENTRY_USER = i18n.translate( - 'xpack.securitySolution.kubernetes.columnEntryUser', - { - defaultMessage: 'User ID', - } -); - -export const COLUMN_INTERACTIVE = i18n.translate( - 'xpack.securitySolution.kubernetes.columnInteractive', - { - defaultMessage: 'Interactive', - } -); - -export const COLUMN_CONTAINER = i18n.translate( - 'xpack.securitySolution.kubernetes.columnContainer', - { - defaultMessage: 'Container', - } -); -export const COLUMN_POD = i18n.translate('xpack.securitySolution.kubernetes.columnPod', { - defaultMessage: 'Pod', -}); diff --git a/x-pack/solutions/security/plugins/security_solution/public/kubernetes/pages/utils/breadcrumbs.ts b/x-pack/solutions/security/plugins/security_solution/public/kubernetes/pages/utils/breadcrumbs.ts deleted file mode 100644 index 9dcd76b838cac..0000000000000 --- a/x-pack/solutions/security/plugins/security_solution/public/kubernetes/pages/utils/breadcrumbs.ts +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import type { ChromeBreadcrumb } from '@kbn/core/public'; -import { SecurityPageName } from '../../../app/types'; -import { getKubernetesDetailsUrl } from '../../../common/components/link_to'; -import type { GetTrailingBreadcrumbs } from '../../../common/components/navigation/breadcrumbs/types'; - -/** - * This module should only export this function. - * All the `getTrailingBreadcrumbs` functions in Security are loaded into the main bundle. - * We should be careful to not import unnecessary modules in this file to avoid increasing the main app bundle size. - */ -export const getTrailingBreadcrumbs: GetTrailingBreadcrumbs = (params, getSecuritySolutionUrl) => { - let breadcrumb: ChromeBreadcrumb[] = []; - - if (params.detailName != null) { - breadcrumb = [ - { - text: params.detailName, - href: getSecuritySolutionUrl({ - path: getKubernetesDetailsUrl(params.detailName, ''), - deepLinkId: SecurityPageName.kubernetes, - }), - }, - ]; - } - - return breadcrumb; -}; diff --git a/x-pack/solutions/security/plugins/security_solution/public/kubernetes/pages/utils/data_view_spec_to_index_pattern.ts b/x-pack/solutions/security/plugins/security_solution/public/kubernetes/pages/utils/data_view_spec_to_index_pattern.ts deleted file mode 100644 index f4cb604ec3d8f..0000000000000 --- a/x-pack/solutions/security/plugins/security_solution/public/kubernetes/pages/utils/data_view_spec_to_index_pattern.ts +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import type { DataViewSpec } from '@kbn/data-plugin/common'; -import type { IndexPattern } from '@kbn/kubernetes-security-plugin/public/types'; - -export const dataViewSpecToIndexPattern = ( - dataViewSpec?: DataViewSpec -): IndexPattern | undefined => { - return dataViewSpec as IndexPattern | undefined; -}; diff --git a/x-pack/solutions/security/plugins/security_solution/public/kubernetes/routes.tsx b/x-pack/solutions/security/plugins/security_solution/public/kubernetes/routes.tsx deleted file mode 100644 index 7520de8cffa5a..0000000000000 --- a/x-pack/solutions/security/plugins/security_solution/public/kubernetes/routes.tsx +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React from 'react'; -import { TrackApplicationView } from '@kbn/usage-collection-plugin/public'; -import { allowedExperimentalValues } from '../../common'; -import { KubernetesContainer } from './pages'; - -import type { SecuritySubPluginRoutes } from '../app/types'; -import { SecurityPageName } from '../app/types'; -import { KUBERNETES_PATH } from '../../common/constants'; -import { PluginTemplateWrapper } from '../common/components/plugin_template_wrapper'; - -export const KubernetesRoutes = () => ( - - - - - -); - -export const routes: SecuritySubPluginRoutes = [ - { - path: allowedExperimentalValues.kubernetesEnabled ? KUBERNETES_PATH : [], - component: KubernetesRoutes, - }, -]; diff --git a/x-pack/solutions/security/plugins/security_solution/public/lazy_sub_plugins.tsx b/x-pack/solutions/security/plugins/security_solution/public/lazy_sub_plugins.tsx index a399f25fb8bda..9a3c0e9e6ebe1 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/lazy_sub_plugins.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/lazy_sub_plugins.tsx @@ -16,7 +16,6 @@ import { Cases } from './cases'; import { Detections } from './detections'; import { Exceptions } from './exceptions'; import { Explore } from './explore'; -import { Kubernetes } from './kubernetes'; import { Onboarding } from './onboarding'; import { Overview } from './overview'; import { Rules } from './rules'; @@ -42,7 +41,6 @@ const subPluginClasses = { Cases, Exceptions, Explore, - Kubernetes, Onboarding, Overview, Rules, diff --git a/x-pack/solutions/security/plugins/security_solution/public/management/pages/endpoint_hosts/view/details/components/insights/workflow_insights.tsx b/x-pack/solutions/security/plugins/security_solution/public/management/pages/endpoint_hosts/view/details/components/insights/workflow_insights.tsx index e0700eae6969c..09c9eee51d38f 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/management/pages/endpoint_hosts/view/details/components/insights/workflow_insights.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/management/pages/endpoint_hosts/view/details/components/insights/workflow_insights.tsx @@ -6,7 +6,6 @@ */ import { - EuiHorizontalRule, EuiAccordion, EuiSpacer, EuiText, @@ -114,6 +113,7 @@ export const WorkflowInsights = React.memo(({ endpointId }: WorkflowInsightsProp label={TECHNICAL_PREVIEW} tooltipContent={TECHNICAL_PREVIEW_TOOLTIP} size="s" + iconType={'beaker'} data-test-subj={'workflow-insights-tech-preview-badge'} />
@@ -134,7 +134,6 @@ export const WorkflowInsights = React.memo(({ endpointId }: WorkflowInsightsProp scanCompleted={scanCompleted && userTriggeredScan} endpointId={endpointId} /> - diff --git a/x-pack/solutions/security/plugins/security_solution/public/management/pages/endpoint_hosts/view/details/components/insights/workflow_insights_results.tsx b/x-pack/solutions/security/plugins/security_solution/public/management/pages/endpoint_hosts/view/details/components/insights/workflow_insights_results.tsx index 035e7e3936a88..783e04248a896 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/management/pages/endpoint_hosts/view/details/components/insights/workflow_insights_results.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/management/pages/endpoint_hosts/view/details/components/insights/workflow_insights_results.tsx @@ -17,6 +17,7 @@ import { EuiSpacer, EuiText, EuiToolTip, + EuiHorizontalRule, } from '@elastic/eui'; import { ENDPOINT_ARTIFACT_LISTS } from '@kbn/securitysolution-list-constants'; import { useUserPrivileges } from '../../../../../../../common/components/user_privileges'; @@ -169,17 +170,20 @@ export const WorkflowInsightsResults = ({ return null; }, [canWriteTrustedApplications, openArtifactCreationPage, results, showEmptyResultsCallout]); + const showInsights = !!(showEmptyResultsCallout || results?.length); + return ( <> - {showEmptyResultsCallout || results?.length ? ( + {showInsights && ( <>

{WORKFLOW_INSIGHTS.issues.title}

- ) : null} + )} {insights} + {showInsights && } ); }; diff --git a/x-pack/solutions/security/plugins/security_solution/public/management/pages/policy/models/advanced_policy_schema.ts b/x-pack/solutions/security/plugins/security_solution/public/management/pages/policy/models/advanced_policy_schema.ts index 51c032487e3f7..57eaf5ca1debf 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/management/pages/policy/models/advanced_policy_schema.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/management/pages/policy/models/advanced_policy_schema.ts @@ -94,6 +94,16 @@ export const AdvancedPolicySchema: AdvancedPolicySchemaType[] = [ } ), }, + { + key: 'linux.advanced.allow_cloud_features', + first_supported_version: '8.18', + documentation: i18n.translate( + 'xpack.securitySolution.endpoint.policy.advanced.linux.advanced.allow_cloud_features', + { + defaultMessage: `Advanced option to selectively choose which external services are allowed, valid keywords are "sample-collection,reputation-lookup,malware-lookup,artifacts-update,staged-artifacts-rollout". Everything is allowed by default, but if any comma separated value(s) are provided all other features are disabled. To disallow all a special keyword "none" can be used. The option imposes severe limitation on Defend functionality. It's meant only for telemetry extra-avoidant users users.`, + } + ), + }, { key: 'linux.advanced.elasticsearch.delay', first_supported_version: '7.9', @@ -320,6 +330,16 @@ export const AdvancedPolicySchema: AdvancedPolicySchemaType[] = [ } ), }, + { + key: 'mac.advanced.allow_cloud_features', + first_supported_version: '8.18', + documentation: i18n.translate( + 'xpack.securitySolution.endpoint.policy.advanced.mac.advanced.allow_cloud_features', + { + defaultMessage: `Advanced option to selectively choose which external services are allowed, valid keywords are "sample-collection,reputation-lookup,malware-lookup,artifacts-update,staged-artifacts-rollout". Everything is allowed by default, but if any comma separated value(s) are provided all other features are disabled. To disallow all a special keyword "none" can be used. The option imposes severe limitation on Defend functionality. It's meant only for telemetry extra-avoidant users users.`, + } + ), + }, { key: 'mac.advanced.elasticsearch.delay', first_supported_version: '7.9', @@ -556,6 +576,16 @@ export const AdvancedPolicySchema: AdvancedPolicySchemaType[] = [ } ), }, + { + key: 'windows.advanced.allow_cloud_features', + first_supported_version: '8.18', + documentation: i18n.translate( + 'xpack.securitySolution.endpoint.policy.advanced.windows.advanced.allow_cloud_features', + { + defaultMessage: `Advanced option to selectively choose which external services are allowed, valid keywords are "sample-collection,reputation-lookup,malware-lookup,artifacts-update,staged-artifacts-rollout". Everything is allowed by default, but if any comma separated value(s) are provided all other features are disabled. To disallow all a special keyword "none" can be used. The option imposes severe limitation on Defend functionality. It's meant only for telemetry extra-avoidant users users.`, + } + ), + }, { key: 'windows.advanced.elasticsearch.delay', first_supported_version: '7.9', @@ -2047,7 +2077,7 @@ export const AdvancedPolicySchema: AdvancedPolicySchemaType[] = [ 'xpack.securitySolution.endpoint.policy.advanced.windows.advanced.events.aggregate_process', { defaultMessage: - 'Reduce event volume by merging related process events into fewer aggregate events. Default is false.', + 'Reduce event volume by merging related process events into fewer aggregate events. Default is true.', } ), }, @@ -2058,7 +2088,7 @@ export const AdvancedPolicySchema: AdvancedPolicySchemaType[] = [ 'xpack.securitySolution.endpoint.policy.advanced.linux.advanced.events.aggregate_process', { defaultMessage: - 'Reduce event volume by merging related process events into fewer aggregate events. Default is false.', + 'Reduce event volume by merging related process events into fewer aggregate events. Default is true.', } ), }, @@ -2069,7 +2099,40 @@ export const AdvancedPolicySchema: AdvancedPolicySchemaType[] = [ 'xpack.securitySolution.endpoint.policy.advanced.mac.advanced.events.aggregate_process', { defaultMessage: - 'Reduce event volume by merging related process events into fewer aggregate events. Default is false.', + 'Reduce event volume by merging related process events into fewer aggregate events. Default is true.', + } + ), + }, + { + key: 'windows.advanced.events.aggregate_network', + first_supported_version: '8.18', + documentation: i18n.translate( + 'xpack.securitySolution.endpoint.policy.advanced.windows.advanced.events.aggregate_network', + { + defaultMessage: + 'Reduce event volume by merging related network events into fewer aggregate events. Default is true.', + } + ), + }, + { + key: 'linux.advanced.events.aggregate_network', + first_supported_version: '8.18', + documentation: i18n.translate( + 'xpack.securitySolution.endpoint.policy.advanced.linux.advanced.events.aggregate_network', + { + defaultMessage: + 'Reduce event volume by merging related network events into fewer aggregate events. Default is true.', + } + ), + }, + { + key: 'mac.advanced.events.aggregate_network', + first_supported_version: '8.18', + documentation: i18n.translate( + 'xpack.securitySolution.endpoint.policy.advanced.mac.advanced.events.aggregate_network', + { + defaultMessage: + 'Reduce event volume by merging related network events into fewer aggregate events. Default is true.', } ), }, @@ -2080,7 +2143,7 @@ export const AdvancedPolicySchema: AdvancedPolicySchemaType[] = [ 'xpack.securitySolution.endpoint.policy.advanced.windows.advanced.alerts.hash.md5', { defaultMessage: - 'Compute and include MD5 hashes in alerts? This will increase CPU usage and alert sizes. If any user exceptionlist, trustlist, or blocklists reference this hash type, Endpoint will ignore this setting and automatically enable this hash type. Default: true', + 'Compute and include MD5 hashes in alerts? This will increase CPU usage and alert sizes. If any user exceptionlist, trustlist, or blocklists reference this hash type, Endpoint will ignore this setting and automatically enable this hash type. Default: false', } ), }, @@ -2091,7 +2154,7 @@ export const AdvancedPolicySchema: AdvancedPolicySchemaType[] = [ 'xpack.securitySolution.endpoint.policy.advanced.windows.advanced.alerts.hash.sha1', { defaultMessage: - 'Compute and include SHA-1 hashes in alerts? This will increase CPU usage and alert sizes. If any user exceptionlist, trustlist, or blocklists reference this hash type, Endpoint will ignore this setting and automatically enable this hash type. Default: true', + 'Compute and include SHA-1 hashes in alerts? This will increase CPU usage and alert sizes. If any user exceptionlist, trustlist, or blocklists reference this hash type, Endpoint will ignore this setting and automatically enable this hash type. Default: false', } ), }, @@ -2102,7 +2165,7 @@ export const AdvancedPolicySchema: AdvancedPolicySchemaType[] = [ 'xpack.securitySolution.endpoint.policy.advanced.windows.advanced.events.hash.md5', { defaultMessage: - 'Compute and include MD5 hashes for processes and libraries in events? This will increase CPU usage and event sizes. Default: true', + 'Compute and include MD5 hashes for processes and libraries in events? This will increase CPU usage and event sizes. Default: false', } ), }, @@ -2113,7 +2176,7 @@ export const AdvancedPolicySchema: AdvancedPolicySchemaType[] = [ 'xpack.securitySolution.endpoint.policy.advanced.windows.advanced.events.hash.sha1', { defaultMessage: - 'Compute and include SHA-1 hashes for processes and libraries in events? This will increase CPU usage and event sizes. Default: true', + 'Compute and include SHA-1 hashes for processes and libraries in events? This will increase CPU usage and event sizes. Default: false', } ), }, @@ -2135,7 +2198,7 @@ export const AdvancedPolicySchema: AdvancedPolicySchemaType[] = [ 'xpack.securitySolution.endpoint.policy.advanced.linux.advanced.alerts.hash.md5', { defaultMessage: - 'Compute and include MD5 hashes in alerts? This will increase CPU usage and alert sizes. If any user exceptionlist, trustlist, or blocklists reference this hash type, Endpoint will ignore this setting and automatically enable this hash type. Default: true', + 'Compute and include MD5 hashes in alerts? This will increase CPU usage and alert sizes. If any user exceptionlist, trustlist, or blocklists reference this hash type, Endpoint will ignore this setting and automatically enable this hash type. Default: false', } ), }, @@ -2146,7 +2209,7 @@ export const AdvancedPolicySchema: AdvancedPolicySchemaType[] = [ 'xpack.securitySolution.endpoint.policy.advanced.linux.advanced.alerts.hash.sha1', { defaultMessage: - 'Compute and include SHA-1 hashes in alerts? This will increase CPU usage and alert sizes. If any user exceptionlist, trustlist, or blocklists reference this hash type, Endpoint will ignore this setting and automatically enable this hash type. Default: true', + 'Compute and include SHA-1 hashes in alerts? This will increase CPU usage and alert sizes. If any user exceptionlist, trustlist, or blocklists reference this hash type, Endpoint will ignore this setting and automatically enable this hash type. Default: false', } ), }, @@ -2157,7 +2220,7 @@ export const AdvancedPolicySchema: AdvancedPolicySchemaType[] = [ 'xpack.securitySolution.endpoint.policy.advanced.linux.advanced.events.hash.md5', { defaultMessage: - 'Compute and include MD5 hashes for processes and libraries in events? This will increase CPU usage and event sizes. Default: true', + 'Compute and include MD5 hashes for processes and libraries in events? This will increase CPU usage and event sizes. Default: false', } ), }, @@ -2168,7 +2231,7 @@ export const AdvancedPolicySchema: AdvancedPolicySchemaType[] = [ 'xpack.securitySolution.endpoint.policy.advanced.linux.advanced.events.hash.sha1', { defaultMessage: - 'Compute and include SHA-1 hashes for processes and libraries in events? This will increase CPU usage and event sizes. Default: true', + 'Compute and include SHA-1 hashes for processes and libraries in events? This will increase CPU usage and event sizes. Default: false', } ), }, @@ -2190,7 +2253,7 @@ export const AdvancedPolicySchema: AdvancedPolicySchemaType[] = [ 'xpack.securitySolution.endpoint.policy.advanced.mac.advanced.alerts.hash.md5', { defaultMessage: - 'Compute and include MD5 hashes in alerts? This will increase CPU usage and alert sizes. If any user exceptionlist, trustlist, or blocklists reference this hash type, Endpoint will ignore this setting and automatically enable this hash type. Default: true', + 'Compute and include MD5 hashes in alerts? This will increase CPU usage and alert sizes. If any user exceptionlist, trustlist, or blocklists reference this hash type, Endpoint will ignore this setting and automatically enable this hash type. Default: false', } ), }, @@ -2201,7 +2264,7 @@ export const AdvancedPolicySchema: AdvancedPolicySchemaType[] = [ 'xpack.securitySolution.endpoint.policy.advanced.mac.advanced.alerts.hash.sha1', { defaultMessage: - 'Compute and include SHA-1 hashes in alerts? This will increase CPU usage and alert sizes. If any user exceptionlist, trustlist, or blocklists reference this hash type, Endpoint will ignore this setting and automatically enable this hash type. Default: true', + 'Compute and include SHA-1 hashes in alerts? This will increase CPU usage and alert sizes. If any user exceptionlist, trustlist, or blocklists reference this hash type, Endpoint will ignore this setting and automatically enable this hash type. Default: false', } ), }, @@ -2212,7 +2275,7 @@ export const AdvancedPolicySchema: AdvancedPolicySchemaType[] = [ 'xpack.securitySolution.endpoint.policy.advanced.mac.advanced.events.hash.md5', { defaultMessage: - 'Compute and include MD5 hashes for processes and libraries in events? This will increase CPU usage and event sizes. Default: true', + 'Compute and include MD5 hashes for processes and libraries in events? This will increase CPU usage and event sizes. Default: false', } ), }, @@ -2223,7 +2286,7 @@ export const AdvancedPolicySchema: AdvancedPolicySchemaType[] = [ 'xpack.securitySolution.endpoint.policy.advanced.mac.advanced.events.hash.sha1', { defaultMessage: - 'Compute and include SHA-1 hashes for processes and libraries in events? This will increase CPU usage and event sizes. Default: true', + 'Compute and include SHA-1 hashes for processes and libraries in events? This will increase CPU usage and event sizes. Default: false', } ), }, @@ -2245,7 +2308,7 @@ export const AdvancedPolicySchema: AdvancedPolicySchemaType[] = [ 'xpack.securitySolution.endpoint.policy.advanced.windows.advanced.set_extended_host_information', { defaultMessage: - 'Include more details about hosts in events? Set to false to receive only id, name and os. Setting to true will increase event size. Default: true', + 'Include more details about hosts in events? Set to false to receive only id, name and os. Setting to true will increase event size. Default: false', } ), }, @@ -2256,7 +2319,7 @@ export const AdvancedPolicySchema: AdvancedPolicySchemaType[] = [ 'xpack.securitySolution.endpoint.policy.advanced.mac.advanced.set_extended_host_information', { defaultMessage: - 'Include more details about hosts in events? Set to false to receive only id, name and os. Setting to true will increase event size. Default: true', + 'Include more details about hosts in events? Set to false to receive only id, name and os. Setting to true will increase event size. Default: false', } ), }, @@ -2267,7 +2330,7 @@ export const AdvancedPolicySchema: AdvancedPolicySchemaType[] = [ 'xpack.securitySolution.endpoint.policy.advanced.linux.advanced.set_extended_host_information', { defaultMessage: - 'Include more details about hosts in events? Set to false to receive only id, name and os. Setting to true will increase event size. Default: true', + 'Include more details about hosts in events? Set to false to receive only id, name and os. Setting to true will increase event size. Default: false', } ), }, diff --git a/x-pack/solutions/security/plugins/security_solution/public/management/pages/policy/view/policy_settings_form/components/advanced_section.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/management/pages/policy/view/policy_settings_form/components/advanced_section.test.tsx index b86c79c46242d..96331492cc3c4 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/management/pages/policy/view/policy_settings_form/components/advanced_section.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/management/pages/policy/view/policy_settings_form/components/advanced_section.test.tsx @@ -24,7 +24,8 @@ jest.mock('../../../../../../common/hooks/use_license'); const useLicenseMock = _useLicense as jest.Mock; -describe('Policy Advanced Settings section', () => { +// Failing: See https://github.com/elastic/kibana/issues/205141 +describe.skip('Policy Advanced Settings section', () => { const testSubj = getPolicySettingsFormTestSubjects('test').advancedSection; let formProps: AdvancedSectionProps; diff --git a/x-pack/solutions/security/plugins/security_solution/public/management/pages/policy/view/policy_settings_form/components/event_merging_banner.tsx b/x-pack/solutions/security/plugins/security_solution/public/management/pages/policy/view/policy_settings_form/components/event_merging_banner.tsx index ec76a416e390d..432aea96b783e 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/management/pages/policy/view/policy_settings_form/components/event_merging_banner.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/management/pages/policy/view/policy_settings_form/components/event_merging_banner.tsx @@ -10,7 +10,11 @@ import { i18n } from '@kbn/i18n'; import { EuiCallOut, EuiLink, EuiText } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; import { useKibana } from '@kbn/kibana-react-plugin/public'; -import { ENDPOINT_VERSION_SUPPORTING_EVENT_MERGING_BY_DEFAULT } from '../constants'; + +/** + * The version from which we decrease event volume by default. + */ +export const ENDPOINT_VERSION_SUPPORTING_EVENT_MERGING_BY_DEFAULT = '8.18'; export interface EventMergingBannerProps { onDismiss: () => void; @@ -21,7 +25,7 @@ export const EventMergingBanner = memo(({ onDismiss }) const bannerTitle = i18n.translate( 'xpack.securitySolution.endpoint.policy.eventMergingBanner.title', { - defaultMessage: "We've recently changed Linux event collection", + defaultMessage: "We've recently changed event collection", } ); diff --git a/x-pack/solutions/security/plugins/security_solution/public/management/pages/policy/view/policy_settings_form/constants.ts b/x-pack/solutions/security/plugins/security_solution/public/management/pages/policy/view/policy_settings_form/constants.ts deleted file mode 100644 index 19f1e36163aad..0000000000000 --- a/x-pack/solutions/security/plugins/security_solution/public/management/pages/policy/view/policy_settings_form/constants.ts +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -/** - * Event merging banner is hidden temporarily for 8.16 (and serverless). - * Probably will be enabled for 8.17 or 8.18, when we can change the defaults and trigger policy deploy by migration. - * Blocker issue: https://github.com/elastic/kibana/issues/193352 - */ -export const ALLOW_SHOWING_EVENT_MERGING_BANNER = false; - -/** - * The version from which we decrease event volume by default. - */ -export const ENDPOINT_VERSION_SUPPORTING_EVENT_MERGING_BY_DEFAULT = '8.17'; diff --git a/x-pack/solutions/security/plugins/security_solution/public/management/pages/policy/view/policy_settings_form/policy_settings_form.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/management/pages/policy/view/policy_settings_form/policy_settings_form.test.tsx index 19a5ec8e6df39..428da56167810 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/management/pages/policy/view/policy_settings_form/policy_settings_form.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/management/pages/policy/view/policy_settings_form/policy_settings_form.test.tsx @@ -27,13 +27,6 @@ import type { IStorageWrapper } from '@kbn/kibana-utils-plugin/public'; jest.mock('../../../../../common/hooks/use_license'); -const mockAllowShowingEventMergingBannerConstantGetter = jest.fn(); -jest.mock('./constants', () => ({ - get ALLOW_SHOWING_EVENT_MERGING_BANNER() { - return mockAllowShowingEventMergingBannerConstantGetter(); - }, -})); - describe('Endpoint Policy Settings Form', () => { const testSubj = getPolicySettingsFormTestSubjects('test'); @@ -42,9 +35,10 @@ describe('Endpoint Policy Settings Form', () => { let renderResult: ReturnType; let upsellingService: UpsellingService; let storageMock: IStorageWrapper; + let mockedContext: AppContextTestRender; beforeEach(() => { - const mockedContext = createAppRootMockRenderer(); + mockedContext = createAppRootMockRenderer(); upsellingService = mockedContext.startServices.upselling; storageMock = mockedContext.startServices.storage; @@ -57,30 +51,30 @@ describe('Endpoint Policy Settings Form', () => { 'data-test-subj': 'test', }; - mockAllowShowingEventMergingBannerConstantGetter.mockReturnValue(false); + mockedContext.setExperimentalFlag({ eventCollectionDataReductionBannerEnabled: false }); render = () => (renderResult = mockedContext.render()); }); describe('event merging banner', () => { beforeEach(() => { - mockAllowShowingEventMergingBannerConstantGetter.mockReturnValue(true); + mockedContext.setExperimentalFlag({ eventCollectionDataReductionBannerEnabled: true }); }); it('should hide the banner if its not allowed to be displayed', () => { - mockAllowShowingEventMergingBannerConstantGetter.mockReturnValue(false); + mockedContext.setExperimentalFlag({ eventCollectionDataReductionBannerEnabled: false }); render(); expect(renderResult.queryByTestId('eventMergingCallout')).not.toBeInTheDocument(); }); - it('should show the event merging banner for 8.16 if it has never been dismissed', () => { + it('should show the event merging banner if it has never been dismissed', () => { render(); expect(renderResult.getByTestId('eventMergingCallout')).toBeInTheDocument(); }); - it('should show the event merging banner for 8.16 if `securitySolution.showEventMergingBanner` is `true`', () => { + it('should show the event merging banner if `securitySolution.showEventMergingBanner` is `true`', () => { storageMock.set('securitySolution.showEventMergingBanner', true); render(); diff --git a/x-pack/solutions/security/plugins/security_solution/public/management/pages/policy/view/policy_settings_form/policy_settings_form.tsx b/x-pack/solutions/security/plugins/security_solution/public/management/pages/policy/view/policy_settings_form/policy_settings_form.tsx index 619ba07346f47..2bd23be6d22ee 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/management/pages/policy/view/policy_settings_form/policy_settings_form.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/management/pages/policy/view/policy_settings_form/policy_settings_form.tsx @@ -9,6 +9,7 @@ import type { PropsWithChildren } from 'react'; import React, { memo, useState, useCallback } from 'react'; import { EuiSpacer, EuiText } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; +import { useEnableExperimental } from '../../../../../common/hooks/use_experimental_features'; import { useKibana } from '../../../../../common/lib/kibana'; import { updateAntivirusRegistrationEnabled } from '../../../../../../common/endpoint/utils/update_antivirus_registration_enabled'; import { useGetProtectionsUnavailableComponent } from './hooks/use_get_protections_unavailable_component'; @@ -26,7 +27,6 @@ import { MalwareProtectionsCard } from './components/cards/malware_protections_c import type { PolicyFormComponentCommonProps } from './types'; import { AdvancedSection } from './components/advanced_section'; import { useTestIdGenerator } from '../../../../hooks/use_test_id_generator'; -import { ALLOW_SHOWING_EVENT_MERGING_BANNER } from './constants'; const PROTECTIONS_SECTION_TITLE = i18n.translate( 'xpack.securitySolution.endpoint.policy.details.protections', @@ -45,8 +45,10 @@ export const PolicySettingsForm = memo((props) => { const ProtectionsUpSellingComponent = useGetProtectionsUnavailableComponent(); const { storage } = useKibana().services; + + const { eventCollectionDataReductionBannerEnabled } = useEnableExperimental(); const [showEventMergingBanner, setShowEventMergingBanner] = useState( - ALLOW_SHOWING_EVENT_MERGING_BANNER && + eventCollectionDataReductionBannerEnabled && (storage.get('securitySolution.showEventMergingBanner') ?? true) ); const onBannerDismiss = useCallback(() => { diff --git a/x-pack/solutions/security/plugins/security_solution/public/overview/components/detection_response/alerts_by_status/alerts_by_status.tsx b/x-pack/solutions/security/plugins/security_solution/public/overview/components/detection_response/alerts_by_status/alerts_by_status.tsx index 7f2dd03ad8079..b8df2ea6df517 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/overview/components/detection_response/alerts_by_status/alerts_by_status.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/overview/components/detection_response/alerts_by_status/alerts_by_status.tsx @@ -5,6 +5,7 @@ * 2.0. */ +import type { EuiThemeComputed } from '@elastic/eui'; import { EuiFlexGroup, EuiFlexItem, @@ -12,11 +13,11 @@ import { EuiProgress, EuiSpacer, EuiText, + useEuiTheme, useIsWithinMaxBreakpoint, useIsWithinMinBreakpoint, } from '@elastic/eui'; import React, { useCallback, useMemo } from 'react'; -import type { Severity } from '@kbn/securitysolution-io-ts-alerting-types'; import styled from 'styled-components'; import { ALERT_WORKFLOW_STATUS, ALERT_SEVERITY } from '@kbn/rule-data-utils'; @@ -49,12 +50,10 @@ import { } from '../translations'; import { useQueryToggle } from '../../../../common/containers/query_toggle'; import { VIEW_ALERTS } from '../../../pages/translations'; -import { SEVERITY_COLOR } from '../utils'; import { FormattedCount } from '../../../../common/components/formatted_number'; import { useUserPrivileges } from '../../../../common/components/user_privileges'; import { ChartLabel } from './chart_label'; import { Legend } from '../../../../common/components/charts/legend'; -import { emptyDonutColor } from '../../../../common/components/charts/donutchart_empty'; import { LastUpdatedAt } from '../../../../common/components/last_updated_at'; import { LinkButton, useGetSecuritySolutionLinkProps } from '../../../../common/components/links'; import { useNavigateToTimeline } from '../hooks/use_navigate_to_timeline'; @@ -66,6 +65,7 @@ import { SourcererScopeName } from '../../../../sourcerer/store/model'; import { VisualizationEmbeddable } from '../../../../common/components/visualization_actions/visualization_embeddable'; import type { Status } from '../../../../../common/api/detection_engine'; import { getAlertsByStatusAttributes } from '../../../../common/components/visualization_actions/lens_attributes/common/alerts/alerts_by_status_donut'; +import { getRiskSeverityColors } from '../../../../common/utils/risk_color_palette'; const StyledFlexItem = styled(EuiFlexItem)` padding: 0 4px; @@ -85,12 +85,20 @@ interface AlertsByStatusProps { signalIndexName: string | null; } -const chartConfigs: Array<{ key: Severity; label: string; color: string }> = [ - { key: 'critical', label: STATUS_CRITICAL_LABEL, color: SEVERITY_COLOR.critical }, - { key: 'high', label: STATUS_HIGH_LABEL, color: SEVERITY_COLOR.high }, - { key: 'medium', label: STATUS_MEDIUM_LABEL, color: SEVERITY_COLOR.medium }, - { key: 'low', label: STATUS_LOW_LABEL, color: SEVERITY_COLOR.low }, -]; +const getChartConfigs = (euiTheme: EuiThemeComputed) => { + const palette = getRiskSeverityColors(euiTheme); + + return [ + { key: 'critical', label: STATUS_CRITICAL_LABEL, color: palette.critical }, + { key: 'high', label: STATUS_HIGH_LABEL, color: palette.high }, + { key: 'medium', label: STATUS_MEDIUM_LABEL, color: palette.medium }, + { key: 'low', label: STATUS_LOW_LABEL, color: palette.low }, + ].map((config) => ({ + ...config, + field: ALERT_SEVERITY, + value: config.label, + })); +}; const eventKindSignalFilter: EntityFilter = { field: 'event.kind', @@ -107,6 +115,7 @@ export const AlertsByStatus = ({ signalIndexName, entityFilter, }: AlertsByStatusProps) => { + const { euiTheme } = useEuiTheme(); const { toggleStatus, setToggleStatus } = useQueryToggle(DETECTION_RESPONSE_ALERTS_BY_STATUS_ID); const { openTimelineWithFilters } = useNavigateToTimeline(); const navigateToAlerts = useNavigateToAlertsPageWithFilters(); @@ -154,15 +163,7 @@ export const AlertsByStatus = ({ to, from, }); - const legendItems: LegendItem[] = useMemo( - () => - chartConfigs.map((d) => ({ - color: d.color, - field: ALERT_SEVERITY, - value: d.label, - })), - [] - ); + const legendItems: LegendItem[] = useMemo(() => getChartConfigs(euiTheme), [euiTheme]); const navigateToAlertsWithStatus = useCallback( (status: Status, level?: string) => @@ -219,9 +220,11 @@ export const AlertsByStatus = ({ const totalAlertsCount = isDonutChartEmbeddablesEnabled ? visualizationTotalAlerts : totalAlerts; - const fillColor: FillColor = useCallback((dataName: string) => { - return chartConfigs.find((cfg) => cfg.label === dataName)?.color ?? emptyDonutColor; - }, []); + const fillColor: FillColor = useCallback( + (dataName: string) => + legendItems.find(({ value }) => value === dataName)?.color ?? euiTheme.colors.textSubdued, + [euiTheme.colors.textSubdued, legendItems] + ); return ( <> diff --git a/x-pack/solutions/security/plugins/security_solution/public/overview/components/detection_response/host_alerts_table/host_alerts_table.tsx b/x-pack/solutions/security/plugins/security_solution/public/overview/components/detection_response/host_alerts_table/host_alerts_table.tsx index 3d4070d4cd8e3..b4e3bf1072eb2 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/overview/components/detection_response/host_alerts_table/host_alerts_table.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/overview/components/detection_response/host_alerts_table/host_alerts_table.tsx @@ -30,7 +30,7 @@ import { HostDetailsLink } from '../../../../common/components/links'; import { useQueryToggle } from '../../../../common/containers/query_toggle'; import * as i18n from '../translations'; -import { ITEMS_PER_PAGE, SEVERITY_COLOR } from '../utils'; +import { ITEMS_PER_PAGE } from '../utils'; import type { HostAlertsItem } from './use_host_alerts_items'; import { useHostAlertsItems } from './use_host_alerts_items'; import { @@ -40,6 +40,7 @@ import { } from '../../../../common/components/cell_actions'; import { useGlobalFilterQuery } from '../../../../common/hooks/use_global_filter_query'; import { SourcererScopeName } from '../../../../sourcerer/store/model'; +import { useRiskSeverityColors } from '../../../../common/utils/risk_color_palette'; interface HostAlertsTableProps { signalIndexName: string | null; @@ -87,7 +88,7 @@ export const HostAlertsTable = React.memo(({ signalIndexName }: HostAlertsTableP filterQuery, }); - const columns = useMemo(() => getTableColumns(openHostInAlerts), [openHostInAlerts]); + const columns = useGetTableColumns(openHostInAlerts); return ( @@ -132,54 +133,29 @@ export const HostAlertsTable = React.memo(({ signalIndexName }: HostAlertsTableP HostAlertsTable.displayName = 'HostAlertsTable'; -const getTableColumns: GetTableColumns = (handleClick) => [ - { - field: 'hostName', - name: i18n.HOST_ALERTS_HOSTNAME_COLUMN, - 'data-test-subj': 'hostSeverityAlertsTable-hostName', - render: (hostName: string) => ( - - - - ), - }, - { - field: 'totalAlerts', - name: i18n.ALERTS_TEXT, - 'data-test-subj': 'hostSeverityAlertsTable-totalAlerts', - render: (totalAlerts: number, { hostName }) => ( - - handleClick({ hostName })} - > - - - - ), - }, - { - field: 'critical', - name: i18n.STATUS_CRITICAL_LABEL, - render: (count: number, { hostName }) => ( - - {count > 0 ? ( +const useGetTableColumns: GetTableColumns = (handleClick) => { + const severityColors = useRiskSeverityColors(); + return useMemo( + () => [ + { + field: 'hostName', + name: i18n.HOST_ALERTS_HOSTNAME_COLUMN, + 'data-test-subj': 'hostSeverityAlertsTable-hostName', + render: (hostName: string) => ( + + + + ), + }, + { + field: 'totalAlerts', + name: i18n.ALERTS_TEXT, + 'data-test-subj': 'hostSeverityAlertsTable-totalAlerts', + render: (totalAlerts: number, { hostName }) => ( [ triggerId={SecurityCellActionsTrigger.ALERTS_COUNT} sourcererScopeId={SourcererScopeName.detections} metadata={{ - andFilters: [ - { field: 'kibana.alert.severity', value: 'critical' }, - { field: 'kibana.alert.workflow_status', value: 'open' }, - ], + andFilters: [{ field: 'kibana.alert.workflow_status', value: 'open' }], }} > handleClick({ hostName, severity: 'critical' })} + data-test-subj="hostSeverityAlertsTable-totalAlertsLink" + disabled={totalAlerts === 0} + onClick={() => handleClick({ hostName })} > - + - ) : ( - - )} - - ), - }, - { - field: 'high', - name: i18n.STATUS_HIGH_LABEL, - render: (count: number, { hostName }) => ( - - {count > 0 ? ( - ( + - handleClick({ hostName, severity: 'high' })}> + {count > 0 ? ( + + handleClick({ hostName, severity: 'critical' })} + > + + + + ) : ( - - - ) : ( - - )} - - ), - }, - { - field: 'medium', - name: i18n.STATUS_MEDIUM_LABEL, - render: (count: number, { hostName }) => ( - - {count > 0 ? ( - - handleClick({ hostName, severity: 'medium' })}> + )} + + ), + }, + { + field: 'high', + name: i18n.STATUS_HIGH_LABEL, + render: (count: number, { hostName }) => ( + + {count > 0 ? ( + + handleClick({ hostName, severity: 'high' })}> + + + + ) : ( - - - ) : ( - - )} - - ), - }, - { - field: 'low', - name: i18n.STATUS_LOW_LABEL, - render: (count: number, { hostName }) => ( - - {count > 0 ? ( - - handleClick({ hostName, severity: 'low' })}> + )} + + ), + }, + { + field: 'medium', + name: i18n.STATUS_MEDIUM_LABEL, + render: (count: number, { hostName }) => ( + + {count > 0 ? ( + + handleClick({ hostName, severity: 'medium' })}> + + + + ) : ( - - - ) : ( - - )} - - ), - }, -]; + )} + + ), + }, + { + field: 'low', + name: i18n.STATUS_LOW_LABEL, + render: (count: number, { hostName }) => ( + + {count > 0 ? ( + + handleClick({ hostName, severity: 'low' })}> + + + + ) : ( + + )} + + ), + }, + ], + [ + handleClick, + severityColors.critical, + severityColors.high, + severityColors.low, + severityColors.medium, + ] + ); +}; diff --git a/x-pack/solutions/security/plugins/security_solution/public/overview/components/detection_response/rule_alerts_table/rule_alerts_table.tsx b/x-pack/solutions/security/plugins/security_solution/public/overview/components/detection_response/rule_alerts_table/rule_alerts_table.tsx index 6c88a6e903ed7..6938c389d4744 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/overview/components/detection_response/rule_alerts_table/rule_alerts_table.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/overview/components/detection_response/rule_alerts_table/rule_alerts_table.tsx @@ -25,7 +25,6 @@ import { SecurityCellActionsTrigger } from '../../../../app/actions/constants'; import { useNavigateToAlertsPageWithFilters } from '../../../../common/hooks/use_navigate_to_alerts_page_with_filters'; import { HeaderSection } from '../../../../common/components/header_section'; -import { SEVERITY_COLOR } from '../utils'; import * as i18n from '../translations'; import type { RuleAlertsItem } from './use_rule_alerts_items'; import { useRuleAlertsItems } from './use_rule_alerts_items'; @@ -40,6 +39,7 @@ import { FormattedCount } from '../../../../common/components/formatted_number'; import { SecurityCellActions, CellActionsMode } from '../../../../common/components/cell_actions'; import { useGlobalFilterQuery } from '../../../../common/hooks/use_global_filter_query'; import { SourcererScopeName } from '../../../../sourcerer/store/model'; +import { useRiskSeverityColors } from '../../../../common/utils/risk_color_palette'; export interface RuleAlertsTableProps { signalIndexName: string | null; @@ -54,82 +54,88 @@ export type GetTableColumns = (params: { const DETECTION_RESPONSE_RULE_ALERTS_QUERY_ID = 'detection-response-rule-alerts-severity-table' as const; -export const getTableColumns: GetTableColumns = ({ +export const useGetTableColumns: GetTableColumns = ({ getAppUrl, navigateTo, openRuleInAlertsPage, -}) => [ - { - field: 'name', - name: i18n.RULE_ALERTS_COLUMN_RULE_NAME, - render: (name: string, { id }) => { - const url = getAppUrl({ deepLinkId: SecurityPageName.rules, path: `id/${id}` }); - return ( - - {/* eslint-disable-next-line @elastic/eui/href-or-on-click */} - { - if (ev) { - ev.preventDefault(); - } - navigateTo({ url }); +}) => { + const severityColors = useRiskSeverityColors(); + return useMemo( + () => [ + { + field: 'name', + name: i18n.RULE_ALERTS_COLUMN_RULE_NAME, + render: (name: string, { id }) => { + const url = getAppUrl({ deepLinkId: SecurityPageName.rules, path: `id/${id}` }); + return ( + + {/* eslint-disable-next-line @elastic/eui/href-or-on-click */} + { + if (ev) { + ev.preventDefault(); + } + navigateTo({ url }); + }} + > + {name} + + + ); + }, + }, + { + field: 'last_alert_at', + name: i18n.RULE_ALERTS_COLUMN_LAST_ALERT, + 'data-test-subj': 'severityRuleAlertsTable-lastAlertAt', + render: (lastAlertAt: string) => , + }, + { + field: 'alert_count', + name: i18n.RULE_ALERTS_COLUMN_ALERT_COUNT, + 'data-test-subj': 'severityRuleAlertsTable-alertCount', + render: (alertCount: number, { name }) => ( + - {name} - - - ); - }, - }, - { - field: 'last_alert_at', - name: i18n.RULE_ALERTS_COLUMN_LAST_ALERT, - 'data-test-subj': 'severityRuleAlertsTable-lastAlertAt', - render: (lastAlertAt: string) => , - }, - { - field: 'alert_count', - name: i18n.RULE_ALERTS_COLUMN_ALERT_COUNT, - 'data-test-subj': 'severityRuleAlertsTable-alertCount', - render: (alertCount: number, { name }) => ( - - openRuleInAlertsPage(name)} - > - - - - ), - }, - { - field: 'severity', - name: i18n.RULE_ALERTS_COLUMN_SEVERITY, - 'data-test-subj': 'severityRuleAlertsTable-severity', - render: (severity: Severity) => ( - {capitalize(severity)} - ), - }, -]; + openRuleInAlertsPage(name)} + > + + + + ), + }, + { + field: 'severity', + name: i18n.RULE_ALERTS_COLUMN_SEVERITY, + 'data-test-subj': 'severityRuleAlertsTable-severity', + render: (severity: Severity) => ( + {capitalize(severity)} + ), + }, + ], + [getAppUrl, navigateTo, openRuleInAlertsPage, severityColors] + ); +}; export const RuleAlertsTable = React.memo(({ signalIndexName }) => { const { getAppUrl, navigateTo } = useNavigation(); @@ -163,10 +169,7 @@ export const RuleAlertsTable = React.memo(({ signalIndexNa }); }, [openAlertsPageWithFilter]); - const columns = useMemo( - () => getTableColumns({ getAppUrl, navigateTo, openRuleInAlertsPage }), - [getAppUrl, navigateTo, openRuleInAlertsPage] - ); + const columns = useGetTableColumns({ getAppUrl, navigateTo, openRuleInAlertsPage }); return ( diff --git a/x-pack/solutions/security/plugins/security_solution/public/overview/components/detection_response/user_alerts_table/user_alerts_table.tsx b/x-pack/solutions/security/plugins/security_solution/public/overview/components/detection_response/user_alerts_table/user_alerts_table.tsx index d2ec3efe63aa5..c4d4d0bd710e3 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/overview/components/detection_response/user_alerts_table/user_alerts_table.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/overview/components/detection_response/user_alerts_table/user_alerts_table.tsx @@ -30,12 +30,13 @@ import { LastUpdatedAt } from '../../../../common/components/last_updated_at'; import { UserDetailsLink } from '../../../../common/components/links'; import { useQueryToggle } from '../../../../common/containers/query_toggle'; import * as i18n from '../translations'; -import { ITEMS_PER_PAGE, SEVERITY_COLOR } from '../utils'; +import { ITEMS_PER_PAGE } from '../utils'; import type { UserAlertsItem } from './use_user_alerts_items'; import { useUserAlertsItems } from './use_user_alerts_items'; import { SecurityCellActions, CellActionsMode } from '../../../../common/components/cell_actions'; import { useGlobalFilterQuery } from '../../../../common/hooks/use_global_filter_query'; import { SourcererScopeName } from '../../../../sourcerer/store/model'; +import { useRiskSeverityColors } from '../../../../common/utils/risk_color_palette'; interface UserAlertsTableProps { signalIndexName: string | null; @@ -82,8 +83,7 @@ export const UserAlertsTable = React.memo(({ signalIndexName }: UserAlertsTableP signalIndexName, filterQuery, }); - - const columns = useMemo(() => getTableColumns(openUserInAlerts), [openUserInAlerts]); + const columns = useGetTableColumns(openUserInAlerts); return ( @@ -128,54 +128,29 @@ export const UserAlertsTable = React.memo(({ signalIndexName }: UserAlertsTableP UserAlertsTable.displayName = 'UserAlertsTable'; -const getTableColumns: GetTableColumns = (handleClick) => [ - { - field: 'userName', - name: i18n.USER_ALERTS_USERNAME_COLUMN, - 'data-test-subj': 'userSeverityAlertsTable-userName', - render: (userName: string) => ( - - - - ), - }, - { - field: 'totalAlerts', - name: i18n.ALERTS_TEXT, - 'data-test-subj': 'userSeverityAlertsTable-totalAlerts', - render: (totalAlerts: number, { userName }) => ( - - handleClick({ userName })} - > - - - - ), - }, - { - field: 'critical', - name: i18n.STATUS_CRITICAL_LABEL, - render: (count: number, { userName }) => ( - - {count > 0 ? ( +const useGetTableColumns: GetTableColumns = (handleClick) => { + const severityColors = useRiskSeverityColors(); + return useMemo( + () => [ + { + field: 'userName', + name: i18n.USER_ALERTS_USERNAME_COLUMN, + 'data-test-subj': 'userSeverityAlertsTable-userName', + render: (userName: string) => ( + + + + ), + }, + { + field: 'totalAlerts', + name: i18n.ALERTS_TEXT, + 'data-test-subj': 'userSeverityAlertsTable-totalAlerts', + render: (totalAlerts: number, { userName }) => ( [ triggerId={SecurityCellActionsTrigger.ALERTS_COUNT} sourcererScopeId={SourcererScopeName.detections} metadata={{ - andFilters: [ - { field: 'kibana.alert.severity', value: 'critical' }, - { field: 'kibana.alert.workflow_status', value: 'open' }, - ], + andFilters: [{ field: 'kibana.alert.workflow_status', value: 'open' }], }} > handleClick({ userName, severity: 'critical' })} + data-test-subj="userSeverityAlertsTable-totalAlertsLink" + disabled={totalAlerts === 0} + onClick={() => handleClick({ userName })} > - + - ) : ( - - )} - - ), - }, - { - field: 'high', - name: i18n.STATUS_HIGH_LABEL, - render: (count: number, { userName }) => ( - - {count > 0 ? ( - ( + - handleClick({ userName, severity: 'high' })}> + {count > 0 ? ( + + handleClick({ userName, severity: 'critical' })} + > + + + + ) : ( - - - ) : ( - - )} - - ), - }, - { - field: 'medium', - name: i18n.STATUS_MEDIUM_LABEL, - render: (count: number, { userName }) => ( - - {count > 0 ? ( - - handleClick({ userName, severity: 'medium' })}> + )} + + ), + }, + { + field: 'high', + name: i18n.STATUS_HIGH_LABEL, + render: (count: number, { userName }) => ( + + {count > 0 ? ( + + handleClick({ userName, severity: 'high' })}> + + + + ) : ( - - - ) : ( - - )} - - ), - }, - { - field: 'low', - name: i18n.STATUS_LOW_LABEL, - render: (count: number, { userName }) => ( - - {count > 0 ? ( - - handleClick({ userName, severity: 'low' })}> + )} + + ), + }, + { + field: 'medium', + name: i18n.STATUS_MEDIUM_LABEL, + render: (count: number, { userName }) => ( + + {count > 0 ? ( + + handleClick({ userName, severity: 'medium' })}> + + + + ) : ( - - - ) : ( - - )} - - ), - }, -]; + )} + + ), + }, + { + field: 'low', + name: i18n.STATUS_LOW_LABEL, + render: (count: number, { userName }) => ( + + {count > 0 ? ( + + handleClick({ userName, severity: 'low' })}> + + + + ) : ( + + )} + + ), + }, + ], + [handleClick, severityColors] + ); +}; diff --git a/x-pack/solutions/security/plugins/security_solution/public/overview/components/detection_response/utils.tsx b/x-pack/solutions/security/plugins/security_solution/public/overview/components/detection_response/utils.tsx index 61ed89aabf0f0..e272ca6530053 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/overview/components/detection_response/utils.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/overview/components/detection_response/utils.tsx @@ -4,7 +4,9 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -// @deprecated +/** + * @deprecated, use getRiskSeverityColors or useRiskSeverityColors from /common/utils/risk_color_palette.tsx instead + */ export const SEVERITY_COLOR = { critical: '#E7664C', high: '#DA8B45', diff --git a/x-pack/solutions/security/plugins/security_solution/public/plugin.tsx b/x-pack/solutions/security/plugins/security_solution/public/plugin.tsx index 7938456e3ddd2..43cc10392dafa 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/plugin.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/plugin.tsx @@ -296,7 +296,6 @@ export class Plugin implements IPlugin = React.memo( = React.memo( const { euiTheme } = useEuiTheme(); const isInstalled = !!ruleMigration.elastic_rule?.id; - const canEdit = !matchedPrebuiltRule && !isInstalled; - - const originalRuleQueryComponent = useMemo(() => { - return ( - - ); - }, [ruleMigration]); - - const translatedRuleQueryComponent = useMemo(() => { - let translatedQuery = ruleMigration.elastic_rule?.query ?? ''; - let translatedQueryLanguage = ruleMigration.elastic_rule?.query_language ?? ''; - if (matchedPrebuiltRule && matchedPrebuiltRule.type !== 'machine_learning') { - translatedQuery = matchedPrebuiltRule.query ?? ''; - translatedQueryLanguage = matchedPrebuiltRule.language; - } - return ( - - ); - }, [canEdit, matchedPrebuiltRule, onTranslationUpdate, ruleMigration]); return ( <> @@ -119,7 +87,9 @@ export const TranslationTab: React.FC = React.memo( - {originalRuleQueryComponent} + + + = React.memo( border-right: ${euiTheme.border.thin}; `} /> - {translatedRuleQueryComponent} + + + diff --git a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rule_details_flyout/tabs/translation/migration_rule_query.tsx b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rule_details_flyout/tabs/translation/migration_rule_query.tsx deleted file mode 100644 index 0aeb4042d1b86..0000000000000 --- a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rule_details_flyout/tabs/translation/migration_rule_query.tsx +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React, { useCallback, useMemo, useState } from 'react'; -import { - EuiButtonEmpty, - EuiCodeBlock, - EuiFlexGroup, - EuiFlexItem, - EuiHorizontalRule, - EuiSpacer, - EuiTitle, - useEuiTheme, -} from '@elastic/eui'; -import { css } from '@emotion/react'; -import { VALIDATION_WARNING_CODES } from '../../../../../../detection_engine/rule_creation/constants/validation_warning_codes'; -import { useFormWithWarnings } from '../../../../../../common/hooks/use_form_with_warnings'; -import { Field, Form, getUseField } from '../../../../../../shared_imports'; -import type { RuleTranslationSchema } from './types'; -import { schema } from './schema'; -import * as i18n from './translations'; -import { EsqlEditor } from './esql_editor'; - -const CommonUseField = getUseField({ component: Field }); - -interface MigrationRuleQueryProps { - title: string; - ruleName?: string; - query: string; - queryLanguage: string; - canEdit?: boolean; - onTranslationUpdate?: (ruleName: string, ruleQuery: string) => Promise; -} - -export const MigrationRuleQuery: React.FC = React.memo( - ({ title, ruleName, query, canEdit, queryLanguage, onTranslationUpdate }) => { - const { euiTheme } = useEuiTheme(); - - const formDefaultValue: RuleTranslationSchema = useMemo(() => { - return { - ruleName: ruleName ?? '', - queryBar: { - query: { - query, - language: 'esql', - }, - }, - }; - }, [query, ruleName]); - const { form } = useFormWithWarnings({ - defaultValue: formDefaultValue, - options: { stripEmptyFields: false, warningValidationCodes: VALIDATION_WARNING_CODES }, - schema, - }); - - const [editMode, setEditMode] = useState(false); - const onCancel = useCallback(() => setEditMode(false), []); - const onEdit = useCallback(() => { - form.reset({ defaultValue: formDefaultValue }); - setEditMode(true); - }, [form, formDefaultValue]); - const onSave = useCallback(async () => { - const { data, isValid } = await form.submit(); - if (isValid) { - await onTranslationUpdate?.(data.ruleName, data.queryBar.query.query); - setEditMode(false); - } - }, [form, onTranslationUpdate]); - - const codeBlockLanguage = useMemo(() => { - if (queryLanguage === 'spl') { - return 'splunk-spl'; - } - return 'sql'; - }, [queryLanguage]); - - const headerComponent = useMemo(() => { - return ( - - - -

{title}

-
-
-
- ); - }, [euiTheme, title]); - - const readQueryComponent = useMemo(() => { - if (editMode) { - return null; - } - return ( - <> - {canEdit ? ( - - - - {i18n.EDIT} - - - - ) : ( - - )} - -

{ruleName}

-
- - - {query} - - - ); - }, [editMode, canEdit, onEdit, ruleName, codeBlockLanguage, query]); - - const editQueryComponent = useMemo(() => { - if (!editMode) { - return null; - } - return ( -
- - - - {i18n.CANCEL} - - - - - {i18n.SAVE} - - - - - - - ); - }, [editMode, form, onCancel, onSave]); - - return ( - <> - {headerComponent} - - {readQueryComponent} - {editQueryComponent} - - ); - } -); -MigrationRuleQuery.displayName = 'MigrationRuleQuery'; diff --git a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rule_details_flyout/tabs/translation/esql_editor/esql_editor.tsx b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rule_details_flyout/tabs/translation/query_details/esql_editor/esql_editor.tsx similarity index 76% rename from x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rule_details_flyout/tabs/translation/esql_editor/esql_editor.tsx rename to x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rule_details_flyout/tabs/translation/query_details/esql_editor/esql_editor.tsx index c5184fdfba5de..57db3f9ddd800 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rule_details_flyout/tabs/translation/esql_editor/esql_editor.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rule_details_flyout/tabs/translation/query_details/esql_editor/esql_editor.tsx @@ -6,10 +6,10 @@ */ import React, { useMemo } from 'react'; -import type { FieldValueQueryBar } from '../../../../../../../detection_engine/rule_creation_ui/components/query_bar_field'; -import { UseField } from '../../../../../../../shared_imports'; +import type { FieldValueQueryBar } from '../../../../../../../../detection_engine/rule_creation_ui/components/query_bar_field'; +import { UseField } from '../../../../../../../../shared_imports'; import { EsqlEditorField } from './esql_editor_field'; -import type { RuleTranslationSchema } from '../types'; +import type { RuleTranslationSchema } from '../../types'; interface EsqlEditorFieldProps { path: string; diff --git a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rule_details_flyout/tabs/translation/esql_editor/esql_editor_field.tsx b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rule_details_flyout/tabs/translation/query_details/esql_editor/esql_editor_field.tsx similarity index 85% rename from x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rule_details_flyout/tabs/translation/esql_editor/esql_editor_field.tsx rename to x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rule_details_flyout/tabs/translation/query_details/esql_editor/esql_editor_field.tsx index 425b9b0d00406..5b92890c2dafd 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rule_details_flyout/tabs/translation/esql_editor/esql_editor_field.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rule_details_flyout/tabs/translation/query_details/esql_editor/esql_editor_field.tsx @@ -10,9 +10,9 @@ import deepEqual from 'fast-deep-equal'; import { EuiFormRow } from '@elastic/eui'; import { ESQLLangEditor } from '@kbn/esql/public'; import type { AggregateQuery } from '@kbn/es-query'; -import { convertToQueryType } from '../../../../../../../common/components/query_bar/convert_to_query_type'; -import type { FieldValueQueryBar } from '../../../../../../../detection_engine/rule_creation_ui/components/query_bar_field'; -import type { FieldHook } from '../../../../../../../shared_imports'; +import { convertToQueryType } from '../../../../../../../../common/components/query_bar/convert_to_query_type'; +import type { FieldValueQueryBar } from '../../../../../../../../detection_engine/rule_creation_ui/components/query_bar_field'; +import type { FieldHook } from '../../../../../../../../shared_imports'; interface EsqlEditorFieldProps { field: FieldHook; diff --git a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rule_details_flyout/tabs/translation/esql_editor/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rule_details_flyout/tabs/translation/query_details/esql_editor/index.tsx similarity index 100% rename from x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rule_details_flyout/tabs/translation/esql_editor/index.tsx rename to x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rule_details_flyout/tabs/translation/query_details/esql_editor/index.tsx diff --git a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rule_details_flyout/tabs/translation/query_details/header.tsx b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rule_details_flyout/tabs/translation/query_details/header.tsx new file mode 100644 index 0000000000000..2f50b3e89639a --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rule_details_flyout/tabs/translation/query_details/header.tsx @@ -0,0 +1,32 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { EuiFlexGroup, EuiFlexItem, EuiIcon, EuiTitle, EuiToolTip } from '@elastic/eui'; + +interface QueryHeaderProps { + title: string; + tooltip: string; +} + +export const QueryHeader: React.FC = React.memo(({ title, tooltip }) => { + return ( + + + +

{title}

+
+
+ + + + + +
+ ); +}); +QueryHeader.displayName = 'QueryHeader'; diff --git a/x-pack/solutions/security/plugins/kubernetes_security/common/types/latest.ts b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rule_details_flyout/tabs/translation/query_details/index.tsx similarity index 75% rename from x-pack/solutions/security/plugins/kubernetes_security/common/types/latest.ts rename to x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rule_details_flyout/tabs/translation/query_details/index.tsx index dce95e7328199..105df32d09c26 100644 --- a/x-pack/solutions/security/plugins/kubernetes_security/common/types/latest.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rule_details_flyout/tabs/translation/query_details/index.tsx @@ -4,4 +4,6 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -export * from './v1'; + +export * from './original_rule_query'; +export * from './translated_rule_query'; diff --git a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rule_details_flyout/tabs/translation/query_details/original_rule_query.tsx b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rule_details_flyout/tabs/translation/query_details/original_rule_query.tsx new file mode 100644 index 0000000000000..2c2b216712c6f --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rule_details_flyout/tabs/translation/query_details/original_rule_query.tsx @@ -0,0 +1,34 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { EuiHorizontalRule } from '@elastic/eui'; +import type { RuleMigration } from '../../../../../../../../common/siem_migrations/model/rule_migration.gen'; +import { QueryHeader } from './header'; +import { QueryViewer } from './query_viewer'; +import * as i18n from './translations'; + +interface OriginalRuleQueryProps { + ruleMigration: RuleMigration; +} + +export const OriginalRuleQuery: React.FC = React.memo( + ({ ruleMigration }) => { + return ( + <> + + + + + ); + } +); +OriginalRuleQuery.displayName = 'OriginalRuleQuery'; diff --git a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rule_details_flyout/tabs/translation/query_details/query_editor.tsx b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rule_details_flyout/tabs/translation/query_details/query_editor.tsx new file mode 100644 index 0000000000000..e518466fc3049 --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rule_details_flyout/tabs/translation/query_details/query_editor.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, { useCallback, useMemo } from 'react'; +import { EuiButtonEmpty, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; +import { VALIDATION_WARNING_CODES } from '../../../../../../../detection_engine/rule_creation/constants/validation_warning_codes'; +import { useFormWithWarnings } from '../../../../../../../common/hooks/use_form_with_warnings'; +import { Field, Form, getUseField } from '../../../../../../../shared_imports'; +import type { RuleTranslationSchema } from '../types'; +import { schema } from '../schema'; +import { EsqlEditor } from './esql_editor'; +import * as i18n from './translations'; + +const CommonUseField = getUseField({ component: Field }); + +interface QueryEditorProps { + query: string; + ruleName: string; + onSave: (ruleName: string, ruleQuery: string) => void; + onCancel: () => void; +} + +export const QueryEditor: React.FC = React.memo( + ({ query, ruleName, onSave, onCancel }) => { + const formDefaultValue: RuleTranslationSchema = useMemo(() => { + return { + ruleName, + queryBar: { + query: { + query, + language: 'esql', + }, + }, + }; + }, [query, ruleName]); + const { form } = useFormWithWarnings({ + defaultValue: formDefaultValue, + options: { stripEmptyFields: false, warningValidationCodes: VALIDATION_WARNING_CODES }, + schema, + }); + + const handleSaveButtonClick = useCallback(async () => { + const { data, isValid } = await form.submit(); + if (isValid) { + onSave(data.ruleName, data.queryBar.query.query); + } + }, [form, onSave]); + + return ( +
+ + + + {i18n.CANCEL} + + + + + {i18n.SAVE} + + + + + + + ); + } +); +QueryEditor.displayName = 'QueryEditor'; diff --git a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rule_details_flyout/tabs/translation/query_details/query_viewer.tsx b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rule_details_flyout/tabs/translation/query_details/query_viewer.tsx new file mode 100644 index 0000000000000..fc4005c3b38e1 --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rule_details_flyout/tabs/translation/query_details/query_viewer.tsx @@ -0,0 +1,72 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { useMemo } from 'react'; +import { + EuiButtonEmpty, + EuiCodeBlock, + EuiFlexGroup, + EuiFlexItem, + EuiSpacer, + EuiText, + EuiTitle, +} from '@elastic/eui'; +import * as i18n from './translations'; + +interface QueryViewerProps { + ruleName: string; + language: string; + query: string; + queryPlaceholder?: string; + onEdit?: () => void; +} + +export const QueryViewer: React.FC = React.memo( + ({ ruleName, language, query, queryPlaceholder, onEdit }) => { + const codeBlockLanguage = useMemo(() => { + if (language === 'spl') { + return 'splunk-spl'; + } + return 'sql'; + }, [language]); + + return ( + <> + {onEdit ? ( + + + + {i18n.EDIT} + + + + ) : ( + + )} + +

{ruleName}

+
+ + {query.length ? ( + + {query} + + ) : ( + + {queryPlaceholder} + + )} + + ); + } +); +QueryViewer.displayName = 'QueryViewer'; diff --git a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rule_details_flyout/tabs/translation/query_details/translated_rule_query.tsx b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rule_details_flyout/tabs/translation/query_details/translated_rule_query.tsx new file mode 100644 index 0000000000000..57bfdf97e2581 --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rule_details_flyout/tabs/translation/query_details/translated_rule_query.tsx @@ -0,0 +1,140 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { useCallback, useMemo, useState } from 'react'; +import { EuiHorizontalRule } from '@elastic/eui'; +import type { + QueryLanguage, + RuleResponse, +} from '../../../../../../../../common/api/detection_engine'; +import type { RuleMigration } from '../../../../../../../../common/siem_migrations/model/rule_migration.gen'; +import { VALIDATION_WARNING_CODES } from '../../../../../../../detection_engine/rule_creation/constants/validation_warning_codes'; +import { useFormWithWarnings } from '../../../../../../../common/hooks/use_form_with_warnings'; +import type { RuleTranslationSchema } from '../types'; +import { schema } from '../schema'; +import { QueryHeader } from './header'; +import { QueryEditor } from './query_editor'; +import { QueryViewer } from './query_viewer'; +import * as i18n from './translations'; + +const transformQueryLanguage = (language: QueryLanguage) => { + switch (language) { + case 'eql': + return 'EQL'; + case 'esql': + return 'ES|QL'; + case 'kuery': + return 'KQL'; + case 'lucene': + return 'Lucene'; + } +}; + +interface TranslatedRuleQueryProps { + ruleMigration: RuleMigration; + matchedPrebuiltRule?: RuleResponse; + onTranslationUpdate?: (ruleName: string, ruleQuery: string) => Promise; +} + +export const TranslatedRuleQuery: React.FC = React.memo( + ({ ruleMigration, matchedPrebuiltRule, onTranslationUpdate }) => { + const isInstalled = !!ruleMigration.elastic_rule?.id; + const canEdit = !matchedPrebuiltRule && !isInstalled; + + const ruleName = useMemo( + () => matchedPrebuiltRule?.name ?? ruleMigration.elastic_rule?.title ?? '', + [matchedPrebuiltRule?.name, ruleMigration.elastic_rule?.title] + ); + + const translatedData = useMemo(() => { + let title = i18n.TRANSLATION_QUERY_TITLE('ES|QL'); + let titleTooltip = i18n.TRANSLATION_QUERY_TOOLTIP; + let query = ruleMigration.elastic_rule?.query ?? ''; + let language = ruleMigration.elastic_rule?.query_language ?? ''; + let queryPlaceholder = i18n.TRANSLATION_QUERY_PLACEHOLDER; + if (matchedPrebuiltRule) { + if (matchedPrebuiltRule.type === 'machine_learning') { + title = i18n.MACHINE_LEARNING_RULE_TITLE; + titleTooltip = i18n.MACHINE_LEARNING_RULE_TOOLTIP; + queryPlaceholder = i18n.MACHINE_LEARNING_RULE_QUERY_PLACEHOLDER; + } else { + title = i18n.TRANSLATION_QUERY_TITLE( + transformQueryLanguage(matchedPrebuiltRule.language) + ); + query = matchedPrebuiltRule.query ?? ''; + language = matchedPrebuiltRule.language; + } + } + return { + title, + titleTooltip, + query, + language, + queryPlaceholder, + }; + }, [ + matchedPrebuiltRule, + ruleMigration.elastic_rule?.query, + ruleMigration.elastic_rule?.query_language, + ]); + + const formDefaultValue: RuleTranslationSchema = useMemo(() => { + return { + ruleName, + queryBar: { + query: { + query: translatedData.query, + language: 'esql', + }, + }, + }; + }, [ruleName, translatedData.query]); + const { form } = useFormWithWarnings({ + defaultValue: formDefaultValue, + options: { stripEmptyFields: false, warningValidationCodes: VALIDATION_WARNING_CODES }, + schema, + }); + + const [isEditing, setIsEditing] = useState(false); + const onCancel = useCallback(() => setIsEditing(false), []); + const onEdit = useCallback(() => { + form.reset({ defaultValue: formDefaultValue }); + setIsEditing(true); + }, [form, formDefaultValue]); + const onSave = useCallback( + async (newRuleName: string, newQuery: string) => { + await onTranslationUpdate?.(newRuleName, newQuery); + setIsEditing(false); + }, + [onTranslationUpdate] + ); + + return ( + <> + + + {isEditing ? ( + + ) : ( + + )} + + ); + } +); +TranslatedRuleQuery.displayName = 'TranslatedRuleQuery'; diff --git a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rule_details_flyout/tabs/translation/query_details/translations.ts b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rule_details_flyout/tabs/translation/query_details/translations.ts new file mode 100644 index 0000000000000..e284a1935e186 --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rule_details_flyout/tabs/translation/query_details/translations.ts @@ -0,0 +1,90 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { i18n } from '@kbn/i18n'; + +export const SPLUNK_QUERY_TITLE = i18n.translate( + 'xpack.securitySolution.siemMigrations.rules.translationDetails.translationTab.splunkQuery.title', + { + defaultMessage: 'Splunk query', + } +); + +export const SPLUNK_QUERY_TOOLTIP = i18n.translate( + 'xpack.securitySolution.siemMigrations.rules.translationDetails.translationTab.splunkQuery.tooltip', + { + defaultMessage: 'This is the rule name detected in the export file uploaded for translation', + } +); + +export const TRANSLATION_QUERY_TITLE = (queryLanguage: string) => { + return i18n.translate( + 'xpack.securitySolution.siemMigrations.rules.translationDetails.translationTab.translationQuery.title', + { + defaultMessage: '{queryLanguage} query', + values: { queryLanguage }, + } + ); +}; + +export const TRANSLATION_QUERY_PLACEHOLDER = i18n.translate( + 'xpack.securitySolution.siemMigrations.rules.translationDetails.translationTab.translationQuery.queryPlaceholder', + { + defaultMessage: 'This rule has not been translated. Click edit to start writing.', + } +); + +export const TRANSLATION_QUERY_TOOLTIP = i18n.translate( + 'xpack.securitySolution.siemMigrations.rules.translationDetails.translationTab.machineLearningRule.tooltip', + { + defaultMessage: + 'Elastic prebuilt rules use EQL, ES|QL, KQL or Lucene. AI-translated rules use ES|QL.', + } +); + +export const MACHINE_LEARNING_RULE_TITLE = i18n.translate( + 'xpack.securitySolution.siemMigrations.rules.translationDetails.translationTab.machineLearningRule.title', + { + defaultMessage: 'Machine learning rule', + } +); + +export const MACHINE_LEARNING_RULE_QUERY_PLACEHOLDER = i18n.translate( + 'xpack.securitySolution.siemMigrations.rules.translationDetails.translationTab.machineLearningRule.queryPlaceholder', + { + defaultMessage: + 'This query was mapped to a Machine Learning rule. See more details in the Overview tab above.', + } +); + +export const MACHINE_LEARNING_RULE_TOOLTIP = i18n.translate( + 'xpack.securitySolution.siemMigrations.rules.translationDetails.translationTab.machineLearningRule.tooltip', + { + defaultMessage: 'Machine learning rules may require additional configuration.', + } +); + +export const EDIT = i18n.translate( + 'xpack.securitySolution.siemMigrations.rules.translationDetails.translationTab.editButtonLabel', + { + defaultMessage: 'Edit', + } +); + +export const SAVE = i18n.translate( + 'xpack.securitySolution.siemMigrations.rules.translationDetails.translationTab.saveButtonLabel', + { + defaultMessage: 'Save', + } +); + +export const CANCEL = i18n.translate( + 'xpack.securitySolution.siemMigrations.rules.translationDetails.translationTab.cancelButtonLabel', + { + defaultMessage: 'Cancel', + } +); diff --git a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rule_details_flyout/tabs/translation/translations.ts b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rule_details_flyout/tabs/translation/translations.ts index 1978a2ded474b..72adf960b2bce 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rule_details_flyout/tabs/translation/translations.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rule_details_flyout/tabs/translation/translations.ts @@ -28,27 +28,6 @@ export const NAME_REQUIRED_ERROR_MESSAGE = i18n.translate( } ); -export const SPLUNK_QUERY_TITLE = i18n.translate( - 'xpack.securitySolution.siemMigrations.rules.translationDetails.translationTab.splunkQueryTitle', - { - defaultMessage: 'Splunk query', - } -); - -export const ESQL_TRANSLATION_TITLE = i18n.translate( - 'xpack.securitySolution.siemMigrations.rules.translationDetails.translationTab.esqlTranslationTitle', - { - defaultMessage: 'ES|QL translation', - } -); - -export const TRANSLATED_QUERY_AREAL_LABEL = i18n.translate( - 'xpack.securitySolution.siemMigrations.rules.translationDetails.translationTab.queryArealLabel', - { - defaultMessage: 'Translated query', - } -); - export const INSTALLED_LABEL = i18n.translate( 'xpack.securitySolution.siemMigrations.rules.translationDetails.translationTab.installedLabel', { @@ -56,27 +35,6 @@ export const INSTALLED_LABEL = i18n.translate( } ); -export const EDIT = i18n.translate( - 'xpack.securitySolution.siemMigrations.rules.translationDetails.translationTab.editButtonLabel', - { - defaultMessage: 'Edit', - } -); - -export const SAVE = i18n.translate( - 'xpack.securitySolution.siemMigrations.rules.translationDetails.translationTab.saveButtonLabel', - { - defaultMessage: 'Save', - } -); - -export const CANCEL = i18n.translate( - 'xpack.securitySolution.siemMigrations.rules.translationDetails.translationTab.cancelButtonLabel', - { - defaultMessage: 'Cancel', - } -); - export const CALLOUT_TRANSLATED_RULE_TITLE = i18n.translate( 'xpack.securitySolution.siemMigrations.rules.translationDetails.translationTab.translatedRuleCalloutTitle', { diff --git a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rules_table/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rules_table/index.tsx index 30c2a8e0b538a..4db6ebcbb72af 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rules_table/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rules_table/index.tsx @@ -41,6 +41,7 @@ import { useStartMigration } from '../../service/hooks/use_start_migration'; import type { FilterOptions } from '../../types'; import { MigrationRulesFilter } from './filters'; import { convertFilterOptions } from './utils/filters'; +import { SiemTranslatedRulesTour } from '../tours/translation_guide'; const DEFAULT_PAGE_SIZE = 10; const DEFAULT_SORT_FIELD = 'translation_result'; @@ -299,6 +300,8 @@ export const MigrationRulesTable: React.FC = React.mem return ( <> + {!isStatsLoading && translationStats?.rules.total && } + = React.memo(({ title, tooltipContent }) => { - return ( - - <> - {title} -   - - - - ); -}); +export const TableHeader: React.FC = React.memo( + ({ id, title, tooltipContent }) => { + return ( + +
+ {title} +   + +
+
+ ); + } +); TableHeader.displayName = 'TableHeader'; diff --git a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rules_table_columns/status.tsx b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rules_table_columns/status.tsx index 0a8d78f3aa812..f4add69f11e5c 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rules_table_columns/status.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/rules_table_columns/status.tsx @@ -16,11 +16,14 @@ import { StatusBadge } from '../status_badge'; import { TableHeader } from './header'; import { convertTranslationResultIntoText } from '../../utils/translation_results'; +export const SIEM_MIGRATIONS_STATUS_HEADER_ID = 'siemMigrationsStatusHeader'; + export const createStatusColumn = (): TableColumn => { return { field: 'translation_result', name: ( { + const { siemMigrations, storage } = useKibana().services; + + const stepsCount = Object.keys(tourSteps).length; + const selectMigrationStepData = tourSteps[TourSteps.MIGRATION_SELECTION]; + const statusHeaderStepData = tourSteps[TourSteps.MIGRATION_RULE_STATUS]; + const getStartedStepData = tourSteps[TourSteps.MIGRATION_ONBOARDING_HUB]; + + const isSelectMigrationAnchorMounted = useIsElementMounted(selectMigrationStepData.anchorId); + const isStatusHeaderAnchorMounted = useIsElementMounted(statusHeaderStepData.anchorId); + const isGetStartedNavigationAnchorMounted = useIsElementMounted(getStartedStepData.anchorId); + + const [tourState, setTourState] = useState(() => { + const restoredTourState = storage.get( + NEW_FEATURES_TOUR_STORAGE_KEYS.SIEM_RULE_TRANSLATION_PAGE + ); + if (restoredTourState != null) { + return restoredTourState; + } + return tourConfig; + }); + + const onTourFinished = useCallback(() => { + setTourState({ + ...tourState, + isTourActive: false, + }); + }, [tourState]); + + const onTourNext = useCallback(() => { + setTourState({ + ...tourState, + currentTourStep: tourState.currentTourStep + 1, + }); + }, [tourState]); + + useEffect(() => { + storage.set(NEW_FEATURES_TOUR_STORAGE_KEYS.SIEM_RULE_TRANSLATION_PAGE, tourState); + }, [tourState, storage]); + + const isTourActive = useMemo(() => { + return siemMigrations.rules.isAvailable() && tourState.isTourActive; + }, [siemMigrations.rules, tourState]); + + return ( + <> + {isSelectMigrationAnchorMounted && ( + + {i18n.NEXT_TOUR_STEP_BUTTON} + + } + /> + )} + {isStatusHeaderAnchorMounted && ( + + {i18n.NEXT_TOUR_STEP_BUTTON} + + } + /> + )} + {isGetStartedNavigationAnchorMounted && ( + + {i18n.FINISH_TOUR_BUTTON} + + } + /> + )} + + ); +}); +SiemTranslatedRulesTour.displayName = 'SiemTranslatedRulesTour'; diff --git a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/tours/translation_guide/step_config.tsx b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/tours/translation_guide/step_config.tsx new file mode 100644 index 0000000000000..ff4e4505cef4e --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/tours/translation_guide/step_config.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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { FormattedMessage } from '@kbn/i18n-react'; +import type { PopoverAnchorPosition } from '@elastic/eui'; +import { DocLink } from '../../../../../common/components/links_to_docs/doc_link'; +import { SecurityPageName } from '../../../../../../common/constants'; +import { SIEM_MIGRATIONS_SELECT_MIGRATION_BUTTON_ID } from '../../header_buttons'; +import { SIEM_MIGRATIONS_STATUS_HEADER_ID } from '../../rules_table_columns'; +import * as i18n from './translations'; + +export const SECURITY_GET_STARTED_BUTTON_ANCHOR = `solutionSideNavCustomIconItem-${SecurityPageName.landing}`; + +export enum TourSteps { + MIGRATION_SELECTION, + MIGRATION_RULE_STATUS, + MIGRATION_ONBOARDING_HUB, +} + +export const tourSteps: { + [key in TourSteps]: { + step: number; + title: string; + content: React.ReactNode; + anchorId: string; + anchorPosition: PopoverAnchorPosition; + }; +} = { + [TourSteps.MIGRATION_SELECTION]: { + step: 1, + title: i18n.MIGRATION_RULES_SELECTOR_TOUR_STEP_TITLE, + content: i18n.MIGRATION_RULES_SELECTOR_TOUR_STEP_CONTENT, + anchorId: SIEM_MIGRATIONS_SELECT_MIGRATION_BUTTON_ID, + anchorPosition: 'downCenter', + }, + [TourSteps.MIGRATION_RULE_STATUS]: { + step: 2, + title: i18n.TRANSLATION_STATUS_TOUR_STEP_TITLE, + content: ( + , + install: {i18n.INSTALL_LABEL}, + installed: {i18n.INSTALLED_LABEL}, + view: {i18n.VIEW_LABEL}, + edit: {i18n.EDIT_LABEL}, + translated: {i18n.TRANSLATED_LABEL}, + reprocessed: {i18n.REPROCESSED_LABEL}, + // TODO: Update doc path once available + link: , + }} + /> + ), + anchorId: SIEM_MIGRATIONS_STATUS_HEADER_ID, + anchorPosition: 'rightCenter', + }, + [TourSteps.MIGRATION_ONBOARDING_HUB]: { + step: 3, + title: i18n.MIGRATION_GUIDE_TOUR_STEP_TITLE, + content: i18n.MIGRATION_GUIDE_TOUR_STEP_CONTENT, + anchorId: SECURITY_GET_STARTED_BUTTON_ANCHOR, + anchorPosition: 'rightCenter', + }, +}; + +export const tourConfig = { + currentTourStep: tourSteps[TourSteps.MIGRATION_SELECTION].step, + isTourActive: true, + tourPopoverWidth: 360, +}; diff --git a/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/tours/translation_guide/translations.ts b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/tours/translation_guide/translations.ts new file mode 100644 index 0000000000000..3ab5a3d3083fb --- /dev/null +++ b/x-pack/solutions/security/plugins/security_solution/public/siem_migrations/rules/components/tours/translation_guide/translations.ts @@ -0,0 +1,108 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { i18n } from '@kbn/i18n'; + +export const MIGRATION_RULES_SELECTOR_TOUR_STEP_TITLE = i18n.translate( + 'xpack.securitySolution.siemMigrations.rules.tour.translationRuleGuide.title', + { + defaultMessage: 'Translated rules in one place', + } +); + +export const MIGRATION_RULES_SELECTOR_TOUR_STEP_CONTENT = i18n.translate( + 'xpack.securitySolution.siemMigrations.rules.tour.translationRuleGuide.content', + { + defaultMessage: + 'Each migration’s translated rules appear on its SIEM rule translations page. Switch between your migrations using this dropdown. Start a new migration by clicking “Upload more rules for translation”.', + } +); + +export const TRANSLATION_STATUS_TOUR_STEP_TITLE = i18n.translate( + 'xpack.securitySolution.siemMigrations.rules.tour.translationRuleGuide.statusStepTitle', + { + defaultMessage: 'Translation status', + } +); + +export const MIGRATION_GUIDE_TOUR_STEP_TITLE = i18n.translate( + 'xpack.securitySolution.siemMigrations.rules.tour.translationRuleGuide.migrationGuideStepTitle', + { + defaultMessage: 'SIEM Rule Migration guide', + } +); + +export const MIGRATION_GUIDE_TOUR_STEP_CONTENT = i18n.translate( + 'xpack.securitySolution.siemMigrations.rules.tour.translationRuleGuide.migrationGuideStepContent', + { + defaultMessage: + 'Your guide and migrated rules can always be found in the Onboarding Hub. Use it to review previous rule migrations or start a new one.', + } +); + +export const NEXT_TOUR_STEP_BUTTON = i18n.translate( + 'xpack.securitySolution.siemMigrations.rules.tour.translationRuleGuide.nextStepButton', + { + defaultMessage: 'Next', + } +); + +export const FINISH_TOUR_BUTTON = i18n.translate( + 'xpack.securitySolution.siemMigrations.rules.tour.translationRuleGuide.finishButton', + { + defaultMessage: 'OK', + } +); + +export const INSTALL_LABEL = i18n.translate( + 'xpack.securitySolution.siemMigrations.rules.tour.translationRuleGuide.installLabel', + { + defaultMessage: 'Install', + } +); + +export const INSTALLED_LABEL = i18n.translate( + 'xpack.securitySolution.siemMigrations.rules.tour.translationRuleGuide.installedLabel', + { + defaultMessage: 'Installed', + } +); + +export const VIEW_LABEL = i18n.translate( + 'xpack.securitySolution.siemMigrations.rules.tour.translationRuleGuide.viewLabel', + { + defaultMessage: 'View', + } +); + +export const EDIT_LABEL = i18n.translate( + 'xpack.securitySolution.siemMigrations.rules.tour.translationRuleGuide.editLabel', + { + defaultMessage: 'Edit', + } +); + +export const TRANSLATED_LABEL = i18n.translate( + 'xpack.securitySolution.siemMigrations.rules.tour.translationRuleGuide.translatedLabel', + { + defaultMessage: 'Translated', + } +); + +export const REPROCESSED_LABEL = i18n.translate( + 'xpack.securitySolution.siemMigrations.rules.tour.translationRuleGuide.reprocessedLabel', + { + defaultMessage: 'Reprocessed', + } +); + +export const SIEM_MIGRATIONS_LINK_LABEL = i18n.translate( + 'xpack.securitySolution.siemMigrations.rules.tour.translationRuleGuide.siemMigrationsLinkLabel', + { + defaultMessage: 'AI Translations here', + } +); diff --git a/x-pack/solutions/security/plugins/security_solution/public/types.ts b/x-pack/solutions/security/plugins/security_solution/public/types.ts index 896f928b4d4ac..31b7aae183c2b 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/types.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/types.ts @@ -30,7 +30,6 @@ import type { CasesPublicStart, CasesPublicSetup } from '@kbn/cases-plugin/publi import type { SecurityPluginSetup, SecurityPluginStart } from '@kbn/security-plugin/public'; import type { TimelinesUIStart } from '@kbn/timelines-plugin/public'; import type { SessionViewStart } from '@kbn/session-view-plugin/public'; -import type { KubernetesSecurityStart } from '@kbn/kubernetes-security-plugin/public'; import type { MlPluginSetup, MlPluginStart } from '@kbn/ml-plugin/public'; import type { OsqueryPluginStart } from '@kbn/osquery-plugin/public'; import type { LicensingPluginStart, LicensingPluginSetup } from '@kbn/licensing-plugin/public'; @@ -68,7 +67,6 @@ import type { Inspect } from '../common/search_strategy'; import type { Detections } from './detections'; import type { Cases } from './cases'; import type { Exceptions } from './exceptions'; -import type { Kubernetes } from './kubernetes'; import type { Onboarding } from './onboarding'; import type { Overview } from './overview'; import type { Rules } from './rules'; @@ -131,7 +129,6 @@ export interface StartPlugins { inspector: InspectorStart; fleet?: FleetStart; guidedOnboarding?: GuidedOnboardingPluginStart; - kubernetesSecurity: KubernetesSecurityStart; lens: LensPublicStart; lists?: ListsPluginStart; licensing: LicensingPluginStart; @@ -242,7 +239,6 @@ export interface SubPlugins { dashboards: Dashboards; exceptions: Exceptions; explore: Explore; - kubernetes: Kubernetes; management: Management; onboarding: Onboarding; overview: Overview; @@ -267,7 +263,6 @@ export interface StartedSubPlugins { dashboards: ReturnType; exceptions: ReturnType; explore: ReturnType; - kubernetes: ReturnType; management: ReturnType; onboarding: ReturnType; overview: ReturnType; diff --git a/x-pack/solutions/security/plugins/security_solution/scripts/endpoint/common/roles_users/serverless/es_serverless_resources/roles.yml b/x-pack/solutions/security/plugins/security_solution/scripts/endpoint/common/roles_users/serverless/es_serverless_resources/roles.yml index 467a180d289a3..f51004e521bf4 100644 --- a/x-pack/solutions/security/plugins/security_solution/scripts/endpoint/common/roles_users/serverless/es_serverless_resources/roles.yml +++ b/x-pack/solutions/security/plugins/security_solution/scripts/endpoint/common/roles_users/serverless/es_serverless_resources/roles.yml @@ -152,6 +152,7 @@ editor: - feature_securitySolutionTimeline.all - feature_securitySolutionNotes.all - feature_actions.read + - feature_actions.endpoint_security_execute - feature_builtInAlerts.all - feature_osquery.all - feature_discover.all @@ -336,6 +337,7 @@ t3_analyst: - feature_securitySolutionTimeline.all - feature_securitySolutionNotes.all - feature_actions.read + - feature_actions.endpoint_security_execute - feature_builtInAlerts.all - feature_osquery.all - feature_discover.all @@ -545,6 +547,7 @@ soc_manager: - feature_securitySolutionTimeline.all - feature_securitySolutionNotes.all - feature_actions.all + - feature_actions.endpoint_security_execute - feature_builtInAlerts.all - feature_osquery.all - feature_indexPatterns.all @@ -748,6 +751,7 @@ endpoint_operations_analyst: - feature_securitySolutionTimeline.all - feature_securitySolutionNotes.all - feature_actions.all + - feature_actions.endpoint_security_execute - feature_builtInAlerts.all - feature_osquery.all - feature_fleet.all diff --git a/x-pack/solutions/security/plugins/security_solution/server/assistant/tools/esql/nl_to_esql_tool.ts b/x-pack/solutions/security/plugins/security_solution/server/assistant/tools/esql/nl_to_esql_tool.ts index 11ca8ffd94edd..20affb2abf664 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/assistant/tools/esql/nl_to_esql_tool.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/assistant/tools/esql/nl_to_esql_tool.ts @@ -48,7 +48,7 @@ export const NL_TO_ESQL_TOOL: AssistantTool = { client: inference.getClient({ request }), connectorId, input: question, - ...(isOssModel ? { functionCalling: 'simulated' } : {}), + functionCalling: 'auto', logger, }) ); diff --git a/x-pack/solutions/security/plugins/security_solution/server/assistant/tools/product_docs/product_documentation_tool.test.ts b/x-pack/solutions/security/plugins/security_solution/server/assistant/tools/product_docs/product_documentation_tool.test.ts index d8d7e5995c92e..737e82d3837d2 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/assistant/tools/product_docs/product_documentation_tool.test.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/assistant/tools/product_docs/product_documentation_tool.test.ts @@ -86,7 +86,7 @@ describe('ProductDocumentationTool', () => { max: 3, connectorId: 'fake-connector', request, - functionCalling: 'native', + functionCalling: 'auto', }); }); }); diff --git a/x-pack/solutions/security/plugins/security_solution/server/assistant/tools/product_docs/product_documentation_tool.ts b/x-pack/solutions/security/plugins/security_solution/server/assistant/tools/product_docs/product_documentation_tool.ts index 071a435e1311f..9f3dd1c05ce1c 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/assistant/tools/product_docs/product_documentation_tool.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/assistant/tools/product_docs/product_documentation_tool.ts @@ -62,8 +62,7 @@ export const PRODUCT_DOCUMENTATION_TOOL: AssistantTool = { max: 3, connectorId, request, - // o11y specific parameter, hardcode to native as we do not utilize the other value (simulated) - functionCalling: 'native', + functionCalling: 'auto', }); return { diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_monitoring/logic/rule_execution_log/client_for_executors/client.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_monitoring/logic/rule_execution_log/client_for_executors/client.ts index 51e8f479bbc1f..32f61c2836ecb 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_monitoring/logic/rule_execution_log/client_for_executors/client.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_monitoring/logic/rule_execution_log/client_for_executors/client.ts @@ -174,6 +174,7 @@ export const createRuleExecutionLogClientForExecutors = ( total_search_duration_ms: totalSearchDurationMs, total_indexing_duration_ms: totalIndexingDurationMs, execution_gap_duration_s: executionGapDurationS, + gap_range: gapRange, } = metrics ?? {}; if (totalSearchDurationMs) { @@ -188,6 +189,10 @@ export const createRuleExecutionLogClientForExecutors = ( ruleMonitoringService.setLastRunMetricsGapDurationS(executionGapDurationS); } + if (gapRange) { + ruleMonitoringService.setLastRunMetricsGapRange(gapRange); + } + if (newStatus === RuleExecutionStatusEnum.failed) { ruleResultService.addLastRunError(message, userError ?? false); } else if (newStatus === RuleExecutionStatusEnum['partial failure']) { @@ -254,6 +259,7 @@ const normalizeStatusChangeArgs = (args: StatusChangeArgs): NormalizedStatusChan total_indexing_duration_ms: normalizeDurations(metrics.indexingDurations), total_enrichment_duration_ms: normalizeDurations(metrics.enrichmentDurations), execution_gap_duration_s: normalizeGap(metrics.executionGap), + gap_range: metrics.gapRange ?? undefined, } : undefined, userError, diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_monitoring/logic/rule_execution_log/client_for_executors/client_interface.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_monitoring/logic/rule_execution_log/client_for_executors/client_interface.ts index 2200424891fee..1c55e9e252581 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_monitoring/logic/rule_execution_log/client_for_executors/client_interface.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_monitoring/logic/rule_execution_log/client_for_executors/client_interface.ts @@ -130,4 +130,5 @@ export interface MetricsArgs { indexingDurations?: string[]; enrichmentDurations?: string[]; executionGap?: Duration; + gapRange?: { gte: string; lte: string }; } diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_types/create_security_rule_type_wrapper.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_types/create_security_rule_type_wrapper.ts index b82c1f942fafb..f733cd2a07c9c 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_types/create_security_rule_type_wrapper.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_types/create_security_rule_type_wrapper.ts @@ -313,6 +313,7 @@ export const createSecurityRuleTypeWrapper: CreateSecurityRuleTypeWrapper = tuples, remainingGap, warningStatusMessage: rangeTuplesWarningMessage, + gap, } = await getRuleRangeTuples({ startedAt, previousStartedAt, @@ -334,7 +335,10 @@ export const createSecurityRuleTypeWrapper: CreateSecurityRuleTypeWrapper = await ruleExecutionLogger.logStatusChange({ newStatus: RuleExecutionStatusEnum.failed, message: gapErrorMessage, - metrics: { executionGap: remainingGap }, + metrics: { + executionGap: remainingGap, + gapRange: experimentalFeatures?.storeGapsInEventLogEnabled ? gap : undefined, + }, }); } @@ -513,6 +517,7 @@ export const createSecurityRuleTypeWrapper: CreateSecurityRuleTypeWrapper = indexingDurations: result.bulkCreateTimes, enrichmentDurations: result.enrichmentTimes, executionGap: remainingGap, + gapRange: experimentalFeatures?.storeGapsInEventLogEnabled ? gap : undefined, }, userError: result.userError, }); diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_types/utils/utils.test.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_types/utils/utils.test.ts index 3430d2ae903ef..83857ee236f5e 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_types/utils/utils.test.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_types/utils/utils.test.ts @@ -491,9 +491,11 @@ describe('utils', () => { }); test('should return two tuples if gap and previouslyStartedAt', async () => { - const { tuples, remainingGap, warningStatusMessage } = await getRuleRangeTuples({ - previousStartedAt: moment().subtract(65, 's').toDate(), - startedAt: moment().toDate(), + const previouslyStartedAt = moment().subtract(65, 's').toDate(); + const startedAt = moment().toDate(); + const { tuples, remainingGap, warningStatusMessage, gap } = await getRuleRangeTuples({ + previousStartedAt: previouslyStartedAt, + startedAt, interval: '50s', from: 'now-55s', to: 'now', @@ -505,12 +507,15 @@ describe('utils', () => { expect(moment(someTuple.to).diff(moment(someTuple.from), 's')).toEqual(55); expect(remainingGap.asMilliseconds()).toEqual(0); expect(warningStatusMessage).toEqual(undefined); + expect(gap).toEqual(undefined); }); test('should return five tuples when give long gap', async () => { - const { tuples, remainingGap, warningStatusMessage } = await getRuleRangeTuples({ - previousStartedAt: moment().subtract(65, 's').toDate(), // 64 is 5 times the interval + lookback, which will trigger max lookback - startedAt: moment().toDate(), + const previousStartedAt = moment().subtract(65, 's').toDate(); // 64 is 5 times the interval + lookback, which will trigger max lookback + const startedAt = moment().toDate(); + const { tuples, remainingGap, warningStatusMessage, gap } = await getRuleRangeTuples({ + previousStartedAt, + startedAt, interval: '10s', from: 'now-13s', to: 'now', @@ -529,6 +534,8 @@ describe('utils', () => { }); expect(remainingGap.asMilliseconds()).toEqual(12000); expect(warningStatusMessage).toEqual(undefined); + expect(gap?.gte).toEqual(previousStartedAt.toISOString()); + expect(gap?.lte).toEqual(moment(previousStartedAt).add(remainingGap, 'ms').toISOString()); }); test('should return a single tuple when give a negative gap (rule ran sooner than expected)', async () => { diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_types/utils/utils.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_types/utils/utils.ts index 75c8b30dc88df..d18020c7dbee9 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_types/utils/utils.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/rule_types/utils/utils.ts @@ -517,10 +517,19 @@ export const getRuleRangeTuples = async ({ 0 ); + let gapRange; + if (remainingGapMilliseconds > 0 && previousStartedAt != null) { + gapRange = { + gte: previousStartedAt.toISOString(), + lte: moment(previousStartedAt).add(remainingGapMilliseconds).toDate().toISOString(), + }; + } + return { tuples: tuples.reverse(), remainingGap: moment.duration(remainingGapMilliseconds), warningStatusMessage, + gap: gapRange, }; }; diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/timeline/routes/timelines/delete_timelines/index.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/timeline/routes/timelines/delete_timelines/index.ts index 4d64ab88c88fb..b8368ec7fe9e6 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/timeline/routes/timelines/delete_timelines/index.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/timeline/routes/timelines/delete_timelines/index.ts @@ -22,7 +22,7 @@ export const deleteTimelinesRoute = (router: SecuritySolutionPluginRouter) => { path: TIMELINE_URL, security: { authz: { - requiredPrivileges: ['securitySolution'], + requiredPrivileges: ['timeline_write'], }, }, access: 'public', diff --git a/x-pack/solutions/security/plugins/security_solution/server/lib/timeline/routes/timelines/persist_favorite/index.ts b/x-pack/solutions/security/plugins/security_solution/server/lib/timeline/routes/timelines/persist_favorite/index.ts index 31d80eebcf9aa..54c08667edd92 100644 --- a/x-pack/solutions/security/plugins/security_solution/server/lib/timeline/routes/timelines/persist_favorite/index.ts +++ b/x-pack/solutions/security/plugins/security_solution/server/lib/timeline/routes/timelines/persist_favorite/index.ts @@ -28,7 +28,7 @@ export const persistFavoriteRoute = (router: SecuritySolutionPluginRouter) => { path: TIMELINE_FAVORITE_URL, security: { authz: { - requiredPrivileges: ['timeline_read'], + requiredPrivileges: ['timeline_write'], }, }, access: 'public', diff --git a/x-pack/solutions/security/plugins/security_solution/tsconfig.json b/x-pack/solutions/security/plugins/security_solution/tsconfig.json index 5ab84a11506ff..d759bc5d9112f 100644 --- a/x-pack/solutions/security/plugins/security_solution/tsconfig.json +++ b/x-pack/solutions/security/plugins/security_solution/tsconfig.json @@ -39,7 +39,6 @@ "@kbn/encrypted-saved-objects-plugin", "@kbn/features-plugin", "@kbn/fleet-plugin", - "@kbn/kubernetes-security-plugin", "@kbn/licensing-plugin", "@kbn/lists-plugin", "@kbn/maps-plugin", diff --git a/x-pack/solutions/security/plugins/security_solution_serverless/public/plugin.ts b/x-pack/solutions/security/plugins/security_solution_serverless/public/plugin.ts index 09eb56ec0edcb..a9743ef4fa51f 100644 --- a/x-pack/solutions/security/plugins/security_solution_serverless/public/plugin.ts +++ b/x-pack/solutions/security/plugins/security_solution_serverless/public/plugin.ts @@ -53,8 +53,6 @@ export class SecuritySolutionServerlessPlugin securitySolution.experimentalFeatures ).features; - setupDeps.discover.showInlineTopNav(); - return {}; } diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group4/builtin_alert_types/circuit_breaker/index_threshold_max_alerts.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group4/builtin_alert_types/circuit_breaker/index_threshold_max_alerts.ts index d18a70fd4699c..8bab44baee538 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group4/builtin_alert_types/circuit_breaker/index_threshold_max_alerts.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group4/builtin_alert_types/circuit_breaker/index_threshold_max_alerts.ts @@ -24,8 +24,7 @@ export default function maxAlertsRuleTests({ getService }: FtrProviderContext) { const es = getService('es'); const esTestIndexTool = new ESTestIndexTool(es, retry); - // Failing: See https://github.com/elastic/kibana/issues/193876 - describe.skip('index threshold rule that hits max alerts circuit breaker', () => { + describe('index threshold rule that hits max alerts circuit breaker', () => { const objectRemover = new ObjectRemover(supertest); beforeEach(async () => { diff --git a/x-pack/test/api_integration/apis/slos/helper/es.ts b/x-pack/test/api_integration/apis/slos/helper/es.ts index f5ac7a6e23c88..eed0df0430e07 100644 --- a/x-pack/test/api_integration/apis/slos/helper/es.ts +++ b/x-pack/test/api_integration/apis/slos/helper/es.ts @@ -6,8 +6,8 @@ */ import { Client } from '@elastic/elasticsearch'; import { - SLO_DESTINATION_INDEX_PATTERN, - SLO_SUMMARY_DESTINATION_INDEX_PATTERN, + SLI_DESTINATION_INDEX_PATTERN, + SUMMARY_DESTINATION_INDEX_PATTERN, } from '@kbn/slo-plugin/common/constants'; export class SloEsClient { @@ -15,7 +15,7 @@ export class SloEsClient { public async getSLOSummaryDataById(id: string) { return await this.esClient.search({ - index: SLO_SUMMARY_DESTINATION_INDEX_PATTERN, + index: SUMMARY_DESTINATION_INDEX_PATTERN, body: { query: { bool: { @@ -35,7 +35,7 @@ export class SloEsClient { public async getSLORollupDataById(id: string) { return await this.esClient.search({ - index: SLO_DESTINATION_INDEX_PATTERN, + index: SLI_DESTINATION_INDEX_PATTERN, body: { query: { bool: { diff --git a/x-pack/test/api_integration/apis/synthetics/add_monitor_private_location.ts b/x-pack/test/api_integration/apis/synthetics/add_monitor_private_location.ts index 5b0c967601638..df35097b96763 100644 --- a/x-pack/test/api_integration/apis/synthetics/add_monitor_private_location.ts +++ b/x-pack/test/api_integration/apis/synthetics/add_monitor_private_location.ts @@ -71,7 +71,7 @@ export default function ({ getService }: FtrProviderContext) { it('add a test private location', async () => { pvtLoc = await testPrivateLocations.addPrivateLocation(); - testFleetPolicyID = pvtLoc.id; + testFleetPolicyID = pvtLoc.agentPolicyId; const apiResponse = await supertestAPI.get(SYNTHETICS_API_URLS.SERVICE_LOCATIONS); @@ -124,7 +124,7 @@ export default function ({ getService }: FtrProviderContext) { it('adds a monitor in private location', async () => { const newMonitor = httpMonitorJson; - newMonitor.locations.push(pvtLoc); + newMonitor.locations.push(omit(pvtLoc, ['spaces'])); const { body, rawBody } = await addMonitorAPI(newMonitor); @@ -138,8 +138,7 @@ export default function ({ getService }: FtrProviderContext) { ); const packagePolicy = apiResponse.body.items.find( - (pkgPolicy: PackagePolicy) => - pkgPolicy.id === newMonitorId + '-' + testFleetPolicyID + '-default' + (pkgPolicy: PackagePolicy) => pkgPolicy.id === newMonitorId + '-' + pvtLoc.id + '-default' ); expect(packagePolicy?.policy_id).eql(testFleetPolicyID); @@ -149,23 +148,33 @@ export default function ({ getService }: FtrProviderContext) { getTestSyntheticsPolicy({ name: httpMonitorJson.name, id: newMonitorId, - location: { id: testFleetPolicyID }, + location: { id: pvtLoc.id }, }) ); }); let testFleetPolicyID2: string; + let pvtLoc2: PrivateLocation; it('edits a monitor with additional private location', async () => { const resPolicy = await testPrivateLocations.addFleetPolicy(testPolicyName + 1); testFleetPolicyID2 = resPolicy.body.item.id; - const pvtLoc2 = await testPrivateLocations.addPrivateLocation({ + pvtLoc2 = await testPrivateLocations.addPrivateLocation({ policyId: testFleetPolicyID2, label: 'Test private location 1', }); - httpMonitorJson.locations.push(pvtLoc2); + httpMonitorJson.locations.push({ + id: pvtLoc2.id, + label: pvtLoc2.label, + isServiceManaged: false, + agentPolicyId: pvtLoc2.agentPolicyId, + geo: { + lat: 0, + lon: 0, + }, + }); const apiResponse = await supertestAPI .put(SYNTHETICS_API_URLS.SYNTHETICS_MONITORS + '/' + newMonitorId) @@ -191,8 +200,7 @@ export default function ({ getService }: FtrProviderContext) { ); let packagePolicy = apiResponsePolicy.body.items.find( - (pkgPolicy: PackagePolicy) => - pkgPolicy.id === newMonitorId + '-' + testFleetPolicyID + '-default' + (pkgPolicy: PackagePolicy) => pkgPolicy.id === newMonitorId + '-' + pvtLoc.id + '-default' ); expect(packagePolicy.policy_id).eql(testFleetPolicyID); @@ -202,13 +210,12 @@ export default function ({ getService }: FtrProviderContext) { getTestSyntheticsPolicy({ name: httpMonitorJson.name, id: newMonitorId, - location: { id: testFleetPolicyID }, + location: { id: pvtLoc.id }, }) ); packagePolicy = apiResponsePolicy.body.items.find( - (pkgPolicy: PackagePolicy) => - pkgPolicy.id === newMonitorId + '-' + testFleetPolicyID2 + '-default' + (pkgPolicy: PackagePolicy) => pkgPolicy.id === newMonitorId + '-' + pvtLoc2.id + '-default' ); expect(packagePolicy.policy_id).eql(testFleetPolicyID2); @@ -219,16 +226,14 @@ export default function ({ getService }: FtrProviderContext) { id: newMonitorId, location: { name: 'Test private location 1', - id: testFleetPolicyID2, + id: pvtLoc2.id, }, }) ); }); it('deletes integration for a removed location from monitor', async () => { - httpMonitorJson.locations = httpMonitorJson.locations.filter( - ({ id }) => id !== testFleetPolicyID2 - ); + httpMonitorJson.locations = httpMonitorJson.locations.filter(({ id }) => id !== pvtLoc2.id); await supertestAPI .put(SYNTHETICS_API_URLS.SYNTHETICS_MONITORS + '/' + newMonitorId + '?internal=true') @@ -241,8 +246,7 @@ export default function ({ getService }: FtrProviderContext) { ); let packagePolicy = apiResponsePolicy.body.items.find( - (pkgPolicy: PackagePolicy) => - pkgPolicy.id === newMonitorId + '-' + testFleetPolicyID + '-default' + (pkgPolicy: PackagePolicy) => pkgPolicy.id === newMonitorId + '-' + pvtLoc.id + '-default' ); expect(packagePolicy.policy_id).eql(testFleetPolicyID); @@ -252,13 +256,12 @@ export default function ({ getService }: FtrProviderContext) { getTestSyntheticsPolicy({ name: httpMonitorJson.name, id: newMonitorId, - location: { id: testFleetPolicyID }, + location: { id: pvtLoc.id }, }) ); packagePolicy = apiResponsePolicy.body.items.find( - (pkgPolicy: PackagePolicy) => - pkgPolicy.id === newMonitorId + '-' + testFleetPolicyID2 + '-default' + (pkgPolicy: PackagePolicy) => pkgPolicy.id === newMonitorId + '-' + pvtLoc2.id + '-default' ); expect(packagePolicy).eql(undefined); @@ -287,7 +290,7 @@ export default function ({ getService }: FtrProviderContext) { ...httpMonitorJson, name: `Test monitor ${uuidv4()}`, [ConfigKey.NAMESPACE]: 'default', - locations: [pvtLoc], + locations: [omit(pvtLoc, ['spaces'])], }; try { @@ -316,7 +319,7 @@ export default function ({ getService }: FtrProviderContext) { const packagePolicy = policyResponse.body.items.find( (pkgPolicy: PackagePolicy) => - pkgPolicy.id === monitorId + '-' + testFleetPolicyID + `-${SPACE_ID}` + pkgPolicy.id === monitorId + '-' + pvtLoc.id + `-${SPACE_ID}` ); expect(packagePolicy.policy_id).eql(testFleetPolicyID); @@ -326,7 +329,7 @@ export default function ({ getService }: FtrProviderContext) { getTestSyntheticsPolicy({ name: monitor.name, id: monitorId, - location: { id: testFleetPolicyID }, + location: { id: pvtLoc.id }, namespace: formatKibanaNamespace(SPACE_ID), spaceId: SPACE_ID, }) @@ -350,7 +353,7 @@ export default function ({ getService }: FtrProviderContext) { ...httpMonitorJson, locations: [ { - id: testFleetPolicyID, + id: pvtLoc.id, label: 'Test private location 0', isServiceManaged: false, }, @@ -374,15 +377,14 @@ export default function ({ getService }: FtrProviderContext) { ); const packagePolicy = policyResponse.body.items.find( - (pkgPolicy: PackagePolicy) => - pkgPolicy.id === monitorId + '-' + testFleetPolicyID + `-default` + (pkgPolicy: PackagePolicy) => pkgPolicy.id === monitorId + '-' + pvtLoc.id + `-default` ); comparePolicies( packagePolicy, getTestSyntheticsPolicy({ name: monitor.name, id: monitorId, - location: { id: testFleetPolicyID }, + location: { id: pvtLoc.id }, isTLSEnabled: true, }) ); @@ -398,7 +400,7 @@ export default function ({ getService }: FtrProviderContext) { ...httpMonitorJson, locations: [ { - id: testFleetPolicyID, + id: pvtLoc.id, label: 'Test private location 0', isServiceManaged: false, }, @@ -412,8 +414,9 @@ export default function ({ getService }: FtrProviderContext) { const apiResponse = await supertestAPI .post(SYNTHETICS_API_URLS.SYNTHETICS_MONITORS) .set('kbn-xsrf', 'true') - .send(monitor) - .expect(200); + .send(monitor); + + expect(apiResponse.status).eql(200, JSON.stringify(apiResponse.body)); monitorId = apiResponse.body.id; @@ -422,15 +425,14 @@ export default function ({ getService }: FtrProviderContext) { ); const packagePolicy = policyResponse.body.items.find( - (pkgPolicy: PackagePolicy) => - pkgPolicy.id === monitorId + '-' + testFleetPolicyID + `-default` + (pkgPolicy: PackagePolicy) => pkgPolicy.id === monitorId + '-' + pvtLoc.id + `-default` ); comparePolicies( packagePolicy, getTestSyntheticsPolicy({ name: monitor.name, id: monitorId, - location: { id: testFleetPolicyID }, + location: { id: pvtLoc.id }, }) ); } finally { @@ -447,7 +449,7 @@ export default function ({ getService }: FtrProviderContext) { [ConfigKey.NAMESPACE]: 'default', locations: [ { - id: testFleetPolicyID, + id: pvtLoc.id, label: 'Test private location 0', isServiceManaged: false, }, @@ -467,8 +469,7 @@ export default function ({ getService }: FtrProviderContext) { ); const packagePolicy = policyResponse.body.items.find( - (pkgPolicy: PackagePolicy) => - pkgPolicy.id === monitorId + '-' + testFleetPolicyID + `-default` + (pkgPolicy: PackagePolicy) => pkgPolicy.id === monitorId + '-' + pvtLoc.id + `-default` ); expect(packagePolicy.package.version).eql(INSTALLED_VERSION); @@ -478,8 +479,7 @@ export default function ({ getService }: FtrProviderContext) { '/api/fleet/package_policies?page=1&perPage=2000&kuery=ingest-package-policies.package.name%3A%20synthetics' ); const packagePolicyAfterUpgrade = policyResponseAfterUpgrade.body.items.find( - (pkgPolicy: PackagePolicy) => - pkgPolicy.id === monitorId + '-' + testFleetPolicyID + `-default` + (pkgPolicy: PackagePolicy) => pkgPolicy.id === monitorId + '-' + pvtLoc.id + `-default` ); expect(semver.gte(packagePolicyAfterUpgrade.package.version, INSTALLED_VERSION)).eql(true); } finally { diff --git a/x-pack/test/api_integration/apis/synthetics/add_monitor_project.ts b/x-pack/test/api_integration/apis/synthetics/add_monitor_project.ts index 661fe4af3c87c..c7eb8131e9d32 100644 --- a/x-pack/test/api_integration/apis/synthetics/add_monitor_project.ts +++ b/x-pack/test/api_integration/apis/synthetics/add_monitor_project.ts @@ -46,6 +46,7 @@ export default function ({ getService }: FtrProviderContext) { let icmpProjectMonitors: ProjectMonitorsRequest; let testPolicyId = ''; + let loc: any; const setUniqueIds = (request: ProjectMonitorsRequest) => { return { ...request, @@ -85,8 +86,8 @@ export default function ({ getService }: FtrProviderContext) { .expect(200); await testPrivateLocations.installSyntheticsPackage(); - const loc = await testPrivateLocations.addPrivateLocation(); - testPolicyId = loc.id; + loc = await testPrivateLocations.addPrivateLocation(); + testPolicyId = loc.agentPolicyId; await supertest .post(SYNTHETICS_API_URLS.PARAMS) .set('kbn-xsrf', 'true') @@ -644,7 +645,7 @@ export default function ({ getService }: FtrProviderContext) { lat: 0, lon: 0, }, - id: testPolicyId, + id: loc.id, agentPolicyId: testPolicyId, isServiceManaged: false, label: 'Test private location 0', @@ -1443,7 +1444,7 @@ export default function ({ getService }: FtrProviderContext) { const packagePolicy = apiResponsePolicy.body.items.find( (pkgPolicy: PackagePolicy) => pkgPolicy.id === - `${monitorsResponse.body.monitors[0][ConfigKey.CUSTOM_HEARTBEAT_ID]}-${testPolicyId}` + `${monitorsResponse.body.monitors[0][ConfigKey.CUSTOM_HEARTBEAT_ID]}-${loc.id}` ); expect(packagePolicy.name).eql( `${projectMonitors.monitors[0].id}-${project}-default-Test private location 0` @@ -1511,7 +1512,7 @@ export default function ({ getService }: FtrProviderContext) { const packagePolicy = apiResponsePolicy.body.items.find( (pkgPolicy: PackagePolicy) => pkgPolicy.id === - `${monitorsResponse.body.monitors[0][ConfigKey.CUSTOM_HEARTBEAT_ID]}-${testPolicyId}` + `${monitorsResponse.body.monitors[0][ConfigKey.CUSTOM_HEARTBEAT_ID]}-${loc.id}` ); expect(packagePolicy.name).eql( `${httpProjectMonitors.monitors[1].id}-${project}-default-Test private location 0` @@ -1530,7 +1531,7 @@ export default function ({ getService }: FtrProviderContext) { configId, projectId: project, locationName: 'Test private location 0', - locationId: testPolicyId, + locationId: loc.id, }) ); } finally { @@ -1575,7 +1576,7 @@ export default function ({ getService }: FtrProviderContext) { const packagePolicy = apiResponsePolicy.body.items.find( (pkgPolicy: PackagePolicy) => pkgPolicy.id === - `${monitorsResponse.body.monitors[0][ConfigKey.CUSTOM_HEARTBEAT_ID]}-${testPolicyId}` + `${monitorsResponse.body.monitors[0][ConfigKey.CUSTOM_HEARTBEAT_ID]}-${loc.id}` ); expect(packagePolicy.policy_id).eql(testPolicyId); @@ -1597,7 +1598,7 @@ export default function ({ getService }: FtrProviderContext) { const packagePolicy2 = apiResponsePolicy2.body.items.find( (pkgPolicy: PackagePolicy) => pkgPolicy.id === - `${monitorsResponse.body.monitors[0][ConfigKey.CUSTOM_HEARTBEAT_ID]}-${testPolicyId}` + `${monitorsResponse.body.monitors[0][ConfigKey.CUSTOM_HEARTBEAT_ID]}-${loc.id}` ); expect(packagePolicy2).eql(undefined); @@ -1637,7 +1638,7 @@ export default function ({ getService }: FtrProviderContext) { const packagePolicy = apiResponsePolicy.body.items.find( (pkgPolicy: PackagePolicy) => pkgPolicy.id === - `${monitorsResponse.body.monitors[0][ConfigKey.CUSTOM_HEARTBEAT_ID]}-${testPolicyId}` + `${monitorsResponse.body.monitors[0][ConfigKey.CUSTOM_HEARTBEAT_ID]}-${loc.id}` ); expect(packagePolicy.policy_id).eql(testPolicyId); @@ -1721,7 +1722,7 @@ export default function ({ getService }: FtrProviderContext) { const configId = monitorsResponse.body.monitors[0].id; const id = monitorsResponse.body.monitors[0][ConfigKey.CUSTOM_HEARTBEAT_ID]; - const policyId = `${id}-${testPolicyId}`; + const policyId = `${id}-${loc.id}`; const packagePolicy = apiResponsePolicy.body.items.find( (pkgPolicy: PackagePolicy) => pkgPolicy.id === policyId @@ -1737,7 +1738,7 @@ export default function ({ getService }: FtrProviderContext) { id, configId, projectId: project, - locationId: testPolicyId, + locationId: loc.id, locationName: 'Test private location 0', }) ); @@ -1764,7 +1765,7 @@ export default function ({ getService }: FtrProviderContext) { const configId2 = monitorsResponse.body.monitors[0].id; const id2 = monitorsResponse.body.monitors[0][ConfigKey.CUSTOM_HEARTBEAT_ID]; - const policyId2 = `${id}-${testPolicyId}`; + const policyId2 = `${id}-${loc.id}`; const packagePolicy2 = apiResponsePolicy2.body.items.find( (pkgPolicy: PackagePolicy) => pkgPolicy.id === policyId2 @@ -1778,7 +1779,7 @@ export default function ({ getService }: FtrProviderContext) { id: id2, configId: configId2, projectId: project, - locationId: testPolicyId, + locationId: loc.id, locationName: 'Test private location 0', namespace: 'custom_namespace', }) @@ -1832,7 +1833,7 @@ export default function ({ getService }: FtrProviderContext) { label: 'Test private location 0', isServiceManaged: false, agentPolicyId: testPolicyId, - id: testPolicyId, + id: loc.id, geo: { lat: 0, lon: 0, diff --git a/x-pack/test/api_integration/apis/synthetics/delete_monitor_project.ts b/x-pack/test/api_integration/apis/synthetics/delete_monitor_project.ts index b240b1ec3d113..88d2e4384e242 100644 --- a/x-pack/test/api_integration/apis/synthetics/delete_monitor_project.ts +++ b/x-pack/test/api_integration/apis/synthetics/delete_monitor_project.ts @@ -27,6 +27,7 @@ export default function ({ getService }: FtrProviderContext) { let projectMonitors: ProjectMonitorsRequest; let testPolicyId = ''; + let loc: any; const testPrivateLocations = new PrivateLocationTestService(getService); const setUniqueIds = (request: ProjectMonitorsRequest) => { @@ -39,8 +40,8 @@ export default function ({ getService }: FtrProviderContext) { before(async () => { await kibanaServer.savedObjects.cleanStandardList(); await testPrivateLocations.installSyntheticsPackage(); - const loc = await testPrivateLocations.addPrivateLocation(); - testPolicyId = loc.id; + loc = await testPrivateLocations.addPrivateLocation(); + testPolicyId = loc.agentPolicyId; }); beforeEach(() => { @@ -404,9 +405,7 @@ export default function ({ getService }: FtrProviderContext) { const packagePolicy = apiResponsePolicy.body.items.find( (pkgPolicy: PackagePolicy) => pkgPolicy.id === - savedObjectsResponse.body.monitors[0][ConfigKey.CUSTOM_HEARTBEAT_ID] + - '-' + - testPolicyId + savedObjectsResponse.body.monitors[0][ConfigKey.CUSTOM_HEARTBEAT_ID] + '-' + loc.id ); expect(packagePolicy.policy_id).to.be(testPolicyId); @@ -438,9 +437,7 @@ export default function ({ getService }: FtrProviderContext) { const packagePolicy2 = apiResponsePolicy2.body.items.find( (pkgPolicy: PackagePolicy) => pkgPolicy.id === - savedObjectsResponse.body.monitors[0][ConfigKey.CUSTOM_HEARTBEAT_ID] + - '-' + - testPolicyId + savedObjectsResponse.body.monitors[0][ConfigKey.CUSTOM_HEARTBEAT_ID] + '-' + loc.id ); expect(packagePolicy2).to.be(undefined); } finally { diff --git a/x-pack/test/api_integration/apis/synthetics/edit_monitor_public_api.ts b/x-pack/test/api_integration/apis/synthetics/edit_monitor_public_api.ts index aeb0eaa0299b3..ef4294a4089d6 100644 --- a/x-pack/test/api_integration/apis/synthetics/edit_monitor_public_api.ts +++ b/x-pack/test/api_integration/apis/synthetics/edit_monitor_public_api.ts @@ -65,7 +65,7 @@ export default function ({ getService }: FtrProviderContext) { }); after(async () => { - await kibanaServer.savedObjects.cleanStandardList(); + // await kibanaServer.savedObjects.cleanStandardList(); }); let monitorId = 'test-id'; @@ -256,7 +256,7 @@ export default function ({ getService }: FtrProviderContext) { ...updates, revision: 3, url: 'https://www.google.com', - locations: [localLoc, pvtLoc], + locations: [localLoc, omit(pvtLoc, 'spaces')], }) ); @@ -270,7 +270,7 @@ export default function ({ getService }: FtrProviderContext) { ...updates, revision: 4, url: 'https://www.google.com', - locations: [pvtLoc], + locations: [omit(pvtLoc, 'spaces')], }) ); }); @@ -289,7 +289,7 @@ export default function ({ getService }: FtrProviderContext) { ...updates, revision: 5, url: 'https://www.google.com', - locations: [localLoc, pvtLoc], + locations: [localLoc, omit(pvtLoc, 'spaces')], }) ); diff --git a/x-pack/test/api_integration/apis/synthetics/private_location_apis.ts b/x-pack/test/api_integration/apis/synthetics/private_location_apis.ts index a4351ede2eda0..7f55ef4cf064f 100644 --- a/x-pack/test/api_integration/apis/synthetics/private_location_apis.ts +++ b/x-pack/test/api_integration/apis/synthetics/private_location_apis.ts @@ -21,6 +21,7 @@ export default function ({ getService }: FtrProviderContext) { describe('PrivateLocationAPI', function () { this.tags('skipCloud'); const supertestWithoutAuth = getService('supertestWithoutAuth'); + const supertest = getService('supertest'); const kServer = getService('kibanaServer'); @@ -132,5 +133,64 @@ export default function ({ getService }: FtrProviderContext) { expect(deleteResponse.status).to.be(200); } }); + + it('can create private location in multiple spaces', async () => { + const apiResponse = await testPrivateLocations.addFleetPolicy(); + const agentPolicyId = apiResponse.body.item.id; + + const { SPACE_ID } = await monitorTestService.addsNewSpace([ + 'minimal_all', + 'can_manage_private_locations', + ]); + + const location: Omit = { + label: 'Test private location 11', + agentPolicyId: agentPolicyId!, + geo: { + lat: 0, + lon: 0, + }, + spaces: [SPACE_ID, 'default'], + }; + const response = await supertest + .post(SYNTHETICS_API_URLS.PRIVATE_LOCATIONS) + .set('kbn-xsrf', 'true') + .send(location); + + expect(response.status).to.be(200); + }); + + it('validation errors works in multiple spaces as well', async () => { + const apiResponse = await testPrivateLocations.addFleetPolicy(); + const agentPolicyId = apiResponse.body.item.id; + + const { username, password, SPACE_ID } = await monitorTestService.addsNewSpace([ + 'minimal_all', + 'can_manage_private_locations', + ]); + + const location: Omit = { + label: 'Test private location 12', + agentPolicyId: agentPolicyId!, + geo: { + lat: 0, + lon: 0, + }, + spaces: [SPACE_ID, 'default'], + }; + const response = await supertest + .post(SYNTHETICS_API_URLS.PRIVATE_LOCATIONS) + .set('kbn-xsrf', 'true') + .send(location); + + expect(response.status).to.be(200); + + const response1 = await supertestWithoutAuth + .post(SYNTHETICS_API_URLS.PRIVATE_LOCATIONS) + .auth(username, password) + .set('kbn-xsrf', 'true') + .send({ ...location, spaces: [SPACE_ID] }); + expect(response1.status).to.be(400); + }); }); } diff --git a/x-pack/test/api_integration/apis/synthetics/sync_global_params.ts b/x-pack/test/api_integration/apis/synthetics/sync_global_params.ts index 44cd5b19d6697..e519b8a874aff 100644 --- a/x-pack/test/api_integration/apis/synthetics/sync_global_params.ts +++ b/x-pack/test/api_integration/apis/synthetics/sync_global_params.ts @@ -30,6 +30,7 @@ export default function ({ getService }: FtrProviderContext) { const kServer = getService('kibanaServer'); let testFleetPolicyID: string; + let loc: any; let _browserMonitorJson: HTTPFields; let browserMonitorJson: HTTPFields; @@ -61,8 +62,8 @@ export default function ({ getService }: FtrProviderContext) { }); it('add a test private location', async () => { - const loc = await testPrivateLocations.addPrivateLocation(); - testFleetPolicyID = loc.id; + loc = await testPrivateLocations.addPrivateLocation(); + testFleetPolicyID = loc.agentPolicyId; const apiResponse = await supertestAPI.get(SYNTHETICS_API_URLS.SERVICE_LOCATIONS); @@ -86,7 +87,7 @@ export default function ({ getService }: FtrProviderContext) { isInvalid: false, }, { - id: testFleetPolicyID, + id: loc.id, isInvalid: false, isServiceManaged: false, label: 'Test private location 0', @@ -95,6 +96,7 @@ export default function ({ getService }: FtrProviderContext) { lon: 0, }, agentPolicyId: testFleetPolicyID, + spaces: ['*'], }, ]; @@ -105,7 +107,7 @@ export default function ({ getService }: FtrProviderContext) { const newMonitor = browserMonitorJson; const pvtLoc = { - id: testFleetPolicyID, + id: loc.id, agentPolicyId: testFleetPolicyID, label: 'Test private location 0', isServiceManaged: false, @@ -136,8 +138,7 @@ export default function ({ getService }: FtrProviderContext) { ); const packagePolicy = apiResponse.body.items.find( - (pkgPolicy: PackagePolicy) => - pkgPolicy.id === newMonitorId + '-' + testFleetPolicyID + '-default' + (pkgPolicy: PackagePolicy) => pkgPolicy.id === newMonitorId + '-' + loc.id + '-default' ); expect(packagePolicy?.policy_id).eql( @@ -193,8 +194,7 @@ export default function ({ getService }: FtrProviderContext) { ); const packagePolicy = apiResponse.body.items.find( - (pkgPolicy: PackagePolicy) => - pkgPolicy.id === newMonitorId + '-' + testFleetPolicyID + '-default' + (pkgPolicy: PackagePolicy) => pkgPolicy.id === newMonitorId + '-' + loc.id + '-default' ); expect(packagePolicy.policy_id).eql(testFleetPolicyID); @@ -214,7 +214,7 @@ export default function ({ getService }: FtrProviderContext) { it('add a http monitor using param', async () => { const newMonitor = httpMonitorJson; const pvtLoc = { - id: testFleetPolicyID, + id: loc.id, agentPolicyId: testFleetPolicyID, label: 'Test private location 0', isServiceManaged: false, @@ -246,8 +246,7 @@ export default function ({ getService }: FtrProviderContext) { ); const packagePolicy = apiResponse.body.items.find( - (pkgPolicy: PackagePolicy) => - pkgPolicy.id === newHttpMonitorId + '-' + testFleetPolicyID + '-default' + (pkgPolicy: PackagePolicy) => pkgPolicy.id === newHttpMonitorId + '-' + loc.id + '-default' ); expect(packagePolicy.policy_id).eql(testFleetPolicyID); @@ -257,7 +256,7 @@ export default function ({ getService }: FtrProviderContext) { id: newHttpMonitorId, isTLSEnabled: false, namespace: 'testnamespace', - location: { id: testFleetPolicyID }, + location: { id: loc.id }, }); comparePolicies(packagePolicy, pPolicy); @@ -304,8 +303,7 @@ export default function ({ getService }: FtrProviderContext) { ); const packagePolicy = apiResponse.body.items.find( - (pkgPolicy: PackagePolicy) => - pkgPolicy.id === newMonitorId + '-' + testFleetPolicyID + '-default' + (pkgPolicy: PackagePolicy) => pkgPolicy.id === newMonitorId + '-' + loc.id + '-default' ); expect(packagePolicy.policy_id).eql(testFleetPolicyID); @@ -316,7 +314,7 @@ export default function ({ getService }: FtrProviderContext) { name: browserMonitorJson.name, id: newMonitorId, isBrowser: true, - location: { id: testFleetPolicyID }, + location: { id: loc.id }, }) ); }); diff --git a/x-pack/test/api_integration/apis/upgrade_assistant/upgrade_assistant.ts b/x-pack/test/api_integration/apis/upgrade_assistant/upgrade_assistant.ts index d7a96333f49e8..f0b8259fb7363 100644 --- a/x-pack/test/api_integration/apis/upgrade_assistant/upgrade_assistant.ts +++ b/x-pack/test/api_integration/apis/upgrade_assistant/upgrade_assistant.ts @@ -128,13 +128,68 @@ export default function ({ getService }: FtrProviderContext) { .expect(200); const expectedResponseKeys = ['readyForUpgrade', 'details']; + // We're not able to easily test different upgrade status scenarios (there are tests with mocked data to handle this) + // so, for now, we simply verify the response returns the expected format + expectedResponseKeys.forEach((key) => { + expect(body[key]).to.not.equal(undefined); + }); + }); + + it('returns a successful response when upgrading to the next minor', async () => { + const { body } = await supertest + .get('/api/upgrade_assistant/status') + .query({ + targetVersion: '9.1.0', + }) + .set('kbn-xsrf', 'xxx') + .expect(200); + const expectedResponseKeys = ['readyForUpgrade', 'details']; // We're not able to easily test different upgrade status scenarios (there are tests with mocked data to handle this) // so, for now, we simply verify the response returns the expected format expectedResponseKeys.forEach((key) => { expect(body[key]).to.not.equal(undefined); }); }); + + it('returns a successful response when upgrading to the next major', async () => { + const { body } = await supertest + .get('/api/upgrade_assistant/status') + .query({ + targetVersion: '10.0.0', + }) + .set('kbn-xsrf', 'xxx') + .expect(200); + + const expectedResponseKeys = ['readyForUpgrade', 'details']; + // We're not able to easily test different upgrade status scenarios (there are tests with mocked data to handle this) + // so, for now, we simply verify the response returns the expected format + expectedResponseKeys.forEach((key) => { + expect(body[key]).to.not.equal(undefined); + }); + }); + + it('returns 403 forbidden error when upgrading more than 1 major', async () => { + const { body } = await supertest + .get('/api/upgrade_assistant/status') + .query({ + targetVersion: '11.0.0', + }) + .set('kbn-xsrf', 'xxx') + .expect(403); + expect(body.message).to.be('Forbidden'); + }); + + it('returns 403 forbidden error when attempting to downgrade', async () => { + const { body } = await supertest + .get('/api/upgrade_assistant/status') + .query({ + targetVersion: '8.0.0', + }) + .set('kbn-xsrf', 'xxx') + .expect(403); + expect(body.message).to.be('Forbidden'); + }); }); }); } diff --git a/x-pack/test/api_integration/deployment_agnostic/apis/observability/slo/delete_slo.ts b/x-pack/test/api_integration/deployment_agnostic/apis/observability/slo/delete_slo.ts index 733d2b6250c29..d1e3fe6e53b68 100644 --- a/x-pack/test/api_integration/deployment_agnostic/apis/observability/slo/delete_slo.ts +++ b/x-pack/test/api_integration/deployment_agnostic/apis/observability/slo/delete_slo.ts @@ -9,8 +9,8 @@ import { cleanup, generate } from '@kbn/data-forge'; import expect from '@kbn/expect'; import { RoleCredentials } from '@kbn/ftr-common-functional-services'; import { - SLO_DESTINATION_INDEX_PATTERN, - SLO_SUMMARY_DESTINATION_INDEX_PATTERN, + SLI_DESTINATION_INDEX_PATTERN, + SUMMARY_DESTINATION_INDEX_PATTERN, getSLOSummaryTransformId, getSLOTransformId, } from '@kbn/slo-plugin/common/constants'; @@ -73,7 +73,7 @@ export default function ({ getService }: DeploymentAgnosticFtrProviderContext) { // expect summary and rollup documents to be deleted await retry.waitForWithTimeout('SLO summary data is deleted', 60 * 1000, async () => { const sloSummaryResponseAfterDeletion = await esClient.search({ - index: SLO_SUMMARY_DESTINATION_INDEX_PATTERN, + index: SUMMARY_DESTINATION_INDEX_PATTERN, body: { query: { bool: { @@ -97,7 +97,7 @@ export default function ({ getService }: DeploymentAgnosticFtrProviderContext) { await retry.waitForWithTimeout('SLO rollup data is deleted', 60 * 1000, async () => { const sloRollupResponseAfterDeletion = await esClient.search({ - index: SLO_DESTINATION_INDEX_PATTERN, + index: SLI_DESTINATION_INDEX_PATTERN, body: { query: { bool: { diff --git a/x-pack/test/api_integration/deployment_agnostic/apis/observability/synthetics/create_monitor_private_location.ts b/x-pack/test/api_integration/deployment_agnostic/apis/observability/synthetics/create_monitor_private_location.ts index c140ba7319e25..4a24dfeac6ba4 100644 --- a/x-pack/test/api_integration/deployment_agnostic/apis/observability/synthetics/create_monitor_private_location.ts +++ b/x-pack/test/api_integration/deployment_agnostic/apis/observability/synthetics/create_monitor_private_location.ts @@ -97,6 +97,7 @@ export default function ({ getService }: DeploymentAgnosticFtrProviderContext) { lon: 0, }, agentPolicyId: testFleetPolicyID, + spaces: ['default'], }, ]; @@ -115,6 +116,7 @@ export default function ({ getService }: DeploymentAgnosticFtrProviderContext) { lat: 0, lon: 0, }, + spaces: ['default'], }; newMonitor.name = invalidName; @@ -123,7 +125,7 @@ export default function ({ getService }: DeploymentAgnosticFtrProviderContext) { .post(SYNTHETICS_API_URLS.SYNTHETICS_MONITORS) .set(editorUser.apiKeyHeader) .set(samlAuth.getInternalRequestHeader()) - .send({ ...newMonitor, locations: [location] }) + .send({ ...newMonitor, locations: [omit(location, 'spaces')] }) .expect(400); expect(apiResponse.body).eql({ diff --git a/x-pack/test/api_integration/services/slo.ts b/x-pack/test/api_integration/services/slo.ts index d0d6cdc190e0e..9244ad7ee00d7 100644 --- a/x-pack/test/api_integration/services/slo.ts +++ b/x-pack/test/api_integration/services/slo.ts @@ -4,7 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import { SLO_SUMMARY_DESTINATION_INDEX_NAME } from '@kbn/slo-plugin/common/constants'; +import { SUMMARY_DESTINATION_INDEX_NAME } from '@kbn/slo-plugin/common/constants'; import { TOTAL_INDEX_PRIVILEGE_SET_EDITOR } from '@kbn/slo-plugin/server/services/get_diagnosis'; import { CreateSLOInput, @@ -110,7 +110,7 @@ export function SloApiProvider({ getService }: FtrProviderContext) { .send() .expect(204); } - await waitForIndexToBeEmpty({ esClient, indexName: SLO_SUMMARY_DESTINATION_INDEX_NAME }); + await waitForIndexToBeEmpty({ esClient, indexName: SUMMARY_DESTINATION_INDEX_NAME }); }, async fetchHistoricalSummary( params: FetchHistoricalSummaryParams 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 f96ac4a0d282a..52fa05ab726cc 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 @@ -20,7 +20,6 @@ import { CASE_CONFIGURE_SAVED_OBJECT, CASE_REPORTERS_URL, CASE_SAVED_OBJECT, - CASE_STATUS_URL, CASE_TAGS_URL, CASE_USER_ACTION_SAVED_OBJECT, INTERNAL_CASE_METRICS_URL, @@ -48,7 +47,6 @@ import { CasesBulkGetResponse, CasesFindResponse, CasesPatchRequest, - CasesStatusResponse, CustomFieldPutRequest, GetRelatedCasesByAlertResponse, SimilarCasesSearchRequest, @@ -450,26 +448,6 @@ export const updateCase = async ({ return cases; }; -export const getAllCasesStatuses = async ({ - supertest, - expectedHttpCode = 200, - auth = { user: superUser, space: null }, - query = {}, -}: { - supertest: SuperTest.Agent; - expectedHttpCode?: number; - auth?: { user: User; space: string | null }; - query?: Record; -}): Promise => { - const { body: statuses } = await supertest - .get(`${getSpaceUrlPrefix(auth.space)}${CASE_STATUS_URL}`) - .auth(auth.user.username, auth.user.password) - .query({ ...query }) - .expect(expectedHttpCode); - - return statuses; -}; - export const getCase = async ({ supertest, caseId, 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 e6d3b4c467f6d..3b510281084f2 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 @@ -7,51 +7,29 @@ import { getCaseFindUserActionsUrl, - getCaseUserActionUrl, getCaseUserActionStatsUrl, getCaseUsersUrl, } from '@kbn/cases-plugin/common/api'; import { - CaseUserActionDeprecatedResponse, - CaseUserActionsDeprecatedResponse, CaseUserActionStatsResponse, GetCaseUsersResponse, UserActionFindRequest, UserActionFindResponse, } from '@kbn/cases-plugin/common/types/api'; import type SuperTest from 'supertest'; +import { UserAction } from '@kbn/cases-plugin/common/types/domain'; import { User } from '../authentication/types'; import { superUser } from '../authentication/users'; import { getSpaceUrlPrefix } from './helpers'; import { removeServerGeneratedPropertiesFromObject } from './omit'; -export const removeServerGeneratedPropertiesFromUserAction = ( - attributes: CaseUserActionDeprecatedResponse -) => { - const keysToRemove: Array = ['action_id', 'created_at']; - return removeServerGeneratedPropertiesFromObject< - CaseUserActionDeprecatedResponse, - (typeof keysToRemove)[number] - >(attributes, keysToRemove); -}; - -export const getCaseUserActions = async ({ - supertest, - caseID, - expectedHttpCode = 200, - auth = { user: superUser, space: null }, -}: { - supertest: SuperTest.Agent; - caseID: string; - expectedHttpCode?: number; - auth?: { user: User; space: string | null }; -}): Promise => { - const { body: userActions } = await supertest - .get(`${getSpaceUrlPrefix(auth.space)}${getCaseUserActionUrl(caseID)}`) - .auth(auth.user.username, auth.user.password) - .expect(expectedHttpCode); - return userActions; +export const removeServerGeneratedPropertiesFromUserAction = (attributes: UserAction) => { + const keysToRemove: Array = ['id', 'created_at', 'version']; + return removeServerGeneratedPropertiesFromObject( + attributes, + keysToRemove + ); }; export const findCaseUserActions = async ({ diff --git a/x-pack/test/cases_api_integration/security_and_spaces/tests/common/attachments_framework/external_references.ts b/x-pack/test/cases_api_integration/security_and_spaces/tests/common/attachments_framework/external_references.ts index 8ae71534ce3cd..1bc1e1c5d2596 100644 --- a/x-pack/test/cases_api_integration/security_and_spaces/tests/common/attachments_framework/external_references.ts +++ b/x-pack/test/cases_api_integration/security_and_spaces/tests/common/attachments_framework/external_references.ts @@ -31,7 +31,7 @@ import { updateComment, getSOFromKibanaIndex, getReferenceFromEsResponse, - getCaseUserActions, + findCaseUserActions, } from '../../../../common/lib/api'; // eslint-disable-next-line import/no-default-export @@ -124,7 +124,7 @@ export default ({ getService }: FtrProviderContext): void => { params: postExternalReferenceSOReq, }); - const userActions = await getCaseUserActions({ supertest, caseID: postedCase.id }); + const { userActions } = await findCaseUserActions({ supertest, caseID: postedCase.id }); const commentUserAction = userActions[1]; expect(commentUserAction.type).to.eql('comment'); @@ -178,13 +178,13 @@ export default ({ getService }: FtrProviderContext): void => { params: postExternalReferenceSOReq, }); - const userActions = await getCaseUserActions({ supertest, caseID: postedCase.id }); + const { userActions } = await findCaseUserActions({ supertest, caseID: postedCase.id }); const createCommentUserAction = userActions[1]; const esResponse = await getSOFromKibanaIndex({ es, soType: CASE_USER_ACTION_SAVED_OBJECT, - soId: createCommentUserAction.action_id, + soId: createCommentUserAction.id, }); const commentOnES = esResponse.body._source?.[CASE_USER_ACTION_SAVED_OBJECT]?.payload.comment; @@ -242,7 +242,7 @@ export default ({ getService }: FtrProviderContext): void => { params: postExternalReferenceESReq, }); - const userActions = await getCaseUserActions({ supertest, caseID: postedCase.id }); + const { userActions } = await findCaseUserActions({ supertest, caseID: postedCase.id }); const createCommentUserAction = userActions.find( (userAction) => userAction.type === UserActionTypes.comment ); @@ -250,7 +250,7 @@ export default ({ getService }: FtrProviderContext): void => { const esResponse = await getSOFromKibanaIndex({ es, soType: CASE_USER_ACTION_SAVED_OBJECT, - soId: createCommentUserAction!.action_id, + soId: createCommentUserAction!.id, }); const commentOnES = esResponse.body._source?.[CASE_USER_ACTION_SAVED_OBJECT]?.payload.comment; diff --git a/x-pack/test/cases_api_integration/security_and_spaces/tests/common/attachments_framework/persistable_state.ts b/x-pack/test/cases_api_integration/security_and_spaces/tests/common/attachments_framework/persistable_state.ts index 24d9cc5132c64..6aa22fae77c85 100644 --- a/x-pack/test/cases_api_integration/security_and_spaces/tests/common/attachments_framework/persistable_state.ts +++ b/x-pack/test/cases_api_integration/security_and_spaces/tests/common/attachments_framework/persistable_state.ts @@ -29,7 +29,7 @@ import { getReferenceFromEsResponse, bulkCreateAttachments, updateComment, - getCaseUserActions, + findCaseUserActions, } from '../../../../common/lib/api'; // eslint-disable-next-line import/no-default-export @@ -74,7 +74,7 @@ export default ({ getService }: FtrProviderContext): void => { params: persistableStateAttachment, }); - const userActions = await getCaseUserActions({ supertest, caseID: postedCase.id }); + const { userActions } = await findCaseUserActions({ supertest, caseID: postedCase.id }); const commentUserAction = userActions[1]; expect(commentUserAction.type).to.eql('comment'); @@ -123,13 +123,13 @@ export default ({ getService }: FtrProviderContext): void => { params: persistableStateAttachment, }); - const userActions = await getCaseUserActions({ supertest, caseID: postedCase.id }); + const { userActions } = await findCaseUserActions({ supertest, caseID: postedCase.id }); const createCommentUserAction = userActions[1]; const esResponse = await getSOFromKibanaIndex({ es, soType: CASE_USER_ACTION_SAVED_OBJECT, - soId: createCommentUserAction.action_id, + soId: createCommentUserAction.id, }); const commentOnES = 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 c7b4d9c077045..5c7df684c8c8c 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 @@ -14,7 +14,7 @@ import { User } from '../../../../common/lib/authentication/types'; import { defaultUser, getPostCaseRequest, postCaseResp } from '../../../../common/lib/mock'; import { deleteAllCaseItems, - getCaseUserActions, + findCaseUserActions, getSpaceUrlPrefix, removeServerGeneratedPropertiesFromCase, removeServerGeneratedPropertiesFromUserAction, @@ -168,12 +168,12 @@ export default ({ getService }: FtrProviderContext): void => { const firstCase = createdCases.cases[0]; const secondCase = createdCases.cases[1]; - const firstCaseUserActions = await getCaseUserActions({ + const { userActions: firstCaseUserActions } = await findCaseUserActions({ supertest, caseID: firstCase.id, }); - const secondCaseUserActions = await getCaseUserActions({ + const { userActions: secondCaseUserActions } = await findCaseUserActions({ supertest, caseID: secondCase.id, }); @@ -193,7 +193,6 @@ export default ({ getService }: FtrProviderContext): void => { action: 'create', type: 'create_case', created_by: defaultUser, - case_id: firstCase.id, comment_id: null, owner: 'securitySolutionFixture', payload: { @@ -215,7 +214,6 @@ export default ({ getService }: FtrProviderContext): void => { action: 'create', type: 'create_case', created_by: defaultUser, - case_id: secondCase.id, comment_id: null, owner: 'securitySolutionFixture', payload: { 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 d38af59f57d16..4ab946b50a737 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 @@ -29,7 +29,7 @@ import { getComment, getCase, superUserSpace1Auth, - getCaseUserActions, + findCaseUserActions, deleteAllCaseItems, createAndUploadFile, deleteAllFiles, @@ -100,11 +100,17 @@ export default ({ getService }: FtrProviderContext): void => { await deleteCases({ supertest, caseIDs: [case1.id, case2.id] }); - const userActionsCase1 = await getCaseUserActions({ supertest, caseID: case1.id }); - expect(userActionsCase1.length).to.be(0); + await findCaseUserActions({ + supertest, + caseID: case1.id, + expectedHttpCode: 404, + }); - const userActionsCase2 = await getCaseUserActions({ supertest, caseID: case2.id }); - expect(userActionsCase2.length).to.be(0); + await findCaseUserActions({ + supertest, + caseID: case2.id, + expectedHttpCode: 404, + }); }); it(`should delete a case's comments and user actions when that case gets deleted`, async () => { @@ -131,15 +137,13 @@ export default ({ getService }: FtrProviderContext): void => { expectedHttpCode: 404, }); - const userActions = await getCaseUserActions({ supertest, caseID: postedCase.id }); - expect(userActions.length).to.be(0); + await findCaseUserActions({ supertest, caseID: postedCase.id, expectedHttpCode: 404 }); }); it('should delete all user actions when deleting a case', async () => { const postedCase = await createCase(supertest, getPostCaseRequest()); await deleteCases({ supertest, caseIDs: [postedCase.id] }); - const userActions = await getCaseUserActions({ supertest, caseID: postedCase.id }); - expect(userActions.length).to.be(0); + await findCaseUserActions({ supertest, caseID: postedCase.id, expectedHttpCode: 404 }); }); it('unhappy path - 404s when case is not there', async () => { 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 a8b81c48b4b3b..13241eda9d89e 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 @@ -38,7 +38,7 @@ import { createCase, createComment, findCases, - getCaseUserActions, + findCaseUserActions, findAttachments, } from '../../../../common/lib/api'; import { getPostCaseRequest, postCommentUserReq } from '../../../../common/lib/mock'; @@ -113,7 +113,7 @@ export default ({ getService }: FtrProviderContext): void => { const comment = commentsResponse.comments[0] as unknown as UserCommentAttachmentAttributes; expect(comment.comment).to.eql('A comment for my case'); - const userActions = await getCaseUserActions({ + const { userActions } = await findCaseUserActions({ supertest: supertestService, caseID: findResponse.cases[0].id, }); @@ -148,7 +148,7 @@ export default ({ getService }: FtrProviderContext): void => { await expectImportToHaveOneCase(supertestService); - const userActions = await getCaseUserActions({ + const { userActions } = await findCaseUserActions({ supertest: supertestService, caseID: 'afeefae0-5cea-11ec-a615-15461784e410', }); diff --git a/x-pack/test/cases_api_integration/security_and_spaces/tests/common/cases/patch_cases.ts b/x-pack/test/cases_api_integration/security_and_spaces/tests/common/cases/patch_cases.ts index 1c3640626436a..f9c429a551d73 100644 --- a/x-pack/test/cases_api_integration/security_and_spaces/tests/common/cases/patch_cases.ts +++ b/x-pack/test/cases_api_integration/security_and_spaces/tests/common/cases/patch_cases.ts @@ -38,7 +38,7 @@ import { superUserSpace1Auth, delay, calculateDuration, - getCaseUserActions, + findCaseUserActions, removeServerGeneratedPropertiesFromUserAction, createConfiguration, getConfigurationRequest, @@ -138,7 +138,7 @@ export default ({ getService }: FtrProviderContext): void => { }, }); - const userActions = await getCaseUserActions({ supertest, caseID: postedCase.id }); + const { userActions } = await findCaseUserActions({ supertest, caseID: postedCase.id }); const statusUserAction = removeServerGeneratedPropertiesFromUserAction(userActions[1]); const data = removeServerGeneratedPropertiesFromCase(patchedCases[0]); const { duration, ...dataWithoutDuration } = data; @@ -156,7 +156,6 @@ export default ({ getService }: FtrProviderContext): void => { action: 'update', created_by: defaultUser, payload: { status: CaseStatuses.closed }, - case_id: postedCase.id, comment_id: null, owner: 'securitySolutionFixture', }); @@ -177,7 +176,7 @@ export default ({ getService }: FtrProviderContext): void => { }, }); - const userActions = await getCaseUserActions({ supertest, caseID: postedCase.id }); + const { userActions } = await findCaseUserActions({ supertest, caseID: postedCase.id }); const statusUserAction = removeServerGeneratedPropertiesFromUserAction(userActions[1]); const data = removeServerGeneratedPropertiesFromCase(patchedCases[0]); @@ -192,7 +191,6 @@ export default ({ getService }: FtrProviderContext): void => { action: 'update', created_by: defaultUser, payload: { status: CaseStatuses['in-progress'] }, - case_id: postedCase.id, comment_id: null, owner: 'securitySolutionFixture', }); diff --git a/x-pack/test/cases_api_integration/security_and_spaces/tests/common/cases/post_case.ts b/x-pack/test/cases_api_integration/security_and_spaces/tests/common/cases/post_case.ts index ede6905352f4e..df544fce5bf5a 100644 --- a/x-pack/test/cases_api_integration/security_and_spaces/tests/common/cases/post_case.ts +++ b/x-pack/test/cases_api_integration/security_and_spaces/tests/common/cases/post_case.ts @@ -19,7 +19,7 @@ import { deleteAllCaseItems, createCase, removeServerGeneratedPropertiesFromCase, - getCaseUserActions, + findCaseUserActions, removeServerGeneratedPropertiesFromUserAction, createConfiguration, getConfigurationRequest, @@ -140,14 +140,13 @@ export default ({ getService }: FtrProviderContext): void => { it('should create a user action when creating a case', async () => { const postedCase = await createCase(supertest, getPostCaseRequest()); - const userActions = await getCaseUserActions({ supertest, caseID: postedCase.id }); + const { userActions } = await findCaseUserActions({ supertest, caseID: postedCase.id }); const creationUserAction = removeServerGeneratedPropertiesFromUserAction(userActions[0]); expect(creationUserAction).to.eql({ action: 'create', type: 'create_case', created_by: defaultUser, - case_id: postedCase.id, comment_id: null, owner: 'securitySolutionFixture', payload: { diff --git a/x-pack/test/cases_api_integration/security_and_spaces/tests/common/cases/status/get_status.ts b/x-pack/test/cases_api_integration/security_and_spaces/tests/common/cases/status/get_status.ts deleted file mode 100644 index 5a919029ca0d7..0000000000000 --- a/x-pack/test/cases_api_integration/security_and_spaces/tests/common/cases/status/get_status.ts +++ /dev/null @@ -1,295 +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 expect from '@kbn/expect'; -import { CaseStatuses } from '@kbn/cases-plugin/common/types/domain'; -import { CASE_STATUS_URL } from '@kbn/cases-plugin/common/constants'; -import { FtrProviderContext } from '../../../../../common/ftr_provider_context'; - -import { getPostCaseRequest, postCaseReq } from '../../../../../common/lib/mock'; -import { - createCase, - updateCase, - getAllCasesStatuses, - deleteAllCaseItems, - superUserSpace1Auth, - extractWarningValueFromWarningHeader, -} from '../../../../../common/lib/api'; -import { - globalRead, - noKibanaPrivileges, - obsOnlyRead, - obsSecRead, - secOnly, - secOnlyRead, - superUser, -} from '../../../../../common/lib/authentication/users'; -import { assertWarningHeader } from '../../../../../common/lib/validation'; - -// eslint-disable-next-line import/no-default-export -export default ({ getService }: FtrProviderContext): void => { - const supertest = getService('supertest'); - const es = getService('es'); - const kibanaServer = getService('kibanaServer'); - - describe('get_status', () => { - it('should return case statuses', async () => { - const [, inProgressCase, postedCase] = await Promise.all([ - createCase(supertest, postCaseReq), - createCase(supertest, postCaseReq), - createCase(supertest, postCaseReq), - ]); - - await updateCase({ - supertest, - params: { - cases: [ - { - id: inProgressCase.id, - version: inProgressCase.version, - status: CaseStatuses['in-progress'], - }, - { - id: postedCase.id, - version: postedCase.version, - status: CaseStatuses.closed, - }, - ], - }, - }); - - const statuses = await getAllCasesStatuses({ supertest }); - - expect(statuses).to.eql({ - count_open_cases: 1, - count_closed_cases: 1, - count_in_progress_cases: 1, - }); - }); - - describe('range queries', () => { - before(async () => { - await deleteAllCaseItems(es); - await kibanaServer.importExport.load( - 'x-pack/test/functional/fixtures/kbn_archiver/cases/8.2.0/cases_various_dates.json' - ); - }); - - after(async () => { - await kibanaServer.importExport.unload( - 'x-pack/test/functional/fixtures/kbn_archiver/cases/8.2.0/cases_various_dates.json' - ); - await deleteAllCaseItems(es); - }); - - it('returns all cases without a range filter', async () => { - const statuses = await getAllCasesStatuses({ supertest }); - - expect(statuses).to.eql({ - count_open_cases: 3, - count_closed_cases: 0, - count_in_progress_cases: 0, - }); - }); - - it('respects the range parameters', async () => { - const queries = [ - { expectedCases: 2, query: { from: '2022-03-16' } }, - { expectedCases: 2, query: { to: '2022-03-21' } }, - { expectedCases: 2, query: { from: '2022-03-15', to: '2022-03-21' } }, - ]; - - for (const query of queries) { - const statuses = await getAllCasesStatuses({ supertest, query: query.query }); - expect(statuses).to.eql({ - count_open_cases: query.expectedCases, - count_closed_cases: 0, - count_in_progress_cases: 0, - }); - } - }); - - it('escapes correctly', async () => { - const statuses = await getAllCasesStatuses({ - supertest, - query: { from: '2022-03-15T10:16:56.252Z', to: '2022-03-20T10:16:56.252' }, - }); - - expect(statuses).to.eql({ - count_open_cases: 2, - count_closed_cases: 0, - count_in_progress_cases: 0, - }); - }); - }); - - describe('rbac', () => { - afterEach(async () => { - await deleteAllCaseItems(es); - }); - - const supertestWithoutAuth = getService('supertestWithoutAuth'); - - it('should return the correct status stats', async () => { - /** - * Owner: Sec - * open: 0, in-prog: 1, closed: 1 - * Owner: Obs - * open: 1, in-prog: 1 - */ - const [inProgressSec, closedSec, , inProgressObs] = await Promise.all([ - createCase(supertestWithoutAuth, getPostCaseRequest(), 200, { - user: superUser, - space: 'space1', - }), - createCase(supertestWithoutAuth, getPostCaseRequest(), 200, { - user: superUser, - space: 'space1', - }), - createCase( - supertestWithoutAuth, - getPostCaseRequest({ owner: 'observabilityFixture' }), - 200, - superUserSpace1Auth - ), - createCase( - supertestWithoutAuth, - getPostCaseRequest({ owner: 'observabilityFixture' }), - 200, - superUserSpace1Auth - ), - ]); - - await updateCase({ - supertest: supertestWithoutAuth, - params: { - cases: [ - { - id: inProgressSec.id, - version: inProgressSec.version, - status: CaseStatuses['in-progress'], - }, - { - id: closedSec.id, - version: closedSec.version, - status: CaseStatuses.closed, - }, - { - id: inProgressObs.id, - version: inProgressObs.version, - status: CaseStatuses['in-progress'], - }, - ], - }, - auth: superUserSpace1Auth, - }); - - for (const scenario of [ - { user: globalRead, stats: { open: 1, inProgress: 2, closed: 1 } }, - { user: superUser, stats: { open: 1, inProgress: 2, closed: 1 } }, - { user: secOnlyRead, stats: { open: 0, inProgress: 1, closed: 1 } }, - { user: obsOnlyRead, stats: { open: 1, inProgress: 1, closed: 0 } }, - { user: obsSecRead, stats: { open: 1, inProgress: 2, closed: 1 } }, - { - user: obsSecRead, - stats: { open: 1, inProgress: 1, closed: 0 }, - owner: 'observabilityFixture', - }, - { - user: obsSecRead, - stats: { open: 1, inProgress: 2, closed: 1 }, - owner: ['observabilityFixture', 'securitySolutionFixture'], - }, - ]) { - const statuses = await getAllCasesStatuses({ - supertest: supertestWithoutAuth, - auth: { user: scenario.user, space: 'space1' }, - query: { - owner: scenario.owner, - }, - }); - - expect(statuses).to.eql({ - count_open_cases: scenario.stats.open, - count_closed_cases: scenario.stats.closed, - count_in_progress_cases: scenario.stats.inProgress, - }); - } - }); - - for (const scenario of [ - { user: noKibanaPrivileges, space: 'space1' }, - { user: secOnly, space: 'space2' }, - ]) { - it(`should return a 403 when retrieving the statuses when the user ${ - scenario.user.username - } with role(s) ${scenario.user.roles.join()} and space ${scenario.space}`, async () => { - await createCase(supertestWithoutAuth, getPostCaseRequest(), 200, { - user: superUser, - space: scenario.space, - }); - - await getAllCasesStatuses({ - supertest: supertestWithoutAuth, - auth: { user: scenario.user, space: scenario.space }, - expectedHttpCode: 403, - }); - }); - } - - describe('range queries', () => { - before(async () => { - await kibanaServer.importExport.load( - 'x-pack/test/functional/fixtures/kbn_archiver/cases/8.2.0/cases_various_dates.json', - { space: 'space1' } - ); - }); - - after(async () => { - await kibanaServer.importExport.unload( - 'x-pack/test/functional/fixtures/kbn_archiver/cases/8.2.0/cases_various_dates.json', - { space: 'space1' } - ); - await deleteAllCaseItems(es); - }); - - it('should respect the owner filter when using range queries', async () => { - const res = await getAllCasesStatuses({ - supertest: supertestWithoutAuth, - query: { - from: '2022-03-15', - to: '2022-03-21', - }, - auth: { - user: secOnly, - space: 'space1', - }, - }); - - expect(res).to.eql({ - count_open_cases: 1, - count_closed_cases: 0, - count_in_progress_cases: 0, - }); - }); - }); - }); - - describe('deprecations', () => { - it('should return a warning header', async () => { - await createCase(supertest, postCaseReq); - const res = await supertest.get(CASE_STATUS_URL).expect(200); - const warningHeader = res.header.warning; - - assertWarningHeader(warningHeader); - - const warningValue = extractWarningValueFromWarningHeader(warningHeader); - expect(warningValue).to.be('Deprecated endpoint'); - }); - }); - }); -}; diff --git a/x-pack/test/cases_api_integration/security_and_spaces/tests/common/comments/post_comment.ts b/x-pack/test/cases_api_integration/security_and_spaces/tests/common/comments/post_comment.ts index a9689575fb524..f68f9c7e229b8 100644 --- a/x-pack/test/cases_api_integration/security_and_spaces/tests/common/comments/post_comment.ts +++ b/x-pack/test/cases_api_integration/security_and_spaces/tests/common/comments/post_comment.ts @@ -40,7 +40,7 @@ import { removeServerGeneratedPropertiesFromSavedObject, superUserSpace1Auth, updateCase, - getCaseUserActions, + findCaseUserActions, removeServerGeneratedPropertiesFromUserAction, getAllComments, bulkCreateAttachments, @@ -148,7 +148,7 @@ export default ({ getService }: FtrProviderContext): void => { caseId: postedCase.id, params: postCommentUserReq, }); - const userActions = await getCaseUserActions({ supertest, caseID: postedCase.id }); + const { userActions } = await findCaseUserActions({ supertest, caseID: postedCase.id }); const commentUserAction = removeServerGeneratedPropertiesFromUserAction(userActions[1]); expect(commentUserAction).to.eql({ @@ -162,7 +162,6 @@ export default ({ getService }: FtrProviderContext): void => { owner: 'securitySolutionFixture', }, }, - case_id: postedCase.id, comment_id: patchedCase.comments![0].id, owner: 'securitySolutionFixture', }); diff --git a/x-pack/test/cases_api_integration/security_and_spaces/tests/common/index.ts b/x-pack/test/cases_api_integration/security_and_spaces/tests/common/index.ts index 74cb02d3ebfc8..0ea40d6c70f45 100644 --- a/x-pack/test/cases_api_integration/security_and_spaces/tests/common/index.ts +++ b/x-pack/test/cases_api_integration/security_and_spaces/tests/common/index.ts @@ -31,10 +31,8 @@ export default ({ loadTestFile }: FtrProviderContext): void => { loadTestFile(require.resolve('./cases/post_case')); loadTestFile(require.resolve('./cases/resolve_case')); loadTestFile(require.resolve('./cases/reporters/get_reporters')); - loadTestFile(require.resolve('./cases/status/get_status')); loadTestFile(require.resolve('./cases/tags/get_tags')); loadTestFile(require.resolve('./cases/categories/get_categories')); - loadTestFile(require.resolve('./user_actions/get_all_user_actions')); loadTestFile(require.resolve('./user_actions/find_user_actions')); loadTestFile(require.resolve('./user_actions/get_user_action_stats')); loadTestFile(require.resolve('./configure/get_configure')); diff --git a/x-pack/test/cases_api_integration/security_and_spaces/tests/common/internal/bulk_create_attachments.ts b/x-pack/test/cases_api_integration/security_and_spaces/tests/common/internal/bulk_create_attachments.ts index 7a2cce01af0dd..b5f5639e62c3a 100644 --- a/x-pack/test/cases_api_integration/security_and_spaces/tests/common/internal/bulk_create_attachments.ts +++ b/x-pack/test/cases_api_integration/security_and_spaces/tests/common/internal/bulk_create_attachments.ts @@ -37,7 +37,7 @@ import { createCaseAndBulkCreateAttachments, bulkCreateAttachments, updateCase, - getCaseUserActions, + findCaseUserActions, removeServerGeneratedPropertiesFromUserAction, createAndUploadFile, deleteAllFiles, @@ -148,7 +148,7 @@ export default ({ getService }: FtrProviderContext): void => { supertest, }); - const userActions = await getCaseUserActions({ supertest, caseID: theCase.id }); + const { userActions } = await findCaseUserActions({ supertest, caseID: theCase.id }); userActions.slice(1).forEach((userAction, index) => { const userActionWithoutServerGeneratedAttributes = @@ -163,7 +163,6 @@ export default ({ getService }: FtrProviderContext): void => { ...attachments[index], }, }, - case_id: theCase.id, comment_id: theCase.comments?.find((comment) => comment.id === userAction.comment_id) ?.id, owner: 'securitySolutionFixture', diff --git a/x-pack/test/cases_api_integration/security_and_spaces/tests/common/internal/find_user_actions.ts b/x-pack/test/cases_api_integration/security_and_spaces/tests/common/internal/find_user_actions.ts index f4926eda9ac9e..3eab46e84951c 100644 --- a/x-pack/test/cases_api_integration/security_and_spaces/tests/common/internal/find_user_actions.ts +++ b/x-pack/test/cases_api_integration/security_and_spaces/tests/common/internal/find_user_actions.ts @@ -42,7 +42,6 @@ import { createComment, bulkCreateAttachments, findInternalCaseUserActions, - getCaseUserActions, updateComment, } from '../../../../common/lib/api'; @@ -58,11 +57,9 @@ export default ({ getService }: FtrProviderContext): void => { await deleteAllCaseItems(es); }); - it('returns the id and version fields but not action_id', async () => { + it('returns the id and version fields', async () => { const theCase = await createCase(supertest, getPostCaseRequest()); - const allUserActions = await getCaseUserActions({ supertest, caseID: theCase.id }); - const response = await findInternalCaseUserActions({ caseID: theCase.id, supertest, @@ -70,10 +67,7 @@ export default ({ getService }: FtrProviderContext): void => { expect(response.userActions.length).to.be(1); expect(response.userActions[0].id).not.to.be(undefined); - expect(response.userActions[0].id).to.eql(allUserActions[0].action_id); expect(response.userActions[0].version).not.to.be(undefined); - expect(response.userActions[0]).not.to.have.property('action_id'); - expect(response.userActions[0]).not.to.have.property('case_id'); expect(response.latestAttachments.length).to.be(0); }); diff --git a/x-pack/test/cases_api_integration/security_and_spaces/tests/common/user_actions/find_user_actions.ts b/x-pack/test/cases_api_integration/security_and_spaces/tests/common/user_actions/find_user_actions.ts index 9b160116b1350..06391ae365989 100644 --- a/x-pack/test/cases_api_integration/security_and_spaces/tests/common/user_actions/find_user_actions.ts +++ b/x-pack/test/cases_api_integration/security_and_spaces/tests/common/user_actions/find_user_actions.ts @@ -37,7 +37,6 @@ import { createComment, bulkCreateAttachments, findCaseUserActions, - getCaseUserActions, } from '../../../../common/lib/api'; import { FtrProviderContext } from '../../../../common/ftr_provider_context'; @@ -52,11 +51,9 @@ export default ({ getService }: FtrProviderContext): void => { await deleteAllCaseItems(es); }); - it('returns the id and version fields but not action_id', async () => { + it('returns the id and version fields', async () => { const theCase = await createCase(supertest, getPostCaseRequest()); - const allUserActions = await getCaseUserActions({ supertest, caseID: theCase.id }); - const response = await findCaseUserActions({ caseID: theCase.id, supertest, @@ -64,10 +61,7 @@ export default ({ getService }: FtrProviderContext): void => { expect(response.userActions.length).to.be(1); expect(response.userActions[0].id).not.to.be(undefined); - expect(response.userActions[0].id).to.eql(allUserActions[0].action_id); expect(response.userActions[0].version).not.to.be(undefined); - expect(response.userActions[0]).not.to.have.property('action_id'); - expect(response.userActions[0]).not.to.have.property('case_id'); }); describe('default parameters', () => { diff --git a/x-pack/test/cases_api_integration/security_and_spaces/tests/common/user_actions/get_all_user_actions.ts b/x-pack/test/cases_api_integration/security_and_spaces/tests/common/user_actions/get_all_user_actions.ts deleted file mode 100644 index 6c524e4320669..0000000000000 --- a/x-pack/test/cases_api_integration/security_and_spaces/tests/common/user_actions/get_all_user_actions.ts +++ /dev/null @@ -1,543 +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 expect from '@kbn/expect'; - -import { - Case, - CaseSeverity, - CaseStatuses, - UserCommentAttachmentPayload, - AttachmentType, - CreateCaseUserAction, - ConnectorTypes, - CustomFieldTypes, - CaseCustomFields, -} from '@kbn/cases-plugin/common/types/domain'; -import { getCaseUserActionUrl } from '@kbn/cases-plugin/common/api'; -import { FtrProviderContext } from '../../../../common/ftr_provider_context'; -import { postCaseReq, postCommentUserReq, getPostCaseRequest } from '../../../../common/lib/mock'; -import { - deleteAllCaseItems, - createCase, - updateCase, - superUserSpace1Auth, - deleteCases, - createComment, - updateComment, - deleteComment, - extractWarningValueFromWarningHeader, - getCaseUserActions, - createConfiguration, - getConfigurationRequest, -} from '../../../../common/lib/api'; -import { - globalRead, - noKibanaPrivileges, - obsSec, - obsSecRead, - secOnly, - secOnlyRead, - superUser, -} from '../../../../common/lib/authentication/users'; -import { assertWarningHeader } from '../../../../common/lib/validation'; - -// eslint-disable-next-line import/no-default-export -export default ({ getService }: FtrProviderContext): void => { - const supertest = getService('supertest'); - const es = getService('es'); - - describe('get_all_user_actions', () => { - afterEach(async () => { - await deleteAllCaseItems(es); - }); - - it('populates the action_id', async () => { - const theCase = await createCase(supertest, postCaseReq); - const userActions = await getCaseUserActions({ supertest, caseID: theCase.id }); - - expect(userActions.length).to.be(1); - expect(userActions[0].action_id).not.to.be(undefined); - expect(userActions[0]).not.to.have.property('id'); - }); - - it('populates the case_id', async () => { - const theCase = await createCase(supertest, postCaseReq); - const userActions = await getCaseUserActions({ supertest, caseID: theCase.id }); - - expect(userActions.length).to.be(1); - expect(userActions[0].case_id).not.to.be(undefined); - }); - - it('creates a create case user action when a case is created', async () => { - const theCase = await createCase(supertest, postCaseReq); - const userActions = await getCaseUserActions({ supertest, caseID: theCase.id }); - const createCaseUserAction = userActions[0] as unknown as CreateCaseUserAction; - - expect(userActions.length).to.eql(1); - expect(createCaseUserAction.action).to.eql('create'); - expect(createCaseUserAction.type).to.eql('create_case'); - expect(createCaseUserAction.payload.description).to.eql(postCaseReq.description); - expect(createCaseUserAction.payload.status).to.eql('open'); - expect(createCaseUserAction.payload.tags).to.eql(postCaseReq.tags); - expect(createCaseUserAction.payload.title).to.eql(postCaseReq.title); - expect(createCaseUserAction.payload.settings).to.eql(postCaseReq.settings); - expect(createCaseUserAction.payload.owner).to.eql(postCaseReq.owner); - expect(createCaseUserAction.payload.connector).to.eql(postCaseReq.connector); - expect(createCaseUserAction.payload.assignees).to.eql(postCaseReq.assignees); - expect(createCaseUserAction.payload.severity).to.eql(postCaseReq.severity); - expect(createCaseUserAction.payload.category).to.eql(null); - expect(createCaseUserAction.payload.customFields).to.eql([]); - }); - - it('deletes all user actions when a case is deleted', async () => { - const theCase = await createCase(supertest, postCaseReq); - await deleteCases({ supertest, caseIDs: [theCase.id] }); - const userActions = await getCaseUserActions({ supertest, caseID: theCase.id }); - - expect(userActions.length).to.be(0); - }); - - it('creates a status update user action when changing the status', async () => { - const theCase = await createCase(supertest, postCaseReq); - await updateCase({ - supertest, - params: { - cases: [ - { - id: theCase.id, - version: theCase.version, - status: CaseStatuses.closed, - }, - ], - }, - }); - - const userActions = await getCaseUserActions({ supertest, caseID: theCase.id }); - const statusUserAction = userActions[1]; - - expect(userActions.length).to.eql(2); - expect(statusUserAction.type).to.eql('status'); - expect(statusUserAction.action).to.eql('update'); - expect(statusUserAction.payload).to.eql({ status: 'closed' }); - }); - - it('creates a severity update user action when changing the severity', async () => { - const theCase = await createCase(supertest, postCaseReq); - await updateCase({ - supertest, - params: { - cases: [ - { - id: theCase.id, - version: theCase.version, - severity: CaseSeverity.HIGH, - }, - ], - }, - }); - - const userActions = await getCaseUserActions({ supertest, caseID: theCase.id }); - const statusUserAction = userActions[1]; - - expect(userActions.length).to.eql(2); - expect(statusUserAction.type).to.eql('severity'); - expect(statusUserAction.action).to.eql('update'); - expect(statusUserAction.payload).to.eql({ severity: 'high' }); - }); - - it('creates a connector update user action', async () => { - const newConnector = { - id: '123', - name: 'Connector', - type: ConnectorTypes.jira as const, - fields: { issueType: 'Task', priority: 'High', parent: null }, - }; - - const theCase = await createCase(supertest, postCaseReq); - await updateCase({ - supertest, - params: { - cases: [ - { - id: theCase.id, - version: theCase.version, - connector: newConnector, - }, - ], - }, - }); - - const userActions = await getCaseUserActions({ supertest, caseID: theCase.id }); - const connectorUserAction = userActions[1]; - - expect(userActions.length).to.eql(2); - expect(connectorUserAction.type).to.eql('connector'); - expect(connectorUserAction.action).to.eql('update'); - expect(connectorUserAction.payload).to.eql({ - connector: { - id: '123', - name: 'Connector', - type: '.jira', - fields: { issueType: 'Task', priority: 'High', parent: null }, - }, - }); - }); - - it('creates an add and delete tag user action', async () => { - const theCase = await createCase(supertest, postCaseReq); - await updateCase({ - supertest, - params: { - cases: [ - { - id: theCase.id, - version: theCase.version, - tags: ['cool', 'neat'], - }, - ], - }, - }); - - const userActions = await getCaseUserActions({ supertest, caseID: theCase.id }); - const addTagsUserAction = userActions[1]; - const deleteTagsUserAction = userActions[2]; - - expect(userActions.length).to.eql(3); - expect(addTagsUserAction.type).to.eql('tags'); - expect(addTagsUserAction.action).to.eql('add'); - expect(addTagsUserAction.payload).to.eql({ tags: ['cool', 'neat'] }); - expect(deleteTagsUserAction.type).to.eql('tags'); - expect(deleteTagsUserAction.action).to.eql('delete'); - expect(deleteTagsUserAction.payload).to.eql({ tags: ['defacement'] }); - }); - - it('creates an update title user action', async () => { - const newTitle = 'Such a great title'; - const theCase = await createCase(supertest, postCaseReq); - - await updateCase({ - supertest, - params: { - cases: [ - { - id: theCase.id, - version: theCase.version, - title: newTitle, - }, - ], - }, - }); - - const userActions = await getCaseUserActions({ supertest, caseID: theCase.id }); - const titleUserAction = userActions[1]; - - expect(userActions.length).to.eql(2); - expect(titleUserAction.type).to.eql('title'); - expect(titleUserAction.action).to.eql('update'); - expect(titleUserAction.payload).to.eql({ title: newTitle }); - }); - - it('creates a description update user action', async () => { - const newDesc = 'Such a great description'; - const theCase = await createCase(supertest, postCaseReq); - - await updateCase({ - supertest, - params: { - cases: [ - { - id: theCase.id, - version: theCase.version, - description: newDesc, - }, - ], - }, - }); - - const userActions = await getCaseUserActions({ supertest, caseID: theCase.id }); - const descUserAction = userActions[1]; - - expect(userActions.length).to.eql(2); - expect(descUserAction.type).to.eql('description'); - expect(descUserAction.action).to.eql('update'); - expect(descUserAction.payload).to.eql({ description: newDesc }); - }); - - it('creates a create comment user action', async () => { - const theCase = await createCase(supertest, postCaseReq); - - const caseWithComments = await createComment({ - supertest, - caseId: theCase.id, - params: postCommentUserReq, - }); - const userActions = await getCaseUserActions({ supertest, caseID: theCase.id }); - const commentUserAction = userActions[1]; - - expect(userActions.length).to.eql(2); - expect(commentUserAction.type).to.eql('comment'); - expect(commentUserAction.action).to.eql('create'); - expect(commentUserAction.comment_id).to.eql(caseWithComments.comments![0].id); - expect(commentUserAction.payload).to.eql({ comment: postCommentUserReq }); - }); - - it('creates an update comment user action', async () => { - const newComment = 'Well I decided to update my comment. So what? Deal with it.'; - const theCase = await createCase(supertest, postCaseReq); - const caseWithComments = await createComment({ - supertest, - caseId: theCase.id, - params: postCommentUserReq, - }); - - await updateComment({ - supertest, - caseId: theCase.id, - req: { - id: caseWithComments.comments![0].id, - version: caseWithComments.comments![0].version, - comment: newComment, - type: AttachmentType.user, - owner: 'securitySolutionFixture', - }, - }); - - const userActions = await getCaseUserActions({ supertest, caseID: theCase.id }); - const commentUserAction = userActions[2]; - - expect(userActions.length).to.eql(3); - expect(commentUserAction.type).to.eql('comment'); - expect(commentUserAction.action).to.eql('update'); - expect(commentUserAction.comment_id).to.eql(caseWithComments.comments![0].id); - expect(commentUserAction.payload).to.eql({ - comment: { - comment: newComment, - type: AttachmentType.user, - owner: 'securitySolutionFixture', - }, - }); - }); - - it('creates a delete comment user action', async () => { - const theCase = await createCase(supertest, postCaseReq); - const caseWithComments = await createComment({ - supertest, - caseId: theCase.id, - params: postCommentUserReq, - }); - - await deleteComment({ - supertest, - caseId: theCase.id, - commentId: caseWithComments.comments![0].id, - }); - - const userActions = await getCaseUserActions({ supertest, caseID: theCase.id }); - const commentUserAction = userActions[2]; - const { id, version: _, ...restComment } = caseWithComments.comments![0]; - - const castedUserComment = restComment as UserCommentAttachmentPayload; - - expect(userActions.length).to.eql(3); - expect(commentUserAction.type).to.eql('comment'); - expect(commentUserAction.action).to.eql('delete'); - expect(commentUserAction.comment_id).to.eql(id); - - expect(commentUserAction.payload).to.eql({ - comment: { - comment: castedUserComment.comment, - type: castedUserComment.type, - owner: castedUserComment.owner, - }, - }); - }); - - it('creates user actions for custom fields correctly', async () => { - await createConfiguration( - supertest, - getConfigurationRequest({ - overrides: { - customFields: [ - { - key: 'test_custom_field_1', - label: 'text', - type: CustomFieldTypes.TEXT, - required: false, - }, - { - key: 'test_custom_field_2', - label: 'toggle', - type: CustomFieldTypes.TOGGLE, - required: false, - }, - { - key: 'test_custom_field_3', - label: 'text', - type: CustomFieldTypes.TEXT, - required: false, - }, - { - key: 'number_custom_field_4', - label: 'number', - type: CustomFieldTypes.NUMBER, - required: false, - }, - ], - }, - }) - ); - - const customFields: CaseCustomFields = [ - { - key: 'test_custom_field_1', - type: CustomFieldTypes.TEXT, - value: 'this is a text field value', - }, - { - key: 'test_custom_field_2', - type: CustomFieldTypes.TOGGLE, - value: true, - }, - { - key: 'test_custom_field_3', - type: CustomFieldTypes.TEXT, - value: 'this is a text field value 3', - }, - { - key: 'number_custom_field_4', - type: CustomFieldTypes.NUMBER, - value: 123, - }, - ]; - - const theCase = await createCase(supertest, { - ...postCaseReq, - customFields: [customFields[0], customFields[2]], - }); - - await updateCase({ - supertest, - params: { - cases: [ - { - id: theCase.id, - version: theCase.version, - customFields: [ - { - key: 'test_custom_field_1', - type: CustomFieldTypes.TEXT, - value: 'new value', - }, - ], - }, - ], - }, - }); - - const userActions = await getCaseUserActions({ supertest, caseID: theCase.id }); - expect(userActions.length).to.eql(3); - - const createCaseUserAction = userActions[0] as unknown as CreateCaseUserAction; - const updateCustomFieldCaseUserAction = userActions[1]; - const updateCustomFieldCaseUserAction2 = userActions[2]; - - expect(createCaseUserAction.payload.customFields).to.eql([customFields[0], customFields[2]]); - - expect(updateCustomFieldCaseUserAction.type).to.eql('customFields'); - expect(updateCustomFieldCaseUserAction.action).to.eql('update'); - expect(updateCustomFieldCaseUserAction.payload).to.eql({ - customFields: [ - { - key: 'test_custom_field_1', - type: CustomFieldTypes.TEXT, - value: 'new value', - }, - ], - }); - - expect(updateCustomFieldCaseUserAction2.type).to.eql('customFields'); - expect(updateCustomFieldCaseUserAction2.action).to.eql('update'); - expect(updateCustomFieldCaseUserAction2.payload).to.eql({ - customFields: [ - { - key: 'test_custom_field_3', - type: CustomFieldTypes.TEXT, - value: null, - }, - ], - }); - }); - - describe('rbac', () => { - const supertestWithoutAuth = getService('supertestWithoutAuth'); - - let caseInfo: Case; - beforeEach(async () => { - caseInfo = await createCase(supertestWithoutAuth, getPostCaseRequest(), 200, { - user: superUser, - space: 'space1', - }); - - await updateCase({ - supertest: supertestWithoutAuth, - params: { - cases: [ - { - id: caseInfo.id, - version: caseInfo.version, - status: CaseStatuses.closed, - }, - ], - }, - auth: superUserSpace1Auth, - }); - }); - - it('should get the user actions for a case when the user has the correct permissions', async () => { - for (const user of [globalRead, superUser, secOnly, secOnlyRead, obsSec, obsSecRead]) { - const userActions = await getCaseUserActions({ - supertest: supertestWithoutAuth, - caseID: caseInfo.id, - auth: { user, space: 'space1' }, - }); - - expect(userActions.length).to.eql(2); - } - }); - - for (const scenario of [ - { user: noKibanaPrivileges, space: 'space1' }, - { user: secOnly, space: 'space2' }, - ]) { - it(`should 403 when requesting the user actions of a case with user ${ - scenario.user.username - } with role(s) ${scenario.user.roles.join()} and space ${scenario.space}`, async () => { - await getCaseUserActions({ - supertest: supertestWithoutAuth, - caseID: caseInfo.id, - auth: { user: scenario.user, space: scenario.space }, - expectedHttpCode: 403, - }); - }); - } - }); - - describe('deprecations', () => { - it('should return a warning header', async () => { - const theCase = await createCase(supertest, postCaseReq); - const res = await supertest.get(getCaseUserActionUrl(theCase.id)).expect(200); - const warningHeader = res.header.warning; - - assertWarningHeader(warningHeader); - - const warningValue = extractWarningValueFromWarningHeader(warningHeader); - expect(warningValue).to.be('Deprecated endpoint'); - }); - }); - }); -}; diff --git a/x-pack/test/cases_api_integration/security_and_spaces/tests/common/user_actions/migrations.ts b/x-pack/test/cases_api_integration/security_and_spaces/tests/common/user_actions/migrations.ts index 627a3b89eaceb..cf4095280442c 100644 --- a/x-pack/test/cases_api_integration/security_and_spaces/tests/common/user_actions/migrations.ts +++ b/x-pack/test/cases_api_integration/security_and_spaces/tests/common/user_actions/migrations.ts @@ -7,11 +7,10 @@ import expect from '@kbn/expect'; import { SECURITY_SOLUTION_OWNER } from '@kbn/cases-plugin/common/constants'; -import { AttachmentType } from '@kbn/cases-plugin/common/types/domain'; -import { CaseUserActionsDeprecatedResponse } from '@kbn/cases-plugin/common/types/api'; +import { AttachmentType, UserActions } from '@kbn/cases-plugin/common/types/domain'; import { UserActionTypes } from '@kbn/cases-plugin/common/types/domain'; import { FtrProviderContext } from '../../../../../common/ftr_provider_context'; -import { deleteAllCaseItems, getCaseUserActions } from '../../../../common/lib/api'; +import { deleteAllCaseItems, findCaseUserActions } from '../../../../common/lib/api'; // eslint-disable-next-line import/no-default-export export default function createGetTests({ getService }: FtrProviderContext) { @@ -38,16 +37,20 @@ export default function createGetTests({ getService }: FtrProviderContext) { }); it('migrates user actions correctly', async () => { - const userActions = await getCaseUserActions({ + const { userActions } = await findCaseUserActions({ supertest, caseID: CASE_ID, }); - expect(userActions).to.eql([ + const userActionsWithoutVersion = userActions.map((userAction) => { + const { version, ...rest } = userAction; + return rest; + }); + + expect(userActionsWithoutVersion).to.eql([ { action: 'create', - action_id: '70306700-7abd-11eb-9ca6-83ec5acb735f', - case_id: '2ea28c10-7855-11eb-9ca6-83ec5acb735f', + id: '70306700-7abd-11eb-9ca6-83ec5acb735f', comment_id: null, created_at: '2023-05-23T08:06:06.216Z', created_by: { @@ -78,8 +81,7 @@ export default function createGetTests({ getService }: FtrProviderContext) { }, { action: 'create', - action_id: '23332380-f94f-11ed-84eb-d959d286ba88', - case_id: '2ea28c10-7855-11eb-9ca6-83ec5acb735f', + id: '23332380-f94f-11ed-84eb-d959d286ba88', comment_id: null, created_at: '2023-05-23T09:49:40.055Z', created_by: { @@ -99,8 +101,7 @@ export default function createGetTests({ getService }: FtrProviderContext) { }, { action: 'update', - action_id: '29743e50-f94f-11ed-84eb-d959d286ba88', - case_id: '2ea28c10-7855-11eb-9ca6-83ec5acb735f', + id: '29743e50-f94f-11ed-84eb-d959d286ba88', comment_id: null, created_at: '2023-05-23T09:49:50.132Z', created_by: { @@ -116,8 +117,7 @@ export default function createGetTests({ getService }: FtrProviderContext) { }, { action: 'update', - action_id: '2b40e800-f94f-11ed-84eb-d959d286ba88', - case_id: '2ea28c10-7855-11eb-9ca6-83ec5acb735f', + id: '2b40e800-f94f-11ed-84eb-d959d286ba88', comment_id: null, created_at: '2023-05-23T09:49:53.378Z', created_by: { @@ -133,8 +133,7 @@ export default function createGetTests({ getService }: FtrProviderContext) { }, { action: 'add', - action_id: '30a22a20-f94f-11ed-84eb-d959d286ba88', - case_id: '2ea28c10-7855-11eb-9ca6-83ec5acb735f', + id: '30a22a20-f94f-11ed-84eb-d959d286ba88', comment_id: null, created_at: '2023-05-23T09:50:02.565Z', created_by: { @@ -150,8 +149,7 @@ export default function createGetTests({ getService }: FtrProviderContext) { }, { action: 'delete', - action_id: '335451d0-f94f-11ed-84eb-d959d286ba88', - case_id: '2ea28c10-7855-11eb-9ca6-83ec5acb735f', + id: '335451d0-f94f-11ed-84eb-d959d286ba88', comment_id: null, created_at: '2023-05-23T09:50:06.959Z', created_by: { @@ -167,8 +165,7 @@ export default function createGetTests({ getService }: FtrProviderContext) { }, { action: 'update', - action_id: '37837c90-f94f-11ed-84eb-d959d286ba88', - case_id: '2ea28c10-7855-11eb-9ca6-83ec5acb735f', + id: '37837c90-f94f-11ed-84eb-d959d286ba88', comment_id: null, created_at: '2023-05-23T09:50:13.728Z', created_by: { @@ -184,8 +181,7 @@ export default function createGetTests({ getService }: FtrProviderContext) { }, { action: 'update', - action_id: '3c4dfcf0-f94f-11ed-84eb-d959d286ba88', - case_id: '2ea28c10-7855-11eb-9ca6-83ec5acb735f', + id: '3c4dfcf0-f94f-11ed-84eb-d959d286ba88', comment_id: null, created_at: '2023-05-23T09:50:22.092Z', created_by: { @@ -205,8 +201,7 @@ export default function createGetTests({ getService }: FtrProviderContext) { }, { action: 'update', - action_id: '3f49b0c0-f94f-11ed-84eb-d959d286ba88', - case_id: '2ea28c10-7855-11eb-9ca6-83ec5acb735f', + id: '3f49b0c0-f94f-11ed-84eb-d959d286ba88', comment_id: null, created_at: '2023-05-23T09:50:27.117Z', created_by: { @@ -222,8 +217,7 @@ export default function createGetTests({ getService }: FtrProviderContext) { }, { action: 'push_to_service', - action_id: '8b93df50-f94f-11ed-84eb-d959d286ba88', - case_id: '2ea28c10-7855-11eb-9ca6-83ec5acb735f', + id: '8b93df50-f94f-11ed-84eb-d959d286ba88', comment_id: null, created_at: '2023-05-23T09:52:35.744Z', created_by: { @@ -271,7 +265,7 @@ export default function createGetTests({ getService }: FtrProviderContext) { }); it('7.10.0 migrates user actions connector', async () => { - const userActions = await getCaseUserActions({ + const { userActions } = await findCaseUserActions({ supertest, caseID: CASE_ID, }); @@ -290,12 +284,17 @@ export default function createGetTests({ getService }: FtrProviderContext) { }); it('7.10.0 migrates user actions correctly', async () => { - const userActions = await getCaseUserActions({ + const { userActions } = await findCaseUserActions({ supertest, caseID: CASE_ID, }); - expect(userActions).to.eql([ + const userActionsWithoutVersion = userActions.map((userAction) => { + const { version, ...rest } = userAction; + return rest; + }); + + expect(userActionsWithoutVersion).to.eql([ { owner: 'securitySolution', action: 'create', @@ -322,8 +321,7 @@ export default function createGetTests({ getService }: FtrProviderContext) { settings: { syncAlerts: true }, }, type: 'create_case', - action_id: 'e22a7600-017f-11eb-93f8-d161651bf509', - case_id: 'e1900ac0-017f-11eb-93f8-d161651bf509', + id: 'e22a7600-017f-11eb-93f8-d161651bf509', comment_id: null, }, { @@ -344,8 +342,7 @@ export default function createGetTests({ getService }: FtrProviderContext) { }, }, type: 'connector', - action_id: 'a22a7600-017f-11eb-93f8-d161651bf509', - case_id: 'e1900ac0-017f-11eb-93f8-d161651bf509', + id: 'a22a7600-017f-11eb-93f8-d161651bf509', comment_id: null, }, { @@ -365,8 +362,7 @@ export default function createGetTests({ getService }: FtrProviderContext) { }, }, type: 'comment', - action_id: 'db027ec0-1ac7-11eb-b5a3-25ee88122510', - case_id: 'e1900ac0-017f-11eb-93f8-d161651bf509', + id: 'db027ec0-1ac7-11eb-b5a3-25ee88122510', comment_id: 'da677740-1ac7-11eb-b5a3-25ee88122510', }, ]); @@ -385,7 +381,7 @@ export default function createGetTests({ getService }: FtrProviderContext) { }); it('adds the owner field', async () => { - const userActions = await getCaseUserActions({ + const { userActions } = await findCaseUserActions({ supertest, caseID: CASE_ID, }); @@ -397,12 +393,17 @@ export default function createGetTests({ getService }: FtrProviderContext) { }); it('7.13.2 migrates user actions correctly', async () => { - const userActions = await getCaseUserActions({ + const { userActions } = await findCaseUserActions({ supertest, caseID: CASE_ID, }); - expect(userActions).to.eql([ + const userActionsWithoutVersion = userActions.map((userAction) => { + const { version, ...rest } = userAction; + return rest; + }); + + expect(userActionsWithoutVersion).to.eql([ { owner: 'securitySolution', action: 'create', @@ -435,8 +436,7 @@ export default function createGetTests({ getService }: FtrProviderContext) { owner: 'securitySolution', }, type: 'create_case', - action_id: 'e5509250-cf9d-11eb-a603-13e7747d215c', - case_id: 'e49ad6e0-cf9d-11eb-a603-13e7747d215c', + id: 'e5509250-cf9d-11eb-a603-13e7747d215c', comment_id: null, }, { @@ -464,8 +464,7 @@ export default function createGetTests({ getService }: FtrProviderContext) { }, }, type: 'pushed', - action_id: 'e6e0f650-cf9d-11eb-a603-13e7747d215c', - case_id: 'e49ad6e0-cf9d-11eb-a603-13e7747d215c', + id: 'e6e0f650-cf9d-11eb-a603-13e7747d215c', comment_id: null, }, { @@ -485,8 +484,7 @@ export default function createGetTests({ getService }: FtrProviderContext) { }, }, type: 'comment', - action_id: 'eee3be50-cf9d-11eb-a603-13e7747d215c', - case_id: 'e49ad6e0-cf9d-11eb-a603-13e7747d215c', + id: 'eee3be50-cf9d-11eb-a603-13e7747d215c', comment_id: 'ee59cdd0-cf9d-11eb-a603-13e7747d215c', }, ]); @@ -494,8 +492,7 @@ export default function createGetTests({ getService }: FtrProviderContext) { }); describe('7.13 connector id extraction', () => { - let userActions: CaseUserActionsDeprecatedResponse; - + let userActions: UserActions; before(async () => { await esArchiver.load( 'x-pack/test/functional/es_archives/cases/migrations/7.13_user_actions' @@ -509,12 +506,17 @@ export default function createGetTests({ getService }: FtrProviderContext) { }); it('7.13 migrates user actions correctly for case with ID aa8ac630-005e-11ec-91f1-6daf2ab59fb5', async () => { - userActions = await getCaseUserActions({ + const result = await findCaseUserActions({ supertest, caseID: 'aa8ac630-005e-11ec-91f1-6daf2ab59fb5', }); - expect(userActions).to.eql([ + const userActionsWithoutVersion = result.userActions.map((userAction) => { + const { version, ...rest } = userAction; + return rest; + }); + + expect(userActionsWithoutVersion).to.eql([ { owner: 'securitySolution', action: 'create', @@ -543,8 +545,7 @@ export default function createGetTests({ getService }: FtrProviderContext) { owner: 'securitySolution', }, type: 'create_case', - action_id: 'ab43b5f0-005e-11ec-91f1-6daf2ab59fb5', - case_id: 'aa8ac630-005e-11ec-91f1-6daf2ab59fb5', + id: 'ab43b5f0-005e-11ec-91f1-6daf2ab59fb5', comment_id: null, }, { @@ -575,20 +576,23 @@ export default function createGetTests({ getService }: FtrProviderContext) { assignees: [], }, type: 'create_case', - action_id: 'b3094de0-005e-11ec-91f1-6daf2ab59fb5', - case_id: 'aa8ac630-005e-11ec-91f1-6daf2ab59fb5', + id: 'b3094de0-005e-11ec-91f1-6daf2ab59fb5', comment_id: null, }, ]); }); it('7.13 migrates user actions correctly for case with ID e6fa9370-005e-11ec-91f1-6daf2ab59fb5', async () => { - userActions = await getCaseUserActions({ + const result = await findCaseUserActions({ supertest, caseID: 'e6fa9370-005e-11ec-91f1-6daf2ab59fb5', }); + const userActionsWithoutVersion = result.userActions.map((userAction) => { + const { version, ...rest } = userAction; + return rest; + }); - expect(userActions).to.eql([ + expect(userActionsWithoutVersion).to.eql([ { owner: 'securitySolution', action: 'create', @@ -621,8 +625,7 @@ export default function createGetTests({ getService }: FtrProviderContext) { assignees: [], }, type: 'create_case', - action_id: 'e7882d70-005e-11ec-91f1-6daf2ab59fb5', - case_id: 'e6fa9370-005e-11ec-91f1-6daf2ab59fb5', + id: 'e7882d70-005e-11ec-91f1-6daf2ab59fb5', comment_id: null, }, { @@ -650,8 +653,7 @@ export default function createGetTests({ getService }: FtrProviderContext) { }, }, type: 'pushed', - action_id: 'e9471b80-005e-11ec-91f1-6daf2ab59fb5', - case_id: 'e6fa9370-005e-11ec-91f1-6daf2ab59fb5', + id: 'e9471b80-005e-11ec-91f1-6daf2ab59fb5', comment_id: null, }, { @@ -671,8 +673,7 @@ export default function createGetTests({ getService }: FtrProviderContext) { }, }, type: 'comment', - action_id: 'efe9de50-005e-11ec-91f1-6daf2ab59fb5', - case_id: 'e6fa9370-005e-11ec-91f1-6daf2ab59fb5', + id: 'efe9de50-005e-11ec-91f1-6daf2ab59fb5', comment_id: 'ef5f0370-005e-11ec-91f1-6daf2ab59fb5', }, { @@ -697,8 +698,7 @@ export default function createGetTests({ getService }: FtrProviderContext) { }, }, type: 'connector', - action_id: '16cd9e30-005f-11ec-91f1-6daf2ab59fb5', - case_id: 'e6fa9370-005e-11ec-91f1-6daf2ab59fb5', + id: '16cd9e30-005f-11ec-91f1-6daf2ab59fb5', comment_id: null, }, { @@ -726,8 +726,7 @@ export default function createGetTests({ getService }: FtrProviderContext) { }, }, type: 'pushed', - action_id: '1ea33bb0-005f-11ec-91f1-6daf2ab59fb5', - case_id: 'e6fa9370-005e-11ec-91f1-6daf2ab59fb5', + id: '1ea33bb0-005f-11ec-91f1-6daf2ab59fb5', comment_id: null, }, { @@ -747,8 +746,7 @@ export default function createGetTests({ getService }: FtrProviderContext) { }, }, type: 'comment', - action_id: '29c98ad0-005f-11ec-91f1-6daf2ab59fb5', - case_id: 'e6fa9370-005e-11ec-91f1-6daf2ab59fb5', + id: '29c98ad0-005f-11ec-91f1-6daf2ab59fb5', comment_id: '29351300-005f-11ec-91f1-6daf2ab59fb5', }, { @@ -773,8 +771,7 @@ export default function createGetTests({ getService }: FtrProviderContext) { }, }, type: 'connector', - action_id: '2f6e65a0-005f-11ec-91f1-6daf2ab59fb5', - case_id: 'e6fa9370-005e-11ec-91f1-6daf2ab59fb5', + id: '2f6e65a0-005f-11ec-91f1-6daf2ab59fb5', comment_id: null, }, { @@ -802,8 +799,7 @@ export default function createGetTests({ getService }: FtrProviderContext) { }, }, type: 'pushed', - action_id: '32a351e0-005f-11ec-91f1-6daf2ab59fb5', - case_id: 'e6fa9370-005e-11ec-91f1-6daf2ab59fb5', + id: '32a351e0-005f-11ec-91f1-6daf2ab59fb5', comment_id: null, }, ]); @@ -811,10 +807,11 @@ export default function createGetTests({ getService }: FtrProviderContext) { describe('none connector case', () => { it('removes the connector id from the case create user action and sets the ids to null', async () => { - userActions = await getCaseUserActions({ + const result = await findCaseUserActions({ supertest, caseID: 'aa8ac630-005e-11ec-91f1-6daf2ab59fb5', }); + userActions = result.userActions; const userAction = getUserActionById( userActions, @@ -840,10 +837,11 @@ export default function createGetTests({ getService }: FtrProviderContext) { describe('case with many user actions', () => { before(async () => { - userActions = await getCaseUserActions({ + const result = await findCaseUserActions({ supertest, caseID: 'e6fa9370-005e-11ec-91f1-6daf2ab59fb5', }); + userActions = result.userActions; }); it('adds the connector id field for a created case user action', async () => { @@ -908,7 +906,7 @@ export default function createGetTests({ getService }: FtrProviderContext) { }); it('removes the rule information from alert user action', async () => { - const userActions = await getCaseUserActions({ + const { userActions } = await findCaseUserActions({ supertest, caseID: 'e49ad6e0-cf9d-11eb-a603-13e7747d215c', }); @@ -927,7 +925,7 @@ export default function createGetTests({ getService }: FtrProviderContext) { }); it('does not modify non-alert attachments', async () => { - const userActions = await getCaseUserActions({ + const { userActions } = await findCaseUserActions({ supertest, caseID: 'e49ad6e0-cf9d-11eb-a603-13e7747d215c', }); @@ -957,16 +955,20 @@ export default function createGetTests({ getService }: FtrProviderContext) { }); it('migrates the user actions correctly', async () => { - const userActions = await getCaseUserActions({ + const { userActions } = await findCaseUserActions({ supertest, caseID: CASE_ID, }); - expect(userActions).to.eql([ + const userActionsWithoutVersion = userActions.map((userAction) => { + const { version, ...rest } = userAction; + return rest; + }); + + expect(userActionsWithoutVersion).to.eql([ { action: 'create', - action_id: '5275af50-5e7d-11ec-9ee9-cd64f0b77b3c', - case_id: '5257a000-5e7d-11ec-9ee9-cd64f0b77b3c', + id: '5275af50-5e7d-11ec-9ee9-cd64f0b77b3c', comment_id: null, created_at: '2021-12-16T14:34:48.709Z', created_by: { @@ -997,8 +999,7 @@ export default function createGetTests({ getService }: FtrProviderContext) { }, { action: 'create', - action_id: '72e73240-5e7d-11ec-9ee9-cd64f0b77b3c', - case_id: '5257a000-5e7d-11ec-9ee9-cd64f0b77b3c', + id: '72e73240-5e7d-11ec-9ee9-cd64f0b77b3c', comment_id: '72a03e30-5e7d-11ec-9ee9-cd64f0b77b3c', created_at: '2021-12-16T14:35:42.872Z', created_by: { @@ -1018,8 +1019,7 @@ export default function createGetTests({ getService }: FtrProviderContext) { }, { action: 'update', - action_id: '7685b5c0-5e7d-11ec-9ee9-cd64f0b77b3c', - case_id: '5257a000-5e7d-11ec-9ee9-cd64f0b77b3c', + id: '7685b5c0-5e7d-11ec-9ee9-cd64f0b77b3c', comment_id: null, created_at: '2021-12-16T14:35:48.826Z', created_by: { @@ -1035,8 +1035,7 @@ export default function createGetTests({ getService }: FtrProviderContext) { }, { action: 'update', - action_id: '7a2d8810-5e7d-11ec-9ee9-cd64f0b77b3c', - case_id: '5257a000-5e7d-11ec-9ee9-cd64f0b77b3c', + id: '7a2d8810-5e7d-11ec-9ee9-cd64f0b77b3c', comment_id: null, created_at: '2021-12-16T14:35:55.421Z', created_by: { @@ -1052,8 +1051,7 @@ export default function createGetTests({ getService }: FtrProviderContext) { }, { action: 'update', - action_id: '7f942160-5e7d-11ec-9ee9-cd64f0b77b3c', - case_id: '5257a000-5e7d-11ec-9ee9-cd64f0b77b3c', + id: '7f942160-5e7d-11ec-9ee9-cd64f0b77b3c', comment_id: '72a03e30-5e7d-11ec-9ee9-cd64f0b77b3c', created_at: '2021-12-16T14:36:04.120Z', created_by: { @@ -1073,8 +1071,7 @@ export default function createGetTests({ getService }: FtrProviderContext) { }, { action: 'add', - action_id: '8591a380-5e7d-11ec-9ee9-cd64f0b77b3c', - case_id: '5257a000-5e7d-11ec-9ee9-cd64f0b77b3c', + id: '8591a380-5e7d-11ec-9ee9-cd64f0b77b3c', comment_id: null, created_at: '2021-12-16T14:36:13.840Z', created_by: { @@ -1090,8 +1087,7 @@ export default function createGetTests({ getService }: FtrProviderContext) { }, { action: 'delete', - action_id: '8591a381-5e7d-11ec-9ee9-cd64f0b77b3c', - case_id: '5257a000-5e7d-11ec-9ee9-cd64f0b77b3c', + id: '8591a381-5e7d-11ec-9ee9-cd64f0b77b3c', comment_id: null, created_at: '2021-12-16T14:36:13.840Z', created_by: { @@ -1107,8 +1103,7 @@ export default function createGetTests({ getService }: FtrProviderContext) { }, { action: 'update', - action_id: '87fadb50-5e7d-11ec-9ee9-cd64f0b77b3c', - case_id: '5257a000-5e7d-11ec-9ee9-cd64f0b77b3c', + id: '87fadb50-5e7d-11ec-9ee9-cd64f0b77b3c', comment_id: null, created_at: '2021-12-16T14:36:17.764Z', created_by: { @@ -1126,8 +1121,7 @@ export default function createGetTests({ getService }: FtrProviderContext) { }, { action: 'update', - action_id: '89ca4420-5e7d-11ec-9ee9-cd64f0b77b3c', - case_id: '5257a000-5e7d-11ec-9ee9-cd64f0b77b3c', + id: '89ca4420-5e7d-11ec-9ee9-cd64f0b77b3c', comment_id: null, created_at: '2021-12-16T14:36:21.509Z', created_by: { @@ -1143,8 +1137,7 @@ export default function createGetTests({ getService }: FtrProviderContext) { }, { action: 'update', - action_id: '9060aae0-5e7d-11ec-9ee9-cd64f0b77b3c', - case_id: '5257a000-5e7d-11ec-9ee9-cd64f0b77b3c', + id: '9060aae0-5e7d-11ec-9ee9-cd64f0b77b3c', comment_id: null, created_at: '2021-12-16T14:36:32.716Z', created_by: { @@ -1169,8 +1162,7 @@ export default function createGetTests({ getService }: FtrProviderContext) { }, { action: 'push_to_service', - action_id: '988579d0-5e7d-11ec-9ee9-cd64f0b77b3c', - case_id: '5257a000-5e7d-11ec-9ee9-cd64f0b77b3c', + id: '988579d0-5e7d-11ec-9ee9-cd64f0b77b3c', comment_id: null, created_at: '2021-12-16T14:36:46.443Z', created_by: { @@ -1198,8 +1190,7 @@ export default function createGetTests({ getService }: FtrProviderContext) { }, { action: 'update', - action_id: 'bcb76020-5e7d-11ec-9ee9-cd64f0b77b3c', - case_id: '5257a000-5e7d-11ec-9ee9-cd64f0b77b3c', + id: 'bcb76020-5e7d-11ec-9ee9-cd64f0b77b3c', comment_id: null, created_at: '2021-12-16T14:37:46.863Z', created_by: { @@ -1223,8 +1214,7 @@ export default function createGetTests({ getService }: FtrProviderContext) { }, { action: 'push_to_service', - action_id: 'c0338e90-5e7d-11ec-9ee9-cd64f0b77b3c', - case_id: '5257a000-5e7d-11ec-9ee9-cd64f0b77b3c', + id: 'c0338e90-5e7d-11ec-9ee9-cd64f0b77b3c', comment_id: null, created_at: '2021-12-16T14:37:53.016Z', created_by: { @@ -1252,8 +1242,7 @@ export default function createGetTests({ getService }: FtrProviderContext) { }, { action: 'update', - action_id: 'c5b6d7a0-5e7d-11ec-9ee9-cd64f0b77b3c', - case_id: '5257a000-5e7d-11ec-9ee9-cd64f0b77b3c', + id: 'c5b6d7a0-5e7d-11ec-9ee9-cd64f0b77b3c', comment_id: null, created_at: '2021-12-16T14:38:01.895Z', created_by: { @@ -1278,8 +1267,7 @@ export default function createGetTests({ getService }: FtrProviderContext) { }, { action: 'create', - action_id: 'ca8f61c0-5e7d-11ec-9ee9-cd64f0b77b3c', - case_id: '5257a000-5e7d-11ec-9ee9-cd64f0b77b3c', + id: 'ca8f61c0-5e7d-11ec-9ee9-cd64f0b77b3c', comment_id: 'ca1d17f0-5e7d-11ec-9ee9-cd64f0b77b3c', created_at: '2021-12-16T14:38:09.649Z', created_by: { @@ -1320,19 +1308,17 @@ export default function createGetTests({ getService }: FtrProviderContext) { describe('add severity', () => { it('adds the severity field to the create case user action', async () => { - const userActions = await getCaseUserActions({ + const { userActions } = await findCaseUserActions({ supertest, caseID: CASE_ID, }); - const createUserAction = userActions.find( - (userAction) => userAction.action_id === CREATE_UA_ID - ); + const createUserAction = userActions.find((userAction) => userAction.id === CREATE_UA_ID); + const { version, ...createUserActionWithoutVersion } = createUserAction ?? {}; - expect(createUserAction).to.eql({ + expect(createUserActionWithoutVersion).to.eql({ action: 'create', - action_id: '5275af50-5e7d-11ec-9ee9-cd64f0b77b3c', - case_id: '5257a000-5e7d-11ec-9ee9-cd64f0b77b3c', + id: '5275af50-5e7d-11ec-9ee9-cd64f0b77b3c', comment_id: null, created_at: '2021-12-16T14:34:48.709Z', created_by: { @@ -1364,7 +1350,7 @@ export default function createGetTests({ getService }: FtrProviderContext) { }); it('does NOT add the severity field to the other user actions', async () => { - const userActions = await getCaseUserActions({ + const { userActions } = await findCaseUserActions({ supertest, caseID: CASE_ID, }); @@ -1399,19 +1385,17 @@ export default function createGetTests({ getService }: FtrProviderContext) { describe('assignees', () => { it('adds the assignees field to the create case user action', async () => { - const userActions = await getCaseUserActions({ + const { userActions } = await findCaseUserActions({ supertest, caseID: CASE_ID, }); - const createUserAction = userActions.find( - (userAction) => userAction.action_id === CREATE_UA_ID - ); + const createUserAction = userActions.find((userAction) => userAction.id === CREATE_UA_ID); + const { version, ...createUserActionWithoutVersion } = createUserAction ?? {}; - expect(createUserAction).to.eql({ + expect(createUserActionWithoutVersion).to.eql({ action: 'create', - action_id: '5275af50-5e7d-11ec-9ee9-cd64f0b77b3c', - case_id: '5257a000-5e7d-11ec-9ee9-cd64f0b77b3c', + id: '5275af50-5e7d-11ec-9ee9-cd64f0b77b3c', comment_id: null, created_at: '2021-12-16T14:34:48.709Z', created_by: { @@ -1443,7 +1427,7 @@ export default function createGetTests({ getService }: FtrProviderContext) { }); it('does NOT add the assignees field to the other user actions', async () => { - const userActions = await getCaseUserActions({ + const { userActions } = await findCaseUserActions({ supertest, caseID: CASE_ID, }); @@ -1461,6 +1445,6 @@ export default function createGetTests({ getService }: FtrProviderContext) { }); } -function getUserActionById(userActions: CaseUserActionsDeprecatedResponse, id: string): any { - return userActions.find((userAction) => userAction.action_id === id); +function getUserActionById(userActions: UserActions, id: string): any { + return userActions.find((userAction) => userAction.id === id); } diff --git a/x-pack/test/cases_api_integration/security_and_spaces/tests/trial/cases/user_actions/get_all_user_actions.ts b/x-pack/test/cases_api_integration/security_and_spaces/tests/trial/cases/user_actions/get_all_user_actions.ts deleted file mode 100644 index 7e3cdfe00d61b..0000000000000 --- a/x-pack/test/cases_api_integration/security_and_spaces/tests/trial/cases/user_actions/get_all_user_actions.ts +++ /dev/null @@ -1,211 +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 http from 'http'; -import expect from '@kbn/expect'; -import { User } from '@kbn/cases-plugin/common/types/domain'; -import { - PushedUserAction, - UserActionWithDeprecatedResponse, -} from '@kbn/cases-plugin/common/types/domain'; -import { FtrProviderContext } from '../../../../../common/ftr_provider_context'; - -import { defaultUser, getPostCaseRequest } from '../../../../../common/lib/mock'; -import { - createCase, - deleteCasesByESQuery, - deleteCasesUserActions, - deleteComments, - deleteConfiguration, - pushCase, - updateCase, - updateConfiguration, - createCaseWithConnector, - getServiceNowSimulationServer, - getCaseUserActions, -} from '../../../../../common/lib/api'; - -import { ObjectRemover as ActionsRemover } from '../../../../../../alerting_api_integration/common/lib'; -import { setupSuperUserProfile } from '../../../../../common/lib/api/user_profiles'; - -// eslint-disable-next-line import/no-default-export -export default ({ getService }: FtrProviderContext): void => { - const supertest = getService('supertest'); - const es = getService('es'); - const actionsRemover = new ActionsRemover(supertest); - - describe('get_all_user_actions', () => { - let serviceNowSimulatorURL: string = ''; - let serviceNowServer: http.Server; - - before(async () => { - const { server, url } = await getServiceNowSimulationServer(); - serviceNowServer = server; - serviceNowSimulatorURL = url; - }); - - afterEach(async () => { - await deleteCasesByESQuery(es); - await deleteComments(es); - await deleteConfiguration(es); - await deleteCasesUserActions(es); - await actionsRemover.removeAll(); - }); - - after(async () => { - serviceNowServer.close(); - }); - - it('creates a push to service user action', async () => { - const { postedCase, connector } = await createCaseWithConnector({ - supertest, - serviceNowSimulatorURL, - actionsRemover, - }); - - const theCase = await pushCase({ - supertest, - caseId: postedCase.id, - connectorId: connector.id, - }); - - const userActions = await getCaseUserActions({ supertest, caseID: theCase.id }); - const pushUserAction = userActions[1] as UserActionWithDeprecatedResponse; - - expect(userActions.length).to.eql(2); - expect(pushUserAction.type).to.eql('pushed'); - expect(pushUserAction.action).to.eql('push_to_service'); - expect(pushUserAction.created_by).to.eql(defaultUser); - expect(pushUserAction.case_id).to.eql(postedCase.id); - expect(pushUserAction.comment_id).to.eql(null); - expect(pushUserAction.owner).to.eql('securitySolutionFixture'); - expect(pushUserAction.payload.externalService).to.eql({ - pushed_at: theCase.external_service!.pushed_at, - connector_id: connector.id, - connector_name: connector.name, - pushed_by: defaultUser, - external_id: '123', - external_title: 'INC01', - external_url: `${connector.config!.apiUrl}/nav_to.do?uri=incident.do?sys_id=123`, - }); - }); - - it('creates a push to service user action and a status update user action when the case is closed after a push', async () => { - const { postedCase, connector, configuration } = await createCaseWithConnector({ - supertest, - serviceNowSimulatorURL, - actionsRemover, - }); - - await updateConfiguration(supertest, configuration.id, { - closure_type: 'close-by-pushing', - version: configuration.version, - }); - - const theCase = await pushCase({ - supertest, - caseId: postedCase.id, - connectorId: connector.id, - }); - - const userActions = await getCaseUserActions({ supertest, caseID: theCase.id }); - const statusUserAction = userActions[1] as unknown as PushedUserAction; - - expect(userActions.length).to.eql(3); - expect(statusUserAction.type).to.eql('status'); - expect(statusUserAction.action).to.eql('update'); - expect(statusUserAction.payload).to.eql({ status: 'closed' }); - }); - - it('creates an add and delete assignees user action', async () => { - const theCase = await createCase( - supertest, - getPostCaseRequest({ assignees: [{ uid: '1' }] }) - ); - await updateCase({ - supertest, - params: { - cases: [ - { - id: theCase.id, - version: theCase.version, - assignees: [{ uid: '2' }, { uid: '3' }], - }, - ], - }, - }); - - const userActions = await getCaseUserActions({ supertest, caseID: theCase.id }); - const addAssigneesUserAction = userActions[1]; - const deleteAssigneesUserAction = userActions[2]; - - expect(userActions.length).to.eql(3); - expect(addAssigneesUserAction.type).to.eql('assignees'); - expect(addAssigneesUserAction.action).to.eql('add'); - expect(addAssigneesUserAction.payload).to.eql({ assignees: [{ uid: '2' }, { uid: '3' }] }); - expect(deleteAssigneesUserAction.type).to.eql('assignees'); - expect(deleteAssigneesUserAction.action).to.eql('delete'); - expect(deleteAssigneesUserAction.payload).to.eql({ assignees: [{ uid: '1' }] }); - }); - - describe('user profile uid', () => { - const supertestWithoutAuth = getService('supertestWithoutAuth'); - - let headers: Record; - let superUserWithProfile: User; - let superUserInfo: User; - - before(async () => { - ({ headers, superUserInfo, superUserWithProfile } = await setupSuperUserProfile( - getService - )); - }); - - it('sets the profile uid', async () => { - const { postedCase, connector } = await createCaseWithConnector({ - supertest: supertestWithoutAuth, - serviceNowSimulatorURL, - actionsRemover, - auth: null, - headers, - }); - - await pushCase({ - supertest: supertestWithoutAuth, - caseId: postedCase.id, - connectorId: connector.id, - auth: null, - headers, - }); - - const userActions = await getCaseUserActions({ supertest, caseID: postedCase.id }); - const pushUserAction = userActions[1] as UserActionWithDeprecatedResponse; - - expect(pushUserAction.payload.externalService.pushed_by).to.eql(superUserWithProfile); - }); - - it('falls back to authc to get the user information when the profile uid is not available', async () => { - const { postedCase, connector } = await createCaseWithConnector({ - supertest: supertestWithoutAuth, - serviceNowSimulatorURL, - actionsRemover, - }); - - await pushCase({ - supertest: supertestWithoutAuth, - caseId: postedCase.id, - connectorId: connector.id, - }); - - const userActions = await getCaseUserActions({ supertest, caseID: postedCase.id }); - const pushUserAction = userActions[1] as UserActionWithDeprecatedResponse; - - expect(pushUserAction.payload.externalService.pushed_by).to.eql(superUserInfo); - }); - }); - }); -}; diff --git a/x-pack/test/cases_api_integration/security_and_spaces/tests/trial/create_comment_sub_privilege.ts b/x-pack/test/cases_api_integration/security_and_spaces/tests/trial/create_comment_sub_privilege.ts index ad2ab8a770334..feac669b4c854 100644 --- a/x-pack/test/cases_api_integration/security_and_spaces/tests/trial/create_comment_sub_privilege.ts +++ b/x-pack/test/cases_api_integration/security_and_spaces/tests/trial/create_comment_sub_privilege.ts @@ -25,7 +25,7 @@ import { createComment, updateComment, deleteAllComments, - getCaseUserActions, + findCaseUserActions, } from '../../../common/lib/api'; import { superUser, @@ -128,7 +128,7 @@ export default ({ getService }: FtrProviderContext): void => { }, }); - const userActions = await getCaseUserActions({ + const { userActions } = await findCaseUserActions({ supertest, caseID: postedCase.id, auth: { user: superUser, space: 'space1' }, diff --git a/x-pack/test/cases_api_integration/security_and_spaces/tests/trial/index.ts b/x-pack/test/cases_api_integration/security_and_spaces/tests/trial/index.ts index 0862434256f0e..a4f3bee02f720 100644 --- a/x-pack/test/cases_api_integration/security_and_spaces/tests/trial/index.ts +++ b/x-pack/test/cases_api_integration/security_and_spaces/tests/trial/index.ts @@ -28,7 +28,6 @@ export default ({ loadTestFile, getService }: FtrProviderContext): void => { // Trial loadTestFile(require.resolve('./cases/push_case')); - loadTestFile(require.resolve('./cases/user_actions/get_all_user_actions')); loadTestFile(require.resolve('./cases/user_actions/find_user_actions')); loadTestFile(require.resolve('./cases/assignees')); loadTestFile(require.resolve('./cases/find_cases')); diff --git a/x-pack/test/cases_api_integration/security_and_spaces/tests/trial/internal/get_connectors.ts b/x-pack/test/cases_api_integration/security_and_spaces/tests/trial/internal/get_connectors.ts index 7544e0f724695..35c4c8690b8b1 100644 --- a/x-pack/test/cases_api_integration/security_and_spaces/tests/trial/internal/get_connectors.ts +++ b/x-pack/test/cases_api_integration/security_and_spaces/tests/trial/internal/get_connectors.ts @@ -40,7 +40,7 @@ import { getServiceNowConnector, getServiceNowSimulationServer, } from '../../../../common/lib/api'; -import { getCaseUserActions } from '../../../../common/lib/api/user_actions'; +import { findCaseUserActions } from '../../../../common/lib/api/user_actions'; import { getPostCaseRequest, postCommentUserReq } from '../../../../common/lib/mock'; // eslint-disable-next-line import/no-default-export @@ -297,8 +297,8 @@ export default ({ getService }: FtrProviderContext): void => { connectorId: serviceNow2.id, }); - const [userActions, connectors] = await Promise.all([ - getCaseUserActions({ supertest, caseID: postedCase.id }), + const [{ userActions }, connectors] = await Promise.all([ + findCaseUserActions({ supertest, caseID: postedCase.id }), getConnectors({ caseId: postedCase.id, supertest }), ]); @@ -365,8 +365,8 @@ export default ({ getService }: FtrProviderContext): void => { connectorId: connector.id, }); - const [userActions, connectors] = await Promise.all([ - getCaseUserActions({ supertest, caseID: postedCase.id }), + const [{ userActions }, connectors] = await Promise.all([ + findCaseUserActions({ supertest, caseID: postedCase.id }), getConnectors({ caseId: postedCase.id, supertest }), ]); diff --git a/x-pack/test/cases_api_integration/security_and_spaces/tests/trial/user_profiles/get_current.ts b/x-pack/test/cases_api_integration/security_and_spaces/tests/trial/user_profiles/get_current.ts index 038a8f53b93bc..b8e22cbf5ddce 100644 --- a/x-pack/test/cases_api_integration/security_and_spaces/tests/trial/user_profiles/get_current.ts +++ b/x-pack/test/cases_api_integration/security_and_spaces/tests/trial/user_profiles/get_current.ts @@ -22,7 +22,7 @@ import { getConfigurationRequest, updateConfiguration, } from '../../../../common/lib/api'; -import { getCaseUserActions } from '../../../../common/lib/api/user_actions'; +import { findCaseUserActions } from '../../../../common/lib/api/user_actions'; import { getPostCaseRequest, postCommentUserReq } from '../../../../common/lib/mock'; // eslint-disable-next-line import/no-default-export @@ -57,7 +57,7 @@ export default function ({ getService }: FtrProviderContext) { headers ); - const userActions = await getCaseUserActions({ + const { userActions } = await findCaseUserActions({ supertest: supertestWithoutAuth, caseID: caseInfo.id, }); @@ -72,7 +72,7 @@ export default function ({ getService }: FtrProviderContext) { space: null, }); - const userActions = await getCaseUserActions({ + const { userActions } = await findCaseUserActions({ supertest: supertestWithoutAuth, caseID: caseInfo.id, }); diff --git a/x-pack/test/cases_api_integration/spaces_only/tests/common/cases/status/get_status.ts b/x-pack/test/cases_api_integration/spaces_only/tests/common/cases/status/get_status.ts deleted file mode 100644 index 934ba92a175d6..0000000000000 --- a/x-pack/test/cases_api_integration/spaces_only/tests/common/cases/status/get_status.ts +++ /dev/null @@ -1,98 +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 expect from '@kbn/expect'; -import { CaseStatuses } from '@kbn/cases-plugin/common/types/domain'; -import { FtrProviderContext } from '../../../../../common/ftr_provider_context'; - -import { postCaseReq } from '../../../../../common/lib/mock'; -import { - createCase, - updateCase, - getAllCasesStatuses, - deleteAllCaseItems, - getAuthWithSuperUser, -} from '../../../../../common/lib/api'; - -// eslint-disable-next-line import/no-default-export -export default ({ getService }: FtrProviderContext): void => { - const supertestWithoutAuth = getService('supertestWithoutAuth'); - const es = getService('es'); - const authSpace1 = getAuthWithSuperUser(); - const authSpace2 = getAuthWithSuperUser('space2'); - - describe('get_status', () => { - afterEach(async () => { - await deleteAllCaseItems(es); - }); - - it('should return case statuses in space1', async () => { - /** - * space1: - * open: 1 - * in progress: 1 - * closed: 0 - * space2: - * closed: 1 - */ - const [, inProgressCase, postedCase] = await Promise.all([ - createCase(supertestWithoutAuth, postCaseReq, 200, authSpace1), - createCase(supertestWithoutAuth, postCaseReq, 200, authSpace1), - createCase(supertestWithoutAuth, postCaseReq, 200, authSpace2), - ]); - - await updateCase({ - supertest: supertestWithoutAuth, - params: { - cases: [ - { - id: inProgressCase.id, - version: inProgressCase.version, - status: CaseStatuses['in-progress'], - }, - ], - }, - auth: authSpace1, - }); - - await updateCase({ - supertest: supertestWithoutAuth, - params: { - cases: [ - { - id: postedCase.id, - version: postedCase.version, - status: CaseStatuses.closed, - }, - ], - }, - auth: authSpace2, - }); - - const statusesSpace1 = await getAllCasesStatuses({ - supertest: supertestWithoutAuth, - auth: authSpace1, - }); - const statusesSpace2 = await getAllCasesStatuses({ - supertest: supertestWithoutAuth, - auth: authSpace2, - }); - - expect(statusesSpace1).to.eql({ - count_open_cases: 1, - count_closed_cases: 0, - count_in_progress_cases: 1, - }); - - expect(statusesSpace2).to.eql({ - count_open_cases: 0, - count_closed_cases: 1, - count_in_progress_cases: 0, - }); - }); - }); -}; diff --git a/x-pack/test/cases_api_integration/spaces_only/tests/common/index.ts b/x-pack/test/cases_api_integration/spaces_only/tests/common/index.ts index cf2b9e1fa2e11..782384bfda422 100644 --- a/x-pack/test/cases_api_integration/spaces_only/tests/common/index.ts +++ b/x-pack/test/cases_api_integration/spaces_only/tests/common/index.ts @@ -23,9 +23,7 @@ export default ({ loadTestFile }: FtrProviderContext): void => { loadTestFile(require.resolve('./cases/patch_cases')); loadTestFile(require.resolve('./cases/post_case')); loadTestFile(require.resolve('./cases/reporters/get_reporters')); - loadTestFile(require.resolve('./cases/status/get_status')); loadTestFile(require.resolve('./cases/tags/get_tags')); - loadTestFile(require.resolve('./user_actions/get_all_user_actions')); loadTestFile(require.resolve('./configure/get_configure')); loadTestFile(require.resolve('./configure/patch_configure')); loadTestFile(require.resolve('./configure/post_configure')); diff --git a/x-pack/test/cases_api_integration/spaces_only/tests/common/user_actions/get_all_user_actions.ts b/x-pack/test/cases_api_integration/spaces_only/tests/common/user_actions/get_all_user_actions.ts deleted file mode 100644 index 6c551c7c985f0..0000000000000 --- a/x-pack/test/cases_api_integration/spaces_only/tests/common/user_actions/get_all_user_actions.ts +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import expect from '@kbn/expect'; -import { FtrProviderContext } from '../../../../common/ftr_provider_context'; - -import { getPostCaseRequest } from '../../../../common/lib/mock'; -import { deleteAllCaseItems, createCase, getAuthWithSuperUser } from '../../../../common/lib/api'; -import { getCaseUserActions } from '../../../../common/lib/api'; - -// eslint-disable-next-line import/no-default-export -export default ({ getService }: FtrProviderContext): void => { - const supertestWithoutAuth = getService('supertestWithoutAuth'); - const es = getService('es'); - const authSpace1 = getAuthWithSuperUser(); - - describe('get_all_user_actions', () => { - afterEach(async () => { - await deleteAllCaseItems(es); - }); - - it(`should get user actions in space1`, async () => { - const postedCase = await createCase( - supertestWithoutAuth, - getPostCaseRequest(), - 200, - authSpace1 - ); - const body = await getCaseUserActions({ - supertest: supertestWithoutAuth, - caseID: postedCase.id, - auth: authSpace1, - }); - - expect(body.length).to.eql(1); - }); - - it(`should not get user actions in the wrong space`, async () => { - const postedCase = await createCase( - supertestWithoutAuth, - getPostCaseRequest(), - 200, - authSpace1 - ); - const body = await getCaseUserActions({ - supertest: supertestWithoutAuth, - caseID: postedCase.id, - auth: getAuthWithSuperUser('space2'), - }); - - expect(body.length).to.eql(0); - }); - }); -}; diff --git a/x-pack/test/kubernetes_security/basic/config.ts b/x-pack/test/kubernetes_security/basic/config.ts deleted file mode 100644 index d57a65a1e9fd2..0000000000000 --- a/x-pack/test/kubernetes_security/basic/config.ts +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { createTestConfig } from '../common/config'; - -// eslint-disable-next-line import/no-default-export -export default createTestConfig({ - license: 'basic', - name: 'X-Pack kubernetes_security API integration tests (basic)', - testFiles: [require.resolve('./tests')], -}); diff --git a/x-pack/test/kubernetes_security/basic/tests/aggregate.ts b/x-pack/test/kubernetes_security/basic/tests/aggregate.ts deleted file mode 100644 index e5d72ed038b42..0000000000000 --- a/x-pack/test/kubernetes_security/basic/tests/aggregate.ts +++ /dev/null @@ -1,134 +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 expect from '@kbn/expect'; -import { - AGGREGATE_ROUTE, - CURRENT_API_VERSION, - ORCHESTRATOR_NAMESPACE, - CONTAINER_IMAGE_NAME, - ENTRY_LEADER_ENTITY_ID, -} from '@kbn/kubernetes-security-plugin/common/constants'; -import { FtrProviderContext } from '../../common/ftr_provider_context'; -const MOCK_INDEX = 'kubernetes-test-index'; -const TIMESTAMP_PROPERTY = '@timestamp'; - -// eslint-disable-next-line import/no-default-export -export default function aggregateTests({ getService }: FtrProviderContext) { - const supertest = getService('supertest'); - const esArchiver = getService('esArchiver'); - const namespaces = ['namespace', 'namespace02', 'namespace03', 'namespace04']; - - function getRoute() { - return supertest - .get(AGGREGATE_ROUTE) - .set('kbn-xsrf', 'foo') - .set('Elastic-Api-Version', CURRENT_API_VERSION); - } - - describe('Kubernetes security with a basic license', () => { - before(async () => { - await esArchiver.load( - 'x-pack/test/functional/es_archives/kubernetes_security/process_events' - ); - }); - - after(async () => { - await esArchiver.unload( - 'x-pack/test/functional/es_archives/kubernetes_security/process_events' - ); - }); - - it(`${AGGREGATE_ROUTE} returns aggregates on process events`, async () => { - const response = await getRoute().query({ - query: JSON.stringify({ match: { [CONTAINER_IMAGE_NAME]: 'debian11' } }), - groupBy: ORCHESTRATOR_NAMESPACE, - page: 0, - index: MOCK_INDEX, - perPage: 10, - }); - expect(response.status).to.be(200); - expect(response.body.buckets.length).to.be(10); - - namespaces.forEach((namespace, i) => { - expect(response.body.buckets[i].key).to.be(namespace); - }); - }); - - it(`${AGGREGATE_ROUTE} allows pagination`, async () => { - const response = await getRoute().query({ - query: JSON.stringify({ match: { [CONTAINER_IMAGE_NAME]: 'debian11' } }), - groupBy: ORCHESTRATOR_NAMESPACE, - page: 1, - index: MOCK_INDEX, - }); - expect(response.status).to.be(200); - expect(response.body.buckets.length).to.be(1); - expect(response.body.buckets[0].key).to.be('namespace11'); - }); - - it(`${AGGREGATE_ROUTE} return countBy value for each aggregation`, async () => { - const response = await getRoute().query({ - query: JSON.stringify({ match: { [CONTAINER_IMAGE_NAME]: 'debian11' } }), - groupBy: ORCHESTRATOR_NAMESPACE, - countBy: ORCHESTRATOR_NAMESPACE, - page: 0, - index: MOCK_INDEX, - }); - expect(response.status).to.be(200); - expect(response.body.buckets.length).to.be(10); - - // when groupBy and countBy use the same field, count_by_aggs.value will always be 1 - response.body.buckets.forEach((agg: any) => { - expect(agg.count_by_aggs.value).to.be(1); - }); - }); - - it(`${AGGREGATE_ROUTE} return sorted aggregation by countBy field if sortByCount is true`, async () => { - const response = await getRoute().query({ - query: JSON.stringify({ match: { [CONTAINER_IMAGE_NAME]: 'debian11' } }), - groupBy: ORCHESTRATOR_NAMESPACE, - countBy: ENTRY_LEADER_ENTITY_ID, - page: 0, - index: MOCK_INDEX, - sortByCount: 'desc', - }); - expect(response.status).to.be(200); - expect(response.body.buckets.length).to.be(10); - expect(response.body.buckets[0].count_by_aggs.value).to.be(2); - expect(response.body.buckets[1].count_by_aggs.value).to.be(1); - }); - - it(`${AGGREGATE_ROUTE} allows a range query`, async () => { - const response = await getRoute().query({ - query: JSON.stringify({ - range: { - [TIMESTAMP_PROPERTY]: { - gte: '2020-12-16T15:16:28.570Z', - lte: '2020-12-16T15:16:30.570Z', - }, - }, - }), - groupBy: ORCHESTRATOR_NAMESPACE, - page: 0, - index: MOCK_INDEX, - }); - expect(response.status).to.be(200); - expect(response.body.buckets.length).to.be(3); - }); - - it(`${AGGREGATE_ROUTE} handles a bad request`, async () => { - const response = await getRoute().query({ - query: 'asdf', - groupBy: ORCHESTRATOR_NAMESPACE, - page: 0, - index: MOCK_INDEX, - }); - expect(response.status).to.be(500); - }); - }); -} diff --git a/x-pack/test/kubernetes_security/basic/tests/count.ts b/x-pack/test/kubernetes_security/basic/tests/count.ts deleted file mode 100644 index 810b91cce0cf7..0000000000000 --- a/x-pack/test/kubernetes_security/basic/tests/count.ts +++ /dev/null @@ -1,80 +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 expect from '@kbn/expect'; -import { COUNT_ROUTE, CURRENT_API_VERSION } from '@kbn/kubernetes-security-plugin/common/constants'; -import { FtrProviderContext } from '../../common/ftr_provider_context'; - -const MOCK_INDEX = 'kubernetes-test-index'; -const ORCHESTRATOR_NAMESPACE_PROPERTY = 'orchestrator.namespace'; -const CONTAINER_IMAGE_NAME_PROPERTY = 'container.image.name'; -const TIMESTAMP_PROPERTY = '@timestamp'; - -// eslint-disable-next-line import/no-default-export -export default function countTests({ getService }: FtrProviderContext) { - const supertest = getService('supertest'); - const esArchiver = getService('esArchiver'); - - function getRoute() { - return supertest - .get(COUNT_ROUTE) - .set('kbn-xsrf', 'foo') - .set('Elastic-Api-Version', CURRENT_API_VERSION); - } - - describe('Kubernetes security with a basic license', () => { - before(async () => { - await esArchiver.load( - 'x-pack/test/functional/es_archives/kubernetes_security/process_events' - ); - }); - - after(async () => { - await esArchiver.unload( - 'x-pack/test/functional/es_archives/kubernetes_security/process_events' - ); - }); - - it(`${COUNT_ROUTE} returns cardinality of a field`, async () => { - const response = await getRoute().query({ - query: JSON.stringify({ match: { [CONTAINER_IMAGE_NAME_PROPERTY]: 'debian11' } }), - field: ORCHESTRATOR_NAMESPACE_PROPERTY, - index: MOCK_INDEX, - }); - expect(response.status).to.be(200); - expect(response.body).to.be(11); - }); - - it(`${COUNT_ROUTE} allows a range query`, async () => { - const response = await getRoute().query({ - query: JSON.stringify({ - range: { - [TIMESTAMP_PROPERTY]: { - gte: '2020-12-16T15:16:28.570Z', - lte: '2020-12-16T15:16:30.570Z', - }, - }, - }), - field: ORCHESTRATOR_NAMESPACE_PROPERTY, - index: MOCK_INDEX, - }); - expect(response.status).to.be(200); - expect(response.body).to.be(3); - }); - - it(`${COUNT_ROUTE} handles a bad query`, async () => { - const response = await getRoute().query({ - query: JSON.stringify({ - range: 'asdf', - }), - field: ORCHESTRATOR_NAMESPACE_PROPERTY, - index: MOCK_INDEX, - }); - expect(response.status).to.be(400); - }); - }); -} diff --git a/x-pack/test/kubernetes_security/basic/tests/index.ts b/x-pack/test/kubernetes_security/basic/tests/index.ts deleted file mode 100644 index c7973fa7c4b5d..0000000000000 --- a/x-pack/test/kubernetes_security/basic/tests/index.ts +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { FtrProviderContext } from '../../common/ftr_provider_context'; - -// eslint-disable-next-line import/no-default-export -export default function kubernetesSecurityApiIntegrationTests({ - loadTestFile, -}: FtrProviderContext) { - describe('Kubernetes security API (basic)', function () { - loadTestFile(require.resolve('./aggregate')); - loadTestFile(require.resolve('./count')); - loadTestFile(require.resolve('./multi_terms_aggregate')); - }); -} diff --git a/x-pack/test/kubernetes_security/basic/tests/multi_terms_aggregate.ts b/x-pack/test/kubernetes_security/basic/tests/multi_terms_aggregate.ts deleted file mode 100644 index 2e2c20a8deea7..0000000000000 --- a/x-pack/test/kubernetes_security/basic/tests/multi_terms_aggregate.ts +++ /dev/null @@ -1,192 +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 expect from '@kbn/expect'; -import { - MULTI_TERMS_AGGREGATE_ROUTE, - CURRENT_API_VERSION, - ORCHESTRATOR_NAMESPACE, - CONTAINER_IMAGE_NAME, - ENTRY_LEADER_ENTITY_ID, -} from '@kbn/kubernetes-security-plugin/common/constants'; -import { FtrProviderContext } from '../../common/ftr_provider_context'; -const MOCK_INDEX = 'kubernetes-test-index'; -const TIMESTAMP_PROPERTY = '@timestamp'; - -// eslint-disable-next-line import/no-default-export -export default function aggregateTests({ getService }: FtrProviderContext) { - const supertest = getService('supertest'); - const esArchiver = getService('esArchiver'); - const namespaces = new Set([ - 'namespace', - 'namespace02', - 'namespace03', - 'namespace04', - 'namespace05', - 'namespace06', - 'namespace07', - 'namespace08', - 'namespace09', - 'namespace10', - ]); - - function getRoute() { - return supertest - .get(MULTI_TERMS_AGGREGATE_ROUTE) - .set('kbn-xsrf', 'foo') - .set('Elastic-Api-Version', CURRENT_API_VERSION); - } - - describe('Kubernetes security with a basic license', () => { - before(async () => { - await esArchiver.load( - 'x-pack/test/functional/es_archives/kubernetes_security/process_events' - ); - }); - - after(async () => { - await esArchiver.unload( - 'x-pack/test/functional/es_archives/kubernetes_security/process_events' - ); - }); - - it(`${MULTI_TERMS_AGGREGATE_ROUTE} returns aggregates on process events`, async () => { - const response = await getRoute().query({ - query: JSON.stringify({ match: { [ENTRY_LEADER_ENTITY_ID]: '1' } }), - groupBys: JSON.stringify([ - { - field: ORCHESTRATOR_NAMESPACE, - }, - { - field: CONTAINER_IMAGE_NAME, - }, - ]), - page: 0, - index: MOCK_INDEX, - perPage: 10, - }); - expect(response.status).to.be(200); - expect(response.body.buckets.length).to.be(10); - - response.body.buckets.forEach((bucket: { key: [string, string] }) => { - expect(namespaces.has(bucket.key[0])).to.be(true); - expect(bucket.key[1]).to.be('debian11'); - }); - }); - - it(`${MULTI_TERMS_AGGREGATE_ROUTE} allows pagination`, async () => { - const response = await getRoute().query({ - query: JSON.stringify({ match: { [ENTRY_LEADER_ENTITY_ID]: '1' } }), - groupBys: JSON.stringify([ - { - field: ORCHESTRATOR_NAMESPACE, - }, - { - field: CONTAINER_IMAGE_NAME, - missing: 'default', - }, - ]), - page: 1, - index: MOCK_INDEX, - perPage: 5, - }); - - expect(response.status).to.be(200); - expect(response.body.buckets.length).to.be(5); - expect(response.body.buckets[0].key[0]).to.be('namespace06'); - expect(response.body.buckets[0].key[1]).to.be('debian11'); - }); - - it(`${MULTI_TERMS_AGGREGATE_ROUTE} allows missing field`, async () => { - const response = await getRoute().query({ - query: JSON.stringify({ match: { [ENTRY_LEADER_ENTITY_ID]: '1' } }), - groupBys: JSON.stringify([ - { - field: ORCHESTRATOR_NAMESPACE, - }, - { - field: CONTAINER_IMAGE_NAME, - missing: 'default', - }, - ]), - page: 2, - index: MOCK_INDEX, - perPage: 4, - }); - expect(response.status).to.be(200); - expect(response.body.buckets.length).to.be(2); - expect(response.body.buckets[1].key[0]).to.be('namespace09'); - expect(response.body.buckets[1].key[1]).to.be('default'); - }); - - it(`${MULTI_TERMS_AGGREGATE_ROUTE} return countBy value for each aggregation`, async () => { - const response = await getRoute().query({ - query: JSON.stringify({ match: { [ENTRY_LEADER_ENTITY_ID]: '1' } }), - groupBys: JSON.stringify([ - { - field: ORCHESTRATOR_NAMESPACE, - }, - { - field: CONTAINER_IMAGE_NAME, - }, - ]), - countBy: ORCHESTRATOR_NAMESPACE, - page: 0, - index: MOCK_INDEX, - }); - expect(response.status).to.be(200); - expect(response.body.buckets.length).to.be(10); - - // when groupBy and countBy use the same field, count_by_aggs.value will always be 1 - response.body.buckets.forEach((agg: any) => { - expect(agg.count_by_aggs.value).to.be(1); - }); - }); - - it(`${MULTI_TERMS_AGGREGATE_ROUTE} allows a range query`, async () => { - const response = await getRoute().query({ - query: JSON.stringify({ - range: { - [TIMESTAMP_PROPERTY]: { - gte: '2020-12-16T15:16:28.570Z', - lte: '2020-12-16T15:16:30.570Z', - }, - }, - }), - groupBys: JSON.stringify([ - { - field: ORCHESTRATOR_NAMESPACE, - }, - { - field: CONTAINER_IMAGE_NAME, - }, - ]), - page: 0, - index: MOCK_INDEX, - }); - expect(response.status).to.be(200); - expect(response.body.buckets.length).to.be(3); - }); - - it(`${MULTI_TERMS_AGGREGATE_ROUTE} handles a bad request`, async () => { - const response = await getRoute().query({ - query: 'asdf', - groupBys: JSON.stringify([ - { - field: ORCHESTRATOR_NAMESPACE, - }, - { - field: CONTAINER_IMAGE_NAME, - }, - ]), - page: 0, - index: MOCK_INDEX, - }); - expect(response.status).to.be(500); - }); - }); -} diff --git a/x-pack/test/kubernetes_security/common/config.ts b/x-pack/test/kubernetes_security/common/config.ts deleted file mode 100644 index 83249182084f3..0000000000000 --- a/x-pack/test/kubernetes_security/common/config.ts +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { FtrConfigProviderContext } from '@kbn/test'; - -interface Settings { - license: 'basic' | 'trial'; - testFiles: string[]; - name: string; -} - -export function createTestConfig(settings: Settings) { - const { testFiles, license, name } = settings; - - return async ({ readConfigFile }: FtrConfigProviderContext) => { - const xPackAPITestsConfig = await readConfigFile( - require.resolve('../../api_integration/config.ts') - ); - - return { - testFiles, - servers: xPackAPITestsConfig.get('servers'), - services: xPackAPITestsConfig.get('services'), - junit: { - reportName: name, - }, - - esTestCluster: { - ...xPackAPITestsConfig.get('esTestCluster'), - license, - }, - kbnTestServer: xPackAPITestsConfig.get('kbnTestServer'), - }; - }; -} diff --git a/x-pack/test/observability_ai_assistant_functional/tests/feature_controls/assistant_security.spec.ts b/x-pack/test/observability_ai_assistant_functional/tests/feature_controls/assistant_security.spec.ts index 1108c7251b89d..117a9f11b316e 100644 --- a/x-pack/test/observability_ai_assistant_functional/tests/feature_controls/assistant_security.spec.ts +++ b/x-pack/test/observability_ai_assistant_functional/tests/feature_controls/assistant_security.spec.ts @@ -20,6 +20,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { const PageObjects = getPageObjects(['common', 'error', 'navigationalSearch', 'security']); const ui = getService('observabilityAIAssistantUI'); const testSubjects = getService('testSubjects'); + const obsAssistantConversationsGlobalSearchEntry = 'Observability AI Assistant / Conversations'; describe('ai assistant privileges', () => { describe('all privileges', () => { @@ -51,7 +52,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { it('shows AI Assistant conversations link in search', async () => { await PageObjects.navigationalSearch.searchFor('observability ai assistant'); const results = await PageObjects.navigationalSearch.getDisplayedResults(); - expect(results[0].label).to.eql('Observability AI Assistant / Conversations'); + expect(results[0].label).to.eql(obsAssistantConversationsGlobalSearchEntry); }); describe('with no connector setup', () => { before(async () => { @@ -118,13 +119,13 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { // need some obs app or obs menu wont show where we can click on AI Assistant infrastructure: ['all'], }); - }); - it('shows no AI Assistant link in solution nav', async () => { // navigate to an observability app so the left side o11y menu shows up await PageObjects.common.navigateToUrl('infraOps', '', { ensureCurrentUrl: true, shouldLoginIfPrompted: false, }); + }); + it('shows no AI Assistant link in solution nav', async () => { await testSubjects.missingOrFail(ui.pages.links.solutionMenuLink); }); it('shows no AI Assistant button in global nav', async () => { @@ -133,7 +134,10 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { it('shows no AI Assistant conversations link in global search', async () => { await PageObjects.navigationalSearch.searchFor('observability ai assistant'); const results = await PageObjects.navigationalSearch.getDisplayedResults(); - expect(results.length).to.eql(0); + const aiAssistantConversationsEntry = results.some( + ({ label }) => label === obsAssistantConversationsGlobalSearchEntry + ); + expect(aiAssistantConversationsEntry).to.be(false); }); it('cannot navigate to AI Assistant page', async () => { await PageObjects.common.navigateToUrl('obsAIAssistant', '', { diff --git a/x-pack/test/security_solution_api_integration/test_suites/investigation/timeline/tests/notes_privileges.ts b/x-pack/test/security_solution_api_integration/test_suites/investigation/timeline/tests/notes_privileges.ts index f0f7c36b924f3..4e41fd8d61bf7 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/investigation/timeline/tests/notes_privileges.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/investigation/timeline/tests/notes_privileges.ts @@ -53,7 +53,9 @@ export default function ({ getService }: FtrProviderContextWithSpaces) { before(async () => { const superTest = await utils.createSuperTestWithUser(users.secNotesAllUser); const { - body: { noteId }, + body: { + note: { noteId }, + }, } = await createNote(superTest, { text: 'test', documentId: '123' }); getNoteId = () => noteId; }); @@ -61,14 +63,16 @@ export default function ({ getService }: FtrProviderContextWithSpaces) { canWriteOrReadUsers.forEach((user) => { it(`user "${user.username}" can read notes`, async () => { const superTest = await utils.createSuperTestWithUser(user); - await getNote(superTest, getNoteId()).expect(200); + const getNoteResponse = await getNote(superTest, getNoteId()); + expect(getNoteResponse.status).to.be(200); }); }); cannotAccessUsers.forEach((user) => { it(`user "${user.username}" cannot read notes`, async () => { const superTest = await utils.createSuperTestWithUser(user); - await getNote(superTest, getNoteId()).expect(403); + const getNoteResponse = await getNote(superTest, getNoteId()); + expect(getNoteResponse.status).to.be(403); }); }); }); @@ -96,7 +100,9 @@ export default function ({ getService }: FtrProviderContextWithSpaces) { before(async () => { const superTest = await utils.createSuperTestWithUser(users.secNotesAllUser); const { - body: { noteId }, + body: { + note: { noteId }, + }, } = await createNote(superTest, { text: 'test', documentId: '123' }); getNoteId = () => noteId; }); @@ -104,14 +110,16 @@ export default function ({ getService }: FtrProviderContextWithSpaces) { canWriteUsers.forEach((user) => { it(`user "${user.username}" can delete notes`, async () => { const superTest = await utils.createSuperTestWithUser(user); - await deleteNote(superTest, getNoteId()).expect(200); + const deleteNoteRequest = await deleteNote(superTest, getNoteId()); + expect(deleteNoteRequest.status).to.be(200); }); }); cannotWriteUsers.forEach((user) => { it(`user "${user.username}" cannot delete notes`, async () => { const superTest = await utils.createSuperTestWithUser(user); - await deleteNote(superTest, getNoteId()).expect(403); + const deleteNoteRequest = await deleteNote(superTest, getNoteId()); + expect(deleteNoteRequest.status).to.be(403); }); }); }); diff --git a/x-pack/test/security_solution_api_integration/test_suites/investigation/timeline/tests/timeline.ts b/x-pack/test/security_solution_api_integration/test_suites/investigation/timeline/tests/timeline.ts index 5a0b79174293f..f09ddc9d221d8 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/investigation/timeline/tests/timeline.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/investigation/timeline/tests/timeline.ts @@ -6,11 +6,15 @@ */ import expect from '@kbn/expect'; -import { SavedTimeline, TimelineTypeEnum } from '@kbn/security-solution-plugin/common/api/timeline'; -import { TIMELINE_URL, TIMELINES_URL } from '@kbn/security-solution-plugin/common/constants'; +import { TimelineTypeEnum } from '@kbn/security-solution-plugin/common/api/timeline'; import TestAgent from 'supertest/lib/agent'; import { FtrProviderContextWithSpaces } from '../../../../ftr_provider_context_with_spaces'; -import { createBasicTimeline, createBasicTimelineTemplate } from '../../utils/timelines'; +import { + createBasicTimeline, + createBasicTimelineTemplate, + getTimelines, + resolveTimeline, +} from '../../utils/timelines'; export default function ({ getService }: FtrProviderContextWithSpaces) { const utils = getService('securitySolutionUtils'); @@ -25,9 +29,9 @@ export default function ({ getService }: FtrProviderContextWithSpaces) { const titleToSaved = 'hello timeline'; await createBasicTimeline(supertest, titleToSaved); - const resp = await supertest.get(TIMELINES_URL).set('kbn-xsrf', 'true'); - - const timelines = resp.body.timeline; + const { + body: { timeline: timelines }, + } = await getTimelines(supertest); expect(timelines.length).to.greaterThan(0); }); @@ -36,11 +40,9 @@ export default function ({ getService }: FtrProviderContextWithSpaces) { const titleToSaved = 'hello timeline'; await createBasicTimeline(supertest, titleToSaved); - const resp = await supertest - .get(`${TIMELINES_URL}?page_size=1&page_index=1`) - .set('kbn-xsrf', 'true'); - - const timelines = resp.body.timeline; + const { + body: { timeline: timelines }, + } = await getTimelines(supertest, { page_size: '1', page_index: '1' }); expect(timelines.length).to.equal(1); }); @@ -49,11 +51,9 @@ export default function ({ getService }: FtrProviderContextWithSpaces) { const titleToSaved = 'hello timeline template'; await createBasicTimelineTemplate(supertest, titleToSaved); - const resp = await supertest - .get(`${TIMELINES_URL}?timeline_type=template`) - .set('kbn-xsrf', 'true'); - - const templates: SavedTimeline[] = resp.body.timeline; + const { + body: { timeline: templates }, + } = await getTimelines(supertest, { timeline_type: 'template' }); expect(templates.length).to.greaterThan(0); expect( @@ -65,7 +65,7 @@ export default function ({ getService }: FtrProviderContextWithSpaces) { * Migration of saved object not working to current serverless version * https://github.com/elastic/kibana/issues/196483 * */ - describe.skip('resolve timeline', () => { + describe('@skipInServerless resolve timeline', () => { before(async () => { await esArchiver.load( 'x-pack/test/functional/es_archives/security_solution/timelines/7.15.0' @@ -79,32 +79,25 @@ export default function ({ getService }: FtrProviderContextWithSpaces) { }); it('should return outcome exactMatch when the id is unchanged', async () => { - const resp = await supertest - .get(`${TIMELINE_URL}/resolve`) - .query({ id: '8dc70950-1012-11ec-9ad3-2d7c6600c0f7' }); - expect(resp.body.data.outcome).to.be('exactMatch'); - expect(resp.body.data.alias_target_id).to.be(undefined); - expect(resp.body.data.timeline.title).to.be('Awesome Timeline'); + const resp = await resolveTimeline(supertest, '8dc70950-1012-11ec-9ad3-2d7c6600c0f7'); + expect(resp.body.outcome).to.be('exactMatch'); + expect(resp.body.alias_target_id).to.be(undefined); + expect(resp.body.timeline.title).to.be('Awesome Timeline'); }); describe('notes', () => { it('should return notes with eventId', async () => { - const resp = await supertest - .get(`${TIMELINE_URL}/resolve`) - .query({ id: '6484cc90-126e-11ec-83d2-db1096c73738' }); - - expect(resp.body.data.timeline.notes[0].eventId).to.be('Edo00XsBEVtyvU-8LGNe'); + const resp = await resolveTimeline(supertest, '6484cc90-126e-11ec-83d2-db1096c73738'); + expect(resp.body.timeline.notes![0].eventId).to.be('Edo00XsBEVtyvU-8LGNe'); }); it('should return notes with the timelineId matching request id', async () => { - const resp = await supertest - .get(`${TIMELINE_URL}/resolve`) - .query({ id: '6484cc90-126e-11ec-83d2-db1096c73738' }); + const resp = await resolveTimeline(supertest, '6484cc90-126e-11ec-83d2-db1096c73738'); - expect(resp.body.data.timeline.notes[0].timelineId).to.be( + expect(resp.body.timeline.notes![0].timelineId).to.be( '6484cc90-126e-11ec-83d2-db1096c73738' ); - expect(resp.body.data.timeline.notes[1].timelineId).to.be( + expect(resp.body.timeline.notes![1].timelineId).to.be( '6484cc90-126e-11ec-83d2-db1096c73738' ); }); @@ -112,27 +105,23 @@ export default function ({ getService }: FtrProviderContextWithSpaces) { describe('pinned events', () => { it('should pinned events with eventId', async () => { - const resp = await supertest - .get(`${TIMELINE_URL}/resolve`) - .query({ id: '6484cc90-126e-11ec-83d2-db1096c73738' }); + const resp = await resolveTimeline(supertest, '6484cc90-126e-11ec-83d2-db1096c73738'); - expect(resp.body.data.timeline.pinnedEventsSaveObject[0].eventId).to.be( + expect(resp.body.timeline.pinnedEventsSaveObject![0].eventId).to.be( 'DNo00XsBEVtyvU-8LGNe' ); - expect(resp.body.data.timeline.pinnedEventsSaveObject[1].eventId).to.be( + expect(resp.body.timeline.pinnedEventsSaveObject![1].eventId).to.be( 'Edo00XsBEVtyvU-8LGNe' ); }); it('should return pinned events with the timelineId matching request id', async () => { - const resp = await supertest - .get(`${TIMELINE_URL}/resolve`) - .query({ id: '6484cc90-126e-11ec-83d2-db1096c73738' }); + const resp = await resolveTimeline(supertest, '6484cc90-126e-11ec-83d2-db1096c73738'); - expect(resp.body.data.timeline.pinnedEventsSaveObject[0].timelineId).to.be( + expect(resp.body.timeline.pinnedEventsSaveObject![0].timelineId).to.be( '6484cc90-126e-11ec-83d2-db1096c73738' ); - expect(resp.body.data.timeline.pinnedEventsSaveObject[1].timelineId).to.be( + expect(resp.body.timeline.pinnedEventsSaveObject![1].timelineId).to.be( '6484cc90-126e-11ec-83d2-db1096c73738' ); }); diff --git a/x-pack/test/security_solution_api_integration/test_suites/investigation/timeline/tests/timeline_privileges.ts b/x-pack/test/security_solution_api_integration/test_suites/investigation/timeline/tests/timeline_privileges.ts index 7ee34ef482ec0..96e6f21e3651c 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/investigation/timeline/tests/timeline_privileges.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/investigation/timeline/tests/timeline_privileges.ts @@ -18,6 +18,7 @@ import { copyTimeline, resolveTimeline, installPrepackedTimelines, + unPinEvent, } from '../../utils/timelines'; import * as users from '../../../../config/privileges/users'; import { roles } from '../../../../config/privileges/roles'; @@ -63,14 +64,16 @@ export default function ({ getService }: FtrProviderContextWithSpaces) { canWriteOrReadUsers.forEach((user) => { it(`user "${user.username}" can read timelines`, async () => { const superTest = await utils.createSuperTestWithUser(user); - await getTimelines(superTest).expect(200); + const getTimelinesResponse = await getTimelines(superTest); + expect(getTimelinesResponse.status).to.be(200); }); }); cannotAccessUsers.forEach((user) => { it(`user "${user.username}" cannot read timelines`, async () => { const superTest = await utils.createSuperTestWithUser(user); - await getTimelines(superTest).expect(403); + const getTimelinesResponse = await getTimelines(superTest); + expect(getTimelinesResponse.status).to.be(403); }); }); }); @@ -87,14 +90,16 @@ export default function ({ getService }: FtrProviderContextWithSpaces) { canWriteOrReadUsers.forEach((user) => { it(`user "${user.username}" can resolve timelines`, async () => { const superTest = await utils.createSuperTestWithUser(user); - await resolveTimeline(superTest, getTimelineId()).expect(200); + const resolveTimelineResponse = await resolveTimeline(superTest, getTimelineId()); + expect(resolveTimelineResponse.status).to.be(200); }); }); cannotAccessUsers.forEach((user) => { it(`user "${user.username}" cannot resolve timelines`, async () => { const superTest = await utils.createSuperTestWithUser(user); - await resolveTimeline(superTest, getTimelineId()).expect(403); + const resolveTimelineResponse = await resolveTimeline(superTest, getTimelineId()); + expect(resolveTimelineResponse.status).to.be(403); }); }); }); @@ -107,7 +112,8 @@ export default function ({ getService }: FtrProviderContextWithSpaces) { const createResponse = await createBasicTimeline(superTest, 'test timeline'); expect(createResponse.status).to.be(200); - await deleteTimeline(superTest, createResponse.body.savedObjectId).expect(200); + const deleteResponse = await deleteTimeline(superTest, createResponse.body.savedObjectId); + expect(deleteResponse.status).to.be(200); }); }); @@ -131,7 +137,8 @@ export default function ({ getService }: FtrProviderContextWithSpaces) { it(`user "${user.username}" cannot delete timelines`, async () => { const superTest = await utils.createSuperTestWithUser(user); - await deleteTimeline(superTest, getTimelineToDeleteId()).expect(403); + const deleteResponse = await deleteTimeline(superTest, getTimelineToDeleteId()); + expect(deleteResponse.status).to.be(403); }); }); }); @@ -185,10 +192,14 @@ export default function ({ getService }: FtrProviderContextWithSpaces) { canWriteUsers.forEach((user) => { it(`user "${user.username}" can favorite/unfavorite timelines`, async () => { const superTest = await utils.createSuperTestWithUser(user); - await favoriteTimeline(superTest, getTimelineId()).expect(200); + const favoriteTimelineRequest = await favoriteTimeline(superTest, getTimelineId()); + expect(favoriteTimelineRequest.status).to.be(200); + expect(favoriteTimelineRequest.body.favorite).to.have.length(1); // unfavorite - await favoriteTimeline(superTest, getTimelineId()).expect(200); + const unFavoriteTimelineRequest = await favoriteTimeline(superTest, getTimelineId()); + expect(unFavoriteTimelineRequest.status).to.be(200); + expect(unFavoriteTimelineRequest.body.favorite).to.have.length(0); }); }); @@ -196,7 +207,8 @@ export default function ({ getService }: FtrProviderContextWithSpaces) { it(`user "${user.username}" cannot favorite/unfavorite timelines`, async () => { const superTest = await utils.createSuperTestWithUser(user); - await favoriteTimeline(superTest, getTimelineId()).expect(403); + const favoriteTimelineRequest = await favoriteTimeline(superTest, getTimelineId()); + expect(favoriteTimelineRequest.status).to.be(403); }); }); }); @@ -214,10 +226,19 @@ export default function ({ getService }: FtrProviderContextWithSpaces) { canWriteUsers.forEach((user) => { it(`user "${user.username}" can pin/unpin events`, async () => { const superTest = await utils.createSuperTestWithUser(user); - await pinEvent(superTest, getTimelineId(), eventId).expect(200); + const pinEventResponse = await pinEvent(superTest, getTimelineId(), eventId); + expect(pinEventResponse.status).to.be(200); + expect('pinnedEventId' in pinEventResponse.body).to.be(true); // unpin - await pinEvent(superTest, getTimelineId(), eventId).expect(200); + const unPinEventResponse = await unPinEvent( + superTest, + getTimelineId(), + eventId, + 'pinnedEventId' in pinEventResponse.body ? pinEventResponse.body.pinnedEventId : '' + ); + expect(unPinEventResponse.status).to.be(200); + expect(unPinEventResponse.body).to.eql({ unpinned: true }); }); }); @@ -225,7 +246,8 @@ export default function ({ getService }: FtrProviderContextWithSpaces) { it(`user "${user.username}" cannot pin/unpin events`, async () => { const superTest = await utils.createSuperTestWithUser(user); - await pinEvent(superTest, getTimelineId(), eventId).expect(403); + const pinEventResponse = await pinEvent(superTest, getTimelineId(), eventId); + expect(pinEventResponse.status).to.be(403); }); }); }); @@ -242,7 +264,12 @@ export default function ({ getService }: FtrProviderContextWithSpaces) { it(`user "${user.username}" can copy timeline`, async () => { const superTest = await utils.createSuperTestWithUser(user); const timeline = getTimeline(); - await copyTimeline(superTest, timeline.savedObjectId, timeline).expect(200); + const copyTimelineResponse = await copyTimeline( + superTest, + timeline.savedObjectId, + timeline + ); + expect(copyTimelineResponse.status).to.be(200); }); }); @@ -250,7 +277,12 @@ export default function ({ getService }: FtrProviderContextWithSpaces) { it(`user "${user.username}" cannot copy timeline`, async () => { const superTest = await utils.createSuperTestWithUser(user); const timeline = getTimeline(); - await copyTimeline(superTest, timeline.savedObjectId, timeline).expect(403); + const copyTimelineResponse = await copyTimeline( + superTest, + timeline.savedObjectId, + timeline + ); + expect(copyTimelineResponse.status).to.be(403); }); }); }); @@ -259,14 +291,16 @@ export default function ({ getService }: FtrProviderContextWithSpaces) { canWriteUsers.forEach((user) => { it(`user "${user.username}" can install prepackaged timelines`, async () => { const superTest = await utils.createSuperTestWithUser(user); - await installPrepackedTimelines(superTest).expect(200); + const installTimelinesResponse = await installPrepackedTimelines(superTest); + expect(installTimelinesResponse.status).to.be(200); }); }); cannotWriteUsers.forEach((user) => { it(`user "${user.username}" cannot install prepackaged timelines`, async () => { const superTest = await utils.createSuperTestWithUser(user); - await installPrepackedTimelines(superTest).expect(403); + const installTimelinesResponse = await installPrepackedTimelines(superTest); + expect(installTimelinesResponse.status).to.be(403); }); }); }); diff --git a/x-pack/test/security_solution_api_integration/test_suites/investigation/utils/notes.ts b/x-pack/test/security_solution_api_integration/test_suites/investigation/utils/notes.ts index 57599ca28aef8..80222669e701a 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/investigation/utils/notes.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/investigation/utils/notes.ts @@ -7,12 +7,16 @@ import type SuperTest from 'supertest'; import { + DeleteNoteRequestBody, GetNotesResult, Note, PersistNoteRouteRequestBody, + PersistNoteRouteResponse, } from '@kbn/security-solution-plugin/common/api/timeline'; import { NOTE_URL } from '@kbn/security-solution-plugin/common/constants'; +import { type SuperTestResponse } from './types'; + /** * Deletes the first 100 notes (the getNotes endpoints is paginated and defaults to 10 is nothing is provided) * This works in ess, serverless and on the MKI environments as it avoids having to look at hidden indexes. @@ -24,12 +28,11 @@ export const deleteNotes = async (supertest: SuperTest.Agent): Promise => .set('elastic-api-version', '2023-10-31'); const { notes } = response.body as GetNotesResult; - await supertest - .delete(NOTE_URL) - .set('kbn-xsrf', 'true') - .send({ - noteIds: notes.map((note: Note) => note.noteId), - }); + const deleteNoteRequestBody: DeleteNoteRequestBody = { + noteIds: notes.map((note: Note) => note.noteId), + }; + + await supertest.delete(NOTE_URL).set('kbn-xsrf', 'true').send(deleteNoteRequestBody); }; /** @@ -47,26 +50,38 @@ export const createNote = async ( savedObjectId?: string; text: string; } -) => - await supertest - .patch(NOTE_URL) - .set('kbn-xsrf', 'true') - .send({ - note: { - eventId: note.documentId || '', - timelineId: note.savedObjectId || '', - note: note.text, - }, - } as PersistNoteRouteRequestBody); +): Promise> => { + const createNoteRequestBody: PersistNoteRouteRequestBody = { + note: { + eventId: note.documentId || '', + timelineId: note.savedObjectId || '', + note: note.text, + }, + }; + return await supertest.patch(NOTE_URL).set('kbn-xsrf', 'true').send(createNoteRequestBody); +}; -export const getNote = (supertest: SuperTest.Agent, noteId: string) => - supertest +export const getNote = async ( + supertest: SuperTest.Agent, + noteId: string +): Promise> => { + return await supertest .get(`${NOTE_URL}?noteId=${noteId}`) .set('kbn-xsrf', 'true') .set('elastic-api-version', '2023-10-31'); +}; -export const deleteNote = (supertest: SuperTest.Agent, noteId: string) => - supertest.delete(NOTE_URL).set('kbn-xsrf', 'true').set('elastic-api-version', '2023-10-31').send({ +export const deleteNote = async ( + supertest: SuperTest.Agent, + noteId: string +): Promise> => { + const deleteNoteRequestBody: DeleteNoteRequestBody = { noteId, - noteIds: null, - }); + }; + + return await supertest + .delete(NOTE_URL) + .set('kbn-xsrf', 'true') + .set('elastic-api-version', '2023-10-31') + .send(deleteNoteRequestBody); +}; diff --git a/x-pack/test/security_solution_api_integration/test_suites/investigation/utils/timelines.ts b/x-pack/test/security_solution_api_integration/test_suites/investigation/utils/timelines.ts index 3b63b1a7b72fb..41f32e134b4ac 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/investigation/utils/timelines.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/investigation/utils/timelines.ts @@ -8,9 +8,20 @@ import type SuperTest from 'supertest'; import { v4 as uuidv4 } from 'uuid'; import { + CopyTimelineRequestBody, + CopyTimelineResponse, + CreateTimelinesRequestBody, + CreateTimelinesResponse, + DeleteTimelinesRequestBody, GetTimelinesResponse, + GetTimelinesRequestQuery, + PatchTimelineRequestBody, + PersistFavoriteRouteRequestBody, + PersistFavoriteRouteResponse, + PersistPinnedEventRouteRequestBody, + PersistPinnedEventResponse, + ResolveTimelineResponse, SavedTimeline, - SavedTimelineWithSavedObjectId, TimelineTypeEnum, } from '@kbn/security-solution-plugin/common/api/timeline'; import { @@ -23,114 +34,177 @@ import { TIMELINE_PREPACKAGED_URL, } from '@kbn/security-solution-plugin/common/constants'; +import { type SuperTestResponse } from './types'; + /** * Deletes the first 100 timelines. * This works in ess, serverless and on the MKI environments as it avoids having to look at hidden indexes. */ -export const deleteTimelines = async (supertest: SuperTest.Agent): Promise => { +export const deleteTimelines = async ( + supertest: SuperTest.Agent +): Promise> => { const response = await getTimelines(supertest); - const { timeline: timelines } = response.body as GetTimelinesResponse; + const { timeline: timelines } = response.body; + const deleteRequestBody: DeleteTimelinesRequestBody = { + savedObjectIds: timelines.map((timeline) => timeline.savedObjectId), + }; - await supertest - .delete(TIMELINE_URL) - .set('kbn-xsrf', 'true') - .send({ - savedObjectIds: timelines.map( - (timeline: SavedTimelineWithSavedObjectId) => timeline.savedObjectId - ), - }); + return await supertest.delete(TIMELINE_URL).set('kbn-xsrf', 'true').send(deleteRequestBody); }; -export const deleteTimeline = (supertest: SuperTest.Agent, savedObjectId: string) => - supertest - .delete(TIMELINE_URL) - .set('kbn-xsrf', 'true') - .send({ - savedObjectIds: [savedObjectId], - }); +export const deleteTimeline = async ( + supertest: SuperTest.Agent, + savedObjectId: string +): Promise> => { + const deleteRequestBody: DeleteTimelinesRequestBody = { + savedObjectIds: [savedObjectId], + }; + + return await supertest.delete(TIMELINE_URL).set('kbn-xsrf', 'true').send(deleteRequestBody); +}; export const patchTimeline = ( supertest: SuperTest.Agent, timelineId: string, version: string, - timelineObj: unknown -) => - supertest.patch(TIMELINE_URL).set('kbn-xsrf', 'true').send({ + timelineObj: SavedTimeline +) => { + const patchRequestBody: PatchTimelineRequestBody = { timelineId, version, timeline: timelineObj, - }); + }; + return supertest.patch(TIMELINE_URL).set('kbn-xsrf', 'true').send(patchRequestBody); +}; -export const createBasicTimeline = async (supertest: SuperTest.Agent, titleToSaved: string) => - await supertest - .post(TIMELINE_URL) - .set('kbn-xsrf', 'true') - .send({ - timelineId: null, - version: null, - timeline: { - title: titleToSaved, - }, - }); +export const createBasicTimeline = async ( + supertest: SuperTest.Agent, + titleToSaved: string +): Promise> => { + const createTimelineBody: CreateTimelinesRequestBody = { + timelineId: null, + version: null, + timeline: { + title: titleToSaved, + }, + }; + return await supertest.post(TIMELINE_URL).set('kbn-xsrf', 'true').send(createTimelineBody); +}; export const createBasicTimelineTemplate = async ( supertest: SuperTest.Agent, titleToSaved: string -) => - await supertest +): Promise> => { + const createTimelineTemplateBody: CreateTimelinesRequestBody = { + timelineId: null, + version: null, + timeline: { + title: titleToSaved, + templateTimelineId: uuidv4(), + templateTimelineVersion: 1, + timelineType: TimelineTypeEnum.template, + }, + }; + return await supertest .post(TIMELINE_URL) .set('kbn-xsrf', 'true') - .send({ - timelineId: null, - version: null, - timeline: { - title: titleToSaved, - templateTimelineId: uuidv4(), - templateTimelineVersion: 1, - timelineType: TimelineTypeEnum.template, - }, - }); - -export const getTimelines = (supertest: SuperTest.Agent) => - supertest.get(TIMELINES_URL).set('kbn-xsrf', 'true').set('elastic-api-version', '2023-10-31'); - -export const resolveTimeline = (supertest: SuperTest.Agent, timelineId: string) => - supertest + .send(createTimelineTemplateBody); +}; + +export const getTimelines = async ( + supertest: SuperTest.Agent, + options?: GetTimelinesRequestQuery +): Promise> => { + let url: string = TIMELINES_URL; + + if (options) { + url += '?'; + for (const [key, value] of Object.entries(options)) { + url += `${key}=${value}&`; + } + } + + return await supertest.get(url).set('kbn-xsrf', 'true').set('elastic-api-version', '2023-10-31'); +}; + +export const resolveTimeline = async ( + supertest: SuperTest.Agent, + timelineId: string +): Promise> => + await supertest .get(`${TIMELINE_RESOLVE_URL}?id=${timelineId}`) .set('kbn-xsrf', 'true') .set('elastic-api-version', '2023-10-31'); -export const favoriteTimeline = (supertest: SuperTest.Agent, timelineId: string) => - supertest +export const favoriteTimeline = async ( + supertest: SuperTest.Agent, + timelineId: string +): Promise> => { + const favoriteTimelineRequestBody: PersistFavoriteRouteRequestBody = { + timelineId, + templateTimelineId: null, + templateTimelineVersion: null, + timelineType: null, + }; + return await supertest .patch(TIMELINE_FAVORITE_URL) .set('kbn-xsrf', 'true') .set('elastic-api-version', '2023-10-31') - .send({ - timelineId, - templateTimelineId: null, - templateTimelineVersion: null, - timelineType: null, - }); - -export const pinEvent = (supertest: SuperTest.Agent, timelineId: string, eventId: string) => - supertest + .send(favoriteTimelineRequestBody); +}; + +export const pinEvent = async ( + supertest: SuperTest.Agent, + timelineId: string, + eventId: string +): Promise> => { + const pinEventRequestBody: PersistPinnedEventRouteRequestBody = { + timelineId, + eventId, + }; + return await supertest + .patch(PINNED_EVENT_URL) + .set('kbn-xsrf', 'true') + .set('elastic-api-version', '2023-10-31') + .send(pinEventRequestBody); +}; + +export const unPinEvent = async ( + supertest: SuperTest.Agent, + timelineId: string, + eventId: string, + pinnedEventId: string +): Promise> => { + const pinEventRequestBody: PersistPinnedEventRouteRequestBody = { + timelineId, + eventId, + pinnedEventId, + }; + return await supertest .patch(PINNED_EVENT_URL) .set('kbn-xsrf', 'true') .set('elastic-api-version', '2023-10-31') - .send({ - timelineId, - eventId, - }); + .send(pinEventRequestBody); +}; -export const copyTimeline = ( +export const copyTimeline = async ( supertest: SuperTest.Agent, timelineId: string, timelineObj: SavedTimeline -) => - supertest.post(TIMELINE_COPY_URL).set('kbn-xsrf', 'true').set('elastic-api-version', '1').send({ +): Promise> => { + const copyTimelineRequestBody: CopyTimelineRequestBody = { timelineIdToCopy: timelineId, timeline: timelineObj, - }); + }; + return supertest + .post(TIMELINE_COPY_URL) + .set('kbn-xsrf', 'true') + .set('elastic-api-version', '1') + .send(copyTimelineRequestBody); +}; -export const installPrepackedTimelines = (supertest: SuperTest.Agent) => - supertest.post(TIMELINE_PREPACKAGED_URL).set('kbn-xsrf', 'true').send(); +export const installPrepackedTimelines = async ( + supertest: SuperTest.Agent +): Promise> => { + return await supertest.post(TIMELINE_PREPACKAGED_URL).set('kbn-xsrf', 'true').send(); +}; diff --git a/x-pack/test/kubernetes_security/common/ftr_provider_context.ts b/x-pack/test/security_solution_api_integration/test_suites/investigation/utils/types.ts similarity index 67% rename from x-pack/test/kubernetes_security/common/ftr_provider_context.ts rename to x-pack/test/security_solution_api_integration/test_suites/investigation/utils/types.ts index 2ea45b854eb28..ec79a3ccd4ee3 100644 --- a/x-pack/test/kubernetes_security/common/ftr_provider_context.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/investigation/utils/types.ts @@ -5,4 +5,6 @@ * 2.0. */ -export type { FtrProviderContext } from '../../api_integration/ftr_provider_context'; +import type SuperTest from 'supertest'; + +export type SuperTestResponse = Omit & { body: T }; diff --git a/x-pack/test/security_solution_cypress/config.ts b/x-pack/test/security_solution_cypress/config.ts index 6b10122213ca7..59219a368a30d 100644 --- a/x-pack/test/security_solution_cypress/config.ts +++ b/x-pack/test/security_solution_cypress/config.ts @@ -46,6 +46,7 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) { '--xpack.ruleRegistry.unsafe.legacyMultiTenancy.enabled=true', `--xpack.securitySolution.enableExperimental=${JSON.stringify([ 'alertSuppressionForSequenceEqlRuleEnabled', + 'assetInventoryUXEnabled', ])}`, // mock cloud to enable the guided onboarding tour in e2e tests '--xpack.cloud.id=test', diff --git a/x-pack/test/security_solution_cypress/cypress/README.md b/x-pack/test/security_solution_cypress/cypress/README.md index 89ab19343dbc7..63e8cda783709 100644 --- a/x-pack/test/security_solution_cypress/cypress/README.md +++ b/x-pack/test/security_solution_cypress/cypress/README.md @@ -153,6 +153,7 @@ If you belong to one of the teams listed in the table, please add new e2e specs | `e2e/detection_response/detection_engine` | Detection Engine | | `e2e/ai_assistant` | AI Assistant | | `e2e/entity_analytics` | Entity Analytics | +| `e2e/asset_inventory` | Cloud Security Posture | ### fixtures/ diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/asset_inventory/asset_inventory_page.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/asset_inventory/asset_inventory_page.cy.ts new file mode 100644 index 0000000000000..e85da8db0a3bf --- /dev/null +++ b/x-pack/test/security_solution_cypress/cypress/e2e/asset_inventory/asset_inventory_page.cy.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 { getDataTestSubjectSelector } from '../../helpers/common'; +import { login } from '../../tasks/login'; +import { visit } from '../../tasks/navigation'; +import { ASSET_INVENTORY_URL } from '../../urls/navigation'; + +const ALL_ASSETS_TITLE = getDataTestSubjectSelector('all-assets-title'); + +describe( + 'Asset Inventory page', + { + env: { + ftrConfig: { + kbnServerArgs: [ + `--xpack.securitySolution.enableExperimental=${JSON.stringify([ + 'assetInventoryUXEnabled', + ])}`, + ], + }, + }, + tags: ['@ess'], + }, + () => { + beforeEach(() => { + login(); + visit(ASSET_INVENTORY_URL); + }); + + it('should display All assets title', () => { + cy.get(ALL_ASSETS_TITLE).should('be.visible'); + }); + } +); diff --git a/x-pack/test/security_solution_cypress/cypress/urls/navigation.ts b/x-pack/test/security_solution_cypress/cypress/urls/navigation.ts index 6f6f4dc1a108a..e6640336c8bd1 100644 --- a/x-pack/test/security_solution_cypress/cypress/urls/navigation.ts +++ b/x-pack/test/security_solution_cypress/cypress/urls/navigation.ts @@ -82,3 +82,6 @@ export const FLEET_URL = '/app/fleet'; // Entity Analytics export const ENTITY_ANALYTICS_DASHBOARD_URL = '/app/security/entity_analytics'; + +// Asset Inventory +export const ASSET_INVENTORY_URL = '/app/security/asset_inventory'; diff --git a/x-pack/test/security_solution_cypress/package.json b/x-pack/test/security_solution_cypress/package.json index 6223b9b3bc624..ab7f8ef31e680 100644 --- a/x-pack/test/security_solution_cypress/package.json +++ b/x-pack/test/security_solution_cypress/package.json @@ -7,6 +7,7 @@ "scripts": { "cypress": "NODE_OPTIONS=--openssl-legacy-provider ../../../node_modules/.bin/cypress", "cypress:open:ess": "TZ=UTC NODE_OPTIONS=--openssl-legacy-provider node ../../solutions/security/plugins/security_solution/scripts/start_cypress_parallel open --spec './cypress/e2e/**/*.cy.ts' --config-file ../../test/security_solution_cypress/cypress/cypress.config.ts --ftr-config-file ../../test/security_solution_cypress/cli_config", + "cypress:asset_inventory:run:ess": "yarn cypress:ess --spec './cypress/e2e/asset_inventory/**/*.cy.ts'", "cypress:entity_analytics:run:ess": "yarn cypress:ess --spec './cypress/e2e/entity_analytics/**/*.cy.ts'", "cypress:run:cases:ess": "yarn cypress:ess --spec './cypress/e2e/explore/cases/*.cy.ts'", "cypress:ess": "TZ=UTC NODE_OPTIONS=--openssl-legacy-provider node ../../solutions/security/plugins/security_solution/scripts/start_cypress_parallel run --config-file ../../test/security_solution_cypress/cypress/cypress_ci.config.ts --ftr-config-file ../../test/security_solution_cypress/cli_config", diff --git a/x-pack/test/spaces_api_integration/security_and_spaces/apis/get_all.ts b/x-pack/test/spaces_api_integration/security_and_spaces/apis/get_all.ts index 4392eb86e6125..4b07043abdddd 100644 --- a/x-pack/test/spaces_api_integration/security_and_spaces/apis/get_all.ts +++ b/x-pack/test/spaces_api_integration/security_and_spaces/apis/get_all.ts @@ -21,7 +21,8 @@ export default function getAllSpacesTestSuite(context: FtrProviderContext) { // @ts-expect-error getAllTestSuiteFactory expects only DeploymentAgnosticFtrProviderContext const { getAllTest, expectRbacForbidden } = getAllTestSuiteFactory(context); - describe('get all', () => { + describe('get all', function () { + this.tags('skipFIPS'); [ { spaceId: SPACES.DEFAULT.spaceId, diff --git a/x-pack/test/tsconfig.json b/x-pack/test/tsconfig.json index c44db155280c4..8957548020096 100644 --- a/x-pack/test/tsconfig.json +++ b/x-pack/test/tsconfig.json @@ -92,7 +92,6 @@ "@kbn/safer-lodash-set", "@kbn/es-archiver", "@kbn/config-schema", - "@kbn/kubernetes-security-plugin", "@kbn/es-query", "@kbn/session-view-plugin", "@kbn/ml-is-populated-object", diff --git a/x-pack/test_serverless/api_integration/test_suites/observability/cases/get_all_user_actions.ts b/x-pack/test_serverless/api_integration/test_suites/observability/cases/get_all_user_actions.ts deleted file mode 100644 index 54221f23256c6..0000000000000 --- a/x-pack/test_serverless/api_integration/test_suites/observability/cases/get_all_user_actions.ts +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { CASE_USER_ACTIONS_URL } from '@kbn/cases-plugin/common/constants'; -import type { RoleCredentials } from '../../../../shared/services'; -import { FtrProviderContext } from '../../../ftr_provider_context'; - -export default ({ getService }: FtrProviderContext): void => { - const svlCases = getService('svlCases'); - const svlUserManager = getService('svlUserManager'); - const supertestWithoutAuth = getService('supertestWithoutAuth'); - const svlCommonApi = getService('svlCommonApi'); - - describe('get_all_user_actions', () => { - let roleAuthc: RoleCredentials; - - before(async () => { - roleAuthc = await svlUserManager.createM2mApiKeyWithRoleScope('admin'); - }); - - after(async () => { - await svlUserManager.invalidateM2mApiKeyWithRoleScope(roleAuthc); - }); - - afterEach(async () => { - await svlCases.api.deleteCases(); - }); - - it('should fetch the status correctly with internal request headers', async () => { - await supertestWithoutAuth - .get(CASE_USER_ACTIONS_URL) - .set(svlCommonApi.getInternalRequestHeader()) - .set(roleAuthc.apiKeyHeader) - .expect(200); - }); - - it('should not fetch the status correctly with no internal request headers', async () => { - await supertestWithoutAuth.get(CASE_USER_ACTIONS_URL).set(roleAuthc.apiKeyHeader).expect(400); - }); - }); -}; diff --git a/x-pack/test_serverless/api_integration/test_suites/observability/cases/get_status.ts b/x-pack/test_serverless/api_integration/test_suites/observability/cases/get_status.ts deleted file mode 100644 index 39527cb12f4ba..0000000000000 --- a/x-pack/test_serverless/api_integration/test_suites/observability/cases/get_status.ts +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { CASE_STATUS_URL } from '@kbn/cases-plugin/common/constants'; -import type { RoleCredentials } from '../../../../shared/services'; -import { FtrProviderContext } from '../../../ftr_provider_context'; - -export default ({ getService }: FtrProviderContext): void => { - const svlCases = getService('svlCases'); - const svlUserManager = getService('svlUserManager'); - const supertestWithoutAuth = getService('supertestWithoutAuth'); - const svlCommonApi = getService('svlCommonApi'); - - describe('get_status', () => { - let roleAuthc: RoleCredentials; - - before(async () => { - roleAuthc = await svlUserManager.createM2mApiKeyWithRoleScope('admin'); - }); - - after(async () => { - await svlUserManager.invalidateM2mApiKeyWithRoleScope(roleAuthc); - }); - - afterEach(async () => { - await svlCases.api.deleteCases(); - }); - - it('should fetch the status correctly with internal request headers', async () => { - await supertestWithoutAuth - .get(CASE_STATUS_URL) - .set(svlCommonApi.getInternalRequestHeader()) - .set(roleAuthc.apiKeyHeader) - .expect(200); - }); - - it('should not fetch the status correctly with no internal request headers', async () => { - await supertestWithoutAuth.get(CASE_STATUS_URL).set(roleAuthc.apiKeyHeader).expect(400); - }); - }); -}; diff --git a/x-pack/test_serverless/api_integration/test_suites/observability/cases/index.ts b/x-pack/test_serverless/api_integration/test_suites/observability/cases/index.ts index ce650c671e2dd..97e56b4220124 100644 --- a/x-pack/test_serverless/api_integration/test_suites/observability/cases/index.ts +++ b/x-pack/test_serverless/api_integration/test_suites/observability/cases/index.ts @@ -12,7 +12,5 @@ export default function ({ loadTestFile }: FtrProviderContext) { loadTestFile(require.resolve('./get_case')); loadTestFile(require.resolve('./find_cases')); loadTestFile(require.resolve('./post_case')); - loadTestFile(require.resolve('./get_status')); - loadTestFile(require.resolve('./get_all_user_actions')); }); } diff --git a/x-pack/test_serverless/shared/lib/security/kibana_roles/project_controller_security_roles.yml b/x-pack/test_serverless/shared/lib/security/kibana_roles/project_controller_security_roles.yml index 86c9d1acb57b0..8d8c716414f89 100644 --- a/x-pack/test_serverless/shared/lib/security/kibana_roles/project_controller_security_roles.yml +++ b/x-pack/test_serverless/shared/lib/security/kibana_roles/project_controller_security_roles.yml @@ -133,6 +133,7 @@ editor: - feature_securitySolutionTimeline.all - feature_securitySolutionNotes.all - feature_actions.read + - feature_actions.endpoint_security_execute - feature_builtInAlerts.all - feature_osquery.all - feature_discover.all @@ -320,6 +321,7 @@ t3_analyst: - feature_securitySolutionTimeline.all - feature_securitySolutionNotes.all - feature_actions.read + - feature_actions.endpoint_security_execute - feature_builtInAlerts.all - feature_osquery.all - feature_discover.all @@ -533,6 +535,7 @@ soc_manager: - feature_securitySolutionTimeline.all - feature_securitySolutionNotes.all - feature_actions.all + - feature_actions.endpoint_security_execute - feature_builtInAlerts.all - feature_osquery.all - feature_indexPatterns.all @@ -736,6 +739,7 @@ endpoint_operations_analyst: - feature_securitySolutionTimeline.all - feature_securitySolutionNotes.all - feature_actions.all + - feature_actions.endpoint_security_execute - feature_builtInAlerts.all - feature_osquery.all - feature_fleet.all diff --git a/yarn.lock b/yarn.lock index 39416aeeaf54c..36302fb03af87 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2011,11 +2011,11 @@ integrity sha512-cwwGvLGqvoaOZmoP5+i4v/rbW+rHkguvTehuZyM2p/xpmaNSdT2h3B7kHw33aiffv35t1XrYHIkdJSEkSEMJuA== "@bundled-es-modules/cookie@^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@bundled-es-modules/cookie/-/cookie-2.0.0.tgz#c3b82703969a61cf6a46e959a012b2c257f6b164" - integrity sha512-Or6YHg/kamKHpxULAdSqhGqnWFneIXu1NKvvfBBzKGwpVsYuFIQ5aBPHDnnoR3ghW1nvSkALd+EF9iMtY7Vjxw== + version "2.0.1" + resolved "https://registry.yarnpkg.com/@bundled-es-modules/cookie/-/cookie-2.0.1.tgz#b41376af6a06b3e32a15241d927b840a9b4de507" + integrity sha512-8o+5fRPLNbjbdGRRmJj3h6Hh1AQJf2dk3qQ/5ZFb+PXkRNiSoMGGUKlsgLfrxneb72axVJyIYji64E2+nNfYyw== dependencies: - cookie "^0.5.0" + cookie "^0.7.2" "@bundled-es-modules/statuses@^1.0.1": version "1.0.1" @@ -4640,6 +4640,10 @@ version "0.0.0" uid "" +"@kbn/core-http-rate-limiter-internal@link:src/core/packages/http/rate-limiter-internal": + version "0.0.0" + uid "" + "@kbn/core-http-request-handler-context-server-internal@link:src/core/packages/http/request-handler-context-server-internal": version "0.0.0" uid "" @@ -5608,6 +5612,10 @@ version "0.0.0" uid "" +"@kbn/esql-variables-types@link:src/platform/packages/shared/kbn-esql-variables-types": + version "0.0.0" + uid "" + "@kbn/esql@link:src/platform/plugins/shared/esql": version "0.0.0" uid "" @@ -6128,10 +6136,6 @@ version "0.0.0" uid "" -"@kbn/kubernetes-security-plugin@link:x-pack/solutions/security/plugins/kubernetes_security": - version "0.0.0" - uid "" - "@kbn/langchain@link:x-pack/platform/packages/shared/kbn-langchain": version "0.0.0" uid "" @@ -6508,7 +6512,7 @@ version "0.0.0" uid "" -"@kbn/observability-ai-assistant-plugin@link:x-pack/platform/plugins/shared/observability_solution/observability_ai_assistant": +"@kbn/observability-ai-assistant-plugin@link:x-pack/platform/plugins/shared/observability_ai_assistant": version "0.0.0" uid "" @@ -7064,7 +7068,7 @@ version "0.0.0" uid "" -"@kbn/search-shared-ui@link:x-pack/solutions/search/packages/search/shared_ui": +"@kbn/search-shared-ui@link:x-pack/solutions/search/packages/shared_ui": version "0.0.0" uid "" @@ -8543,7 +8547,7 @@ resolved "https://registry.yarnpkg.com/@msgpackr-extract/msgpackr-extract-win32-x64/-/msgpackr-extract-win32-x64-3.0.2.tgz#0f164b726869f71da3c594171df5ebc1c4b0a407" integrity sha512-O+6Gs8UeDbyFpbSh2CPEz/UOrrdWPTBYNblZK5CxxLisYt4kGX3Sc+czffFonyjiGSq3jWLwJS/CCJc7tBr4sQ== -"@mswjs/http-middleware@^0.10.1": +"@mswjs/http-middleware@0.10.1": version "0.10.1" resolved "https://registry.yarnpkg.com/@mswjs/http-middleware/-/http-middleware-0.10.1.tgz#7ff38c5398ba01efe98e16a0da24d612ffd69ccc" integrity sha512-I58RDHXzwKjMjaSO7aV7X0zUzbAvUEEDYsL9+I6Ro0zF5LgjnNdpZoMufG/WoYEenhDCgv7K+HMpLxGuhlfjKA== @@ -11299,10 +11303,10 @@ resolved "https://registry.yarnpkg.com/@types/braces/-/braces-3.0.0.tgz#7da1c0d44ff1c7eb660a36ec078ea61ba7eb42cb" integrity sha512-TbH79tcyi9FHwbyboOKeRachRq63mSuWYXOflsNO9ZyE5ClQ/JaozNKl+aWUq87qPNsXasXxi2AbgfwIJ+8GQw== -"@types/byte-size@^8.1.0": - version "8.1.0" - resolved "https://registry.yarnpkg.com/@types/byte-size/-/byte-size-8.1.0.tgz#013a3995d1ff2d85ad27da0801029f13328bd91b" - integrity sha512-LCIlZh8vyx+I2fgRycE1D34c33QDppYY6quBYYoaOpQ1nGhJ/avSP2VlrAefVotjJxgSk6WkKo0rTcCJwGG7vA== +"@types/byte-size@^8.1.2": + version "8.1.2" + resolved "https://registry.yarnpkg.com/@types/byte-size/-/byte-size-8.1.2.tgz#abb3d70ab62c400d8753bed1ff2aa315ef9ff7f5" + integrity sha512-jGyVzYu6avI8yuqQCNTZd65tzI8HZrLjKX9sdMqZrGWVlNChu0rf6p368oVEDCYJe5BMx2Ov04tD1wqtgTwGSA== "@types/cacheable-request@^6.0.1": version "6.0.1" @@ -13158,7 +13162,7 @@ resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d" integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== -"@xyflow/react@^12.4.0": +"@xyflow/react@^12.4.1": version "12.4.2" resolved "https://registry.yarnpkg.com/@xyflow/react/-/react-12.4.2.tgz#669ab18923d93a8d8fb526241a2affc0d50abf9d" integrity sha512-AFJKVc/fCPtgSOnRst3xdYJwiEcUN9lDY7EO/YiRvFHYCJGgfzg+jpvZjkTOnBLGyrMJre9378pRxAc3fsR06A== @@ -14836,10 +14840,10 @@ builtin-status-codes@^3.0.0: resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" integrity sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug= -byte-size@^8.1.0: - version "8.1.0" - resolved "https://registry.yarnpkg.com/byte-size/-/byte-size-8.1.0.tgz#6353d0bc14ab7a69abcefbf11f8db0145a862cb5" - integrity sha512-FkgMTAg44I0JtEaUAvuZTtU2a2YDmBRbQxdsQNSMtLCjhG0hMcF5b1IMN9UjSCJaU4nvlj/GER7B9sI4nKdCgA== +byte-size@^9.0.1: + version "9.0.1" + resolved "https://registry.yarnpkg.com/byte-size/-/byte-size-9.0.1.tgz#7014b9f0e11ea732a8f2c21bef1cb8a78c6c55ff" + integrity sha512-YLe9x3rabBrcI0cueCdLS2l5ONUKywcRpTs02B8KP9/Cimhj7o3ZccGrPnRvcbyHMbb7W79/3MUJl7iGgTXKEw== bytes@3.0.0: version "3.0.0" @@ -15947,12 +15951,7 @@ cookie@0.7.1: resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.7.1.tgz#2f73c42142d5d5cf71310a74fc4ae61670e5dbc9" integrity sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w== -cookie@^0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b" - integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw== - -cookie@^0.7.1: +cookie@^0.7.1, cookie@^0.7.2: version "0.7.2" resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.7.2.tgz#556369c472a2ba910f2979891b526b3436237ed7" integrity sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w== @@ -24807,7 +24806,7 @@ msgpackr@^1.9.9: optionalDependencies: msgpackr-extract "^3.0.2" -msw@^2.4.12: +msw@~2.5.2: version "2.5.2" resolved "https://registry.yarnpkg.com/msw/-/msw-2.5.2.tgz#dfce10b68dbabc2d5dafeb6d7fb82c3c7073a4d1" integrity sha512-eBsFgU30NYtrfC62XzS1rdAzFK+Br0zKU4ORqD9Qliq86362DWZyPiD6FLfMgy0Ktik83DPTXmqPMz2bqwmJdA== @@ -33621,10 +33620,10 @@ xtend@~2.1.1: dependencies: object-keys "~0.4.0" -xterm@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/xterm/-/xterm-5.1.0.tgz#3e160d60e6801c864b55adf19171c49d2ff2b4fc" - integrity sha512-LovENH4WDzpwynj+OTkLyZgJPeDom9Gra4DMlGAgz6pZhIDCQ+YuO7yfwanY+gVbn/mmZIStNOnVRU/ikQuAEQ== +xterm@^5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/xterm/-/xterm-5.3.0.tgz#867daf9cc826f3d45b5377320aabd996cb0fce46" + integrity sha512-8QqjlekLUFTrU6x7xck1MsPzPA571K5zNqWm0M0oroYEWVOptZ0+ubQSkQ3uxIEhcIHRujJy6emDWX4A7qyFzg== y18n@^3.2.0: version "3.2.2"